⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rattle.tcl

📁 MD中rattle 算法
💻 TCL
字号:
proc rattle {type args} {
#Initial check of type value before other errors can occur
    if {$type != "off" && $type != "bonds" && $type != "angles" && $type != "water"} {
	error "rattle: unknown type \"$type\": must be `bonds', `angles', `water' or `off'"
    }


    #set system_h
    database handle system_h System.

    #reset the resetEnergyExpression and chargeChanged flags under the
    #Global table in the system database
    System_SetGlobal resetEnergyExpression 1
    System_SetGlobal chargeChanged 1

    set rattleMsg ""
    vector bl {}
    vector av {}
#Check/perform the `off' function
    database handle dbh {} dbn
    object dbn cast int

    $l = [llength $args]
    if {$type == "off"} {
	if $l {
	    error "rattle off: extra arguments given"
	}
	rattleSystem off [object dbn]
	return
    }
    rattleSystem on [object dbn]

#Check/grab the tolerance arguments - the optional values are considered further on
    if {[lindex $args 0] == "-tolerance"} {
	if {$l < 2} {
	    error "rattle: with -tolerance: no tolerance value specified"
	}
	vector tol [lindex $args 1]
	if {[object tol info type] != "double"} {
	    error "rattle: tolerance value must be a vector of reals"
	}
	incr l -2
	set args [lrange $args 2 end]
    } else {
	vector tol 1.0e-7
    }
#Check/set up water parameters
    if {$type == "water"} {
    #Check/set up water ff type
	global env
	if {[lindex $args 0] == "-waterType"} {
	    if {$l < 2} {
		error "rattle water: option value not specified for `-waterType'"
	    }
	    set wtype [string toupper [lindex $args 1]]
	    incr l -2
	    set args [lrange $args 2 end]
	} else {
	    set wtype SPC
	}
	if {[regexp -nocase esff $env(FORCEFIELD)]} {
	    if {$wtype != "CURRENT"} {
		error "rattle: ESFF forcefield does not support SPC or TIP3P waters"
	    }
	}
    #Check for tolerance again in case this comes now
	if {[lindex $args 0] == "-tolerance"} {
	    if {$l < 2} {
		error "rattle: with -tolerance: no tolerance value specified"
	    }
	    vector tol [lindex $args 1]
	    if {[object tol info type] != "double"} {
		error "rattle: tolerance value must be a vector of reals"
	    }
	    incr l -2
	    set args [lrange $args 2 end]
	}
    #Check no more arguments provided - waters is all or nothing
	if $l {
	    error "rattle water: too many arguments provided: no water subsets may be specified"
	}
    #Grab target atom sets - must be waters
	$dbh select -nosubdivide {WTR OHH} Monomer.Type waters
	if ![object waters info nItems] {
	    echo "Warning: rattle: system does not contain water molecules (monomer type \"WTR\" or \"OHH\")"
	    return
	}
	$dbh select -nosubdivide $waters Atom.Monomer waters
	$dbh select -nosubdivide -regexp ^O.*   Atom.Name waterO  $waters
	$dbh select -nosubdivide -regexp ^H.*1$ Atom.Name waterH1 $waters
	$dbh select -nosubdivide -regexp ^H.*2$ Atom.Name waterH2 $waters
    #Check/setup water ff parameters and geometries
	if {$wtype == "SPC"} {
	    vector bl 1.00
	    vector wc -0.820
	    molGeom set distance $bl $waterO $waterH1
	    molGeom set distance $bl $waterO $waterH2
	    molGeom set angle 109.47 $waterH1 $waterO $waterH2
	    $dbh set ospc Atom.Type $waterO
	    $dbh set hspc Atom.Type $waterH1
	    $dbh set hspc Atom.Type $waterH2
	    $dbh set $wc Atom.Charge $waterO
	    $dbh set 0.410 Atom.Charge $waterH1
	    $dbh set 0.410 Atom.Charge $waterH2
	} elseif {$wtype == "TIP3P"} {
	    vector bl 0.957
	    vector wc -0.834
	    molGeom set distance $bl $waterO $waterH1
	    molGeom set distance $bl $waterO $waterH2
	    molGeom set angle 104.52 $waterH1 $waterO $waterH2
	    $dbh set otip Atom.Type $waterO
	    $dbh set htip Atom.Type $waterH1
	    $dbh set htip Atom.Type $waterH2
	    $dbh set $wc Atom.Charge $waterO
	    $dbh set 0.417 Atom.Charge $waterH1
	    $dbh set 0.417 Atom.Charge $waterH2
	} elseif {$wtype != "CURRENT"} {
	    error "rattle water: unknown forcefield specification \"$wtype\": must be SPC, TIP3P or CURRENT"
	}
    #Put OH distance into the Rattle table
	select atoms1 $waterH1
	object atoms1 append $waterH2
	select atoms2 $waterO
	object atoms2 append $waterO
	if {$wtype == "CURRENT"} {
	    molGeom get distance bl $atoms1 $atoms2
	}
	addRattle $atoms1 $atoms2 $bl $tol
    #Set up Atom lists for putting into the Rattle table for atoms adjacent to angle
	set atoms1 $waterH1
	set atoms2 $waterH2
	vector bl ""
    } elseif {$type == "bonds" } {
#Check/set up bond values and atom sets
    #Check for value specification
	if {[lindex $args 0] == "-bondLength"} {
	    if {$l < 2} {
		error "rattle bonds: option value not specified for `-bondLength'"
	    }
	    vector bl [lindex $args 1]
	    incr l -2
	    set args [lrange $args 2 end]
	}
    #Check for tolerance again in case this comes now
	if {[lindex $args 0] == "-tolerance"} {
	    if {$l < 2} {
		error "rattle: with -tolerance: no tolerance value specified"
	    }
	    vector tol [lindex $args 1]
	    if {[object tol info type] != "double"} {
		error "rattle: tolerance value must be a vector of reals"
	    }
	    incr l -2
	    set args [lrange $args 2 end]
	}
	switch $l {
	0 {
	    $dbh select Water Molecule.Type waters
	    if [object waters info nItems] {
		select nWater "!(*<Type>Water):*:Atom;*"
		if [object nWater info nItems] {
		    getBondAtoms atoms1 atoms2 $nWater
		    set rattleMsg "constrained all bonds for all non-water molecules"
		} else {
		    getBondAtoms atoms1 atoms2
		    set rattleMsg "constrained all bonds for all water molecules"
		}
	    } else {
		getBondAtoms atoms1 atoms2
		set rattleMsg "constrained all bonds for all molecules"
	    }
	  }
	1 {
	    set subtype [string tolower [subset get subs [lindex $args 0]]]
	    if {$subtype != "distance"} {
		error "rattle bonds: with 1 subset specification: must be a `distance' subset"
	    }
	    $dbh get atoms1 Distance.Point1 $subs
	    $dbh get atoms2 Distance.Point2 $subs
	  }
	2 {
	    select atoms1 [lindex $args 0] ; $natoms1 = [object atoms1 info nItems]
	    select atoms2 [lindex $args 1] ; $natoms2 = [object atoms2 info nItems]
	    if {$natoms1 != $natoms2} {
		error "rattle bonds: atom lists must specify the same number of items"
	    }
	  }
	default {error "rattle bonds: too many atom specifications provided"}
	}
    } elseif {$type == "angles"} {
#Check/set up angle values and atom sets
    #Check for value specification
	if {[lindex $args 0] == "-angleValue"} {
	    if {$l < 2} {
		error "rattle angles: option value not specified for `-angleValue'"
	    }
	    vector av [lindex $args 1]
	    incr l -2
	    set args [lrange $args 2 end]
	}
    #Check for tolerance again in case this comes now
	if {[lindex $args 0] == "-tolerance"} {
	    if {$l < 2} {
		error "rattle: with -tolerance: no tolerance value specified"
	    }
	    vector tol [lindex $args 1]
	    if {[object tol info type] != "double"} {
		error "rattle: tolerance value must be a vector of reals"
	    }
	    incr l -2
	    set args [lrange $args 2 end]
	}
	switch $l {
	0 {
	    $dbh select Water Molecule.Type waters
	    if [object waters info nItems] {
		select nWater "!(*<Type>Water):*:Atom;*"
		if [object nWater info nItems] {
		    getAngleAtoms atoms1 atoms2 atoms3 $nWater
		    set rattleMsg "constrained all angles for all non-water molecules"
		} else {
		    getAngleAtoms atoms1 atoms2 atoms3
		    set rattleMsg "constrained all angles for all water molecules"
		}
	    } else {
		getAngleAtoms atoms1 atoms2 atoms3
		set rattleMsg "constrained all angles for all molecules"
	    }
	  }
	1 {
	    set subtype [string tolower [subset get subs [lindex $args 0]]]
	    if {$subtype != "angle"} {
		error "rattle angles: with 1 subset specification: must be an `angle' subset"
	    }
	    $dbh get atoms1 Angle.Point1 $subs
	    $dbh get atoms2 Angle.Point2 $subs
	    $dbh get atoms3 Angle.Point3 $subs
	  }
	3 {
	    select atoms1 [lindex $args 0] ; $natoms1 = [object atoms1 info nItems]
	    select atoms2 [lindex $args 1] ; $natoms2 = [object atoms2 info nItems]
	    select atoms3 [lindex $args 2] ; $natoms3 = [object atoms3 info nItems]
	    if {$natoms1 != $natoms2 || $natoms1 != $natoms3} {
		error "rattle angles: atom lists must specify the same number of items"
	    }
	  }
	default {error "rattle angles: incorrect number of atom specifications provided"}
	}
    #Fix specified angle values
	if [object av info nItems] {
	    if [catch {molGeom set angle $av $atoms1 $atoms2 $atoms3} msg] {
		set msg [string range $msg 14 end]
		error "rattle angles: $msg"
	    }
	}
	set atoms2 $atoms3
    }
#Fix/get specified bonds lengths
    if {[object bl info nItems] && $type == "bonds"} {
	if [catch {molGeom set distance $bl $atoms1 $atoms2} msg] {
	    if {[string first "directly bonded" $msg] || [string first "ring structure" $msg]} {
		set msg [string range $msg 14 end]
		echo Warning: rattle bonds: unable to set geometry: $msg
	    } else {
		error "rattle bonds: $msg"
	    }
	}
    } else {
	molGeom get distance bl $atoms1 $atoms2
    }
#Finally fill in the Rattle table
    addRattle $atoms1 $atoms2 $bl $tol
    if {$rattleMsg != ""} {echo "rattle: $rattleMsg"}
}
proc addRattle {atms1 atms2 bondLength tolerance} {
#This procedure assumes that atoms1 & atoms2 are atom objects
#and that bondLength and tolerance are scalar vectors
#Select (copy) the atom lists and check/create the Rattle table
    select atoms1 $atms1   ; $nat1 = [object atoms1 info nItems]
    select atoms2 $atms2
    vector bdl $bondLength ; $nbdl = [object bdl info nItems]
    vector tol $tolerance  ; $ntol = [object tol info nItems]
    if {$nbdl != 1 && $nbdl != $nat1} {
	error "rattle: constraint value must contain 1 or $nat1 values"
    }
    if {$ntol != 1 && $ntol != $nat1} {
	error "rattle: torelance value must contain 1 or $nat1 values"
    }
    database handle dbh $atoms1
    if !{[$dbh exists Rattle]} {
	$dbh createTable Rattle
	$dbh createColumn -nodeleteref Rattle.Atom-1 reference Atom
	$dbh createColumn -nodeleteref Rattle.Atom-2 reference Atom
	$dbh createColumn Rattle.BondLength double 
	$dbh createColumn Rattle.Tolerance double 1.0e-7
	$dbh create [object atoms1 info nItems] Rattle newRows
	$dbh set $atoms1 Rattle.Atom-1 $newRows
	$dbh set $atoms2 Rattle.Atom-2 $newRows
	$dbh set $bdl Rattle.BondLength $newRows
	$dbh set $tol Rattle.Tolerance $newRows
	return
    }
#Filter out all the atom pairs already in the table...
#First get all rows for which atoms1 & atoms2 pairs are in
    $dbh select $atoms1 Rattle.Atom-1 a1
    $dbh select -itempergroup $atoms2 Rattle.Atom-2 a2 $a1
    if [object a2 info nItems] {
    #Use the grouping on a2 to filter the initial atom-pair lists
	object a2 group -size f4
    #Apply filters to bondLength and fill in for old row values
	if {[object bdl info nItems] == 1} {
	    $dbh set $bdl Rattle.BondLength $a2
	} else {
	    object bl get $bdl
	    object bl filter $f4
	    $dbh set $bl Rattle.BondLength $a2
	}
    #Apply filters to tolerance and fill in for old row values
	if {[object tol info nItems] == 1} {
	    $dbh set $tol Rattle.Tolerance $a2
	} else {
	    object tv get $tol
	    object tv filter $f4
	    $dbh set $tv Rattle.Tolerance $a2
	}
    #Get all new atom pairs
	object f4 cast boolean
	vector f5 not $f4
	object atoms1 filter $f5
	object atoms2 filter $f5
    #Adjust tol and bdl
	if {[object bdl info nItems] > 1} {
	    object bdl filter $f5
	}
	if {[object tol info nItems] > 1} {
	    object tol filter $f5
	}
    }
#Filter out all the atom pairs already in the table in the oposite order
    if [object atoms2 info nItems] {
	$dbh select $atoms2 Rattle.Atom-1 a1
	$dbh select -itempergroup $atoms1 Rattle.Atom-2 a2 $a1
    } else {
	vector a2 ""
    }
    if [object a2 info nItems] {
    #Use the grouping on a2 to filter the initial atom-pair lists
	object a2 group -size f4
    #Apply filters to bondLength and fill in for old row values
	if {[object bdl info nItems] == 1} {
	    $dbh set $bdl Rattle.BondLength $a2
	} else {
	    object bl get $bdl
	    object bl filter $f4
	    $dbh set $bl Rattle.BondLength $a2
	}
    #Apply filters to tolerance and fill in for old row values
	if {[object tol info nItems] == 1} {
	    $dbh set $tol Rattle.Tolerance $a2
	} else {
	    object tv get $tol
	    object tv filter $f4
	    $dbh set $tv Rattle.Tolerance $a2
	}
    #Get all new atom pairs
	object f4 cast boolean
	vector f5 not $f4
	object atoms1 filter $f5
	object atoms2 filter $f5
    #Adjust tol and bdl
	if {[object bdl info nItems] > 1} {
	    object bdl filter $f5
	}
	if {[object tol info nItems] > 1} {
	    object tol filter $f5
	}
    }
#Create the new Rattle rows and fill in
    if [object atoms1 info nItems] {
	$dbh create [object atoms1 info nItems] Rattle newRows
	$dbh set $atoms1 Rattle.Atom-1 $newRows
	$dbh set $atoms2 Rattle.Atom-2 $newRows
	$dbh set $bdl Rattle.BondLength $newRows
	$dbh set $tol Rattle.Tolerance $newRows
    }
}
proc rattleSystem {op dbn} {
    global RattleSystemData
    if [catch {set RattleSystemData($dbn)}] {
	if {$op == "off"} {return} elseif {$op != "on"} {
	    error "rattleSystem: arg#1 <op>: operation must be `on' or `off'"
	}
	database handle dbh #$dbn
    #Mark Molecule.Type column for all water molecules
	$dbh select -nosubdivide {WTR OHH} Monomer.Type waters
	if [object waters info nItems] {
	    $dbh get water Monomer.Molecule $waters
	    $dbh set Water Molecule.Type $water
	    object water range $waters 0
	    $dbh select $water Atom.Monomer watms
	} else {
	    set RattleSystemData($dbn) 1
	    return
	}
    #Store to global array of database original Atom charge and type values for water atoms
	$dbh get ch Atom.Charge $watms
	$dbh get at Atom.Type $watms
	set RattleSystemData($dbn) "[object ch] [object at]"
    } elseif {$op == "on"} {return} elseif {$op == "off"} {
    #Repair atom table to original form
	set x $RattleSystemData($dbn)
	database handle dbh #$dbn
	if ![catch {select aO "*<Type>Water:*:O*"}] {
	    select aH1 "*<Type>Water:*:H*1"
	    select aH2 "*<Type>Water:*:H*2"
	    $dbh set [lindex $x 0] Atom.Charge $aO
	    $dbh set [lindex $x 1] Atom.Charge $aH1
	    $dbh set [lindex $x 2] Atom.Charge $aH2
	    $dbh set [lindex $x 3] Atom.Type $aO
	    $dbh set [lindex $x 4] Atom.Type $aH1
	    $dbh set [lindex $x 5] Atom.Type $aH2
	}
    #Unset the database encountered variable (leaving Molecule as is)
	unset RattleSystemData($dbn)
	$dbh delete Rattle
    } else {
	error "rattleSystem: arg#1 <op>: operation must be `on' or `off'"
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -