While the tclForces interface described above is very flexible, it is only efficient for applying forces to a small number of pre-selected atoms. Applying forces individually to a potentially large number of atoms, such as applying boundary conditions, is much more efficient with the tclBC facility described below.
The script provided in tclBCScript and the calcforces procedure it defines are executed in multiple Tcl interpreters, one for every processor that owns patches. These tclBC interpreters do not share state with the Tcl interpreter used for tclForces or config file parsing. The calcforces procedure is passed as arguments the current timestep, a ``unique'' flag which is non-zero for exactly one Tcl interpreter in the simulation (that on the processor of patch zero), and any arguments provided to the most recent tclBCArgs option. The ``unique'' flag is useful to limit printing of messages, since the command is invoked on multiple processors.
The print, vecadd, vecsub, vecscale, getbond, getangle, getdihedral, anglegrad, and dihedralgrad commands described under tclForces are available at all times.
The wrapmode <mode> command, available in the tclBCScript or the calcforces procedure, determines how coordinates obtained in the calcforces procedure are wrapped around periodic boundaries. The options are:
The following commands are available from within the calcforces procedure:
As an example, these spherical boundary condition forces:
sphericalBC on sphericalBCcenter 0.0,0.0,0.0 sphericalBCr1 48 sphericalBCk1 10 sphericalBCexp1 2
Are replicated in the following script:
tclBC on tclBCScript { proc veclen2 {v1} { foreach {x1 y1 z1} $v1 { break } return [expr $x1*$x1 + $y1*$y1 + $z1*$z1] } # wrapmode input # wrapmode cell # wrapmode nearest # wrapmode patch ;# the default proc calcforces {step unique R K} { if { $step % 20 == 0 } { cleardrops # if $unique { print "clearing dropped atom list at step $step" } } set R [expr 1.*$R] set R2 [expr $R*$R] set tol 2.0 set cut2 [expr ($R-$tol)*($R-$tol)] while {[nextatom]} { # addenergy 1 ; # monitor how many atoms are checked set rvec [getcoord] set r2 [veclen2 $rvec] if { $r2 < $cut2 } { dropatom continue } if { $r2 > $R2 } { # addenergy 1 ; # monitor how many atoms are affected set r [expr sqrt($r2)] addenergy [expr $K*($r - $R)*($r - $R)] addforce [vecscale $rvec [expr -2.*$K*($r-$R)/$r]] } } } } tclBCArgs {48.0 10.0}