| 1 | #!/bin/sh | 
|---|
| 2 | # | 
|---|
| 3 | # Performs an molecular dynamics simulation with the BOSSANOVA method | 
|---|
| 4 |  | 
|---|
| 5 | MPIRUN="/opt/packages/mpichgm-1.2.7..15/bin/mpirun.ch_gm" | 
|---|
| 6 | #MPIRUN="/usr/bin/mpirun.mpich" | 
|---|
| 7 | exec_prefix="@prefix@" | 
|---|
| 8 | MOLECUILDER="@bindir@/molecuilder" | 
|---|
| 9 | JOINER="@bindir@/joiner" | 
|---|
| 10 | PCP="@bindir@/pcp" | 
|---|
| 11 |  | 
|---|
| 12 | function check { | 
|---|
| 13 | if [ ! $? -eq 0 ]; then | 
|---|
| 14 | echo "An error occured." | tee -a dynamic.log | 
|---|
| 15 | exit 1; | 
|---|
| 16 | fi | 
|---|
| 17 | } | 
|---|
| 18 |  | 
|---|
| 19 | function RunSim { | 
|---|
| 20 | # 1 is the config file | 
|---|
| 21 | # 2 is the number of nodes | 
|---|
| 22 | # 3 further command line option | 
|---|
| 23 | # 4 and argument | 
|---|
| 24 | # set the maximum number of nodes | 
|---|
| 25 | MaxNodes=`cat $2 | awk 'END{print NR}'` | 
|---|
| 26 | gamma=`grep ProcPEGamma $1 | awk -F"\t" {'print $2'}` | 
|---|
| 27 | psi=`grep ProcPEPsi $1 | awk -F"\t" {'print $2'}` | 
|---|
| 28 | let nodes=$gamma*$psi | 
|---|
| 29 | if [ $nodes -gt $MaxNodes ]; then | 
|---|
| 30 | echo "Process $1 needs too many nodes! Breaking." | tee -a dynamic.log | 
|---|
| 31 | exit 1 | 
|---|
| 32 | fi | 
|---|
| 33 | ${MPIRUN} -machinefile $2 -np $nodes ${PCP} -a 86000 $3 $4 $1 2>/dev/null >/dev/null | 
|---|
| 34 | check | 
|---|
| 35 | } | 
|---|
| 36 |  | 
|---|
| 37 | function MultiRunSim { | 
|---|
| 38 | # 1 is config file | 
|---|
| 39 | # 2 is the number of groups | 
|---|
| 40 |  | 
|---|
| 41 | # find the next free proc group | 
|---|
| 42 | DIR=`dirname $1` | 
|---|
| 43 | started=0 | 
|---|
| 44 | while [ $started -eq 0 ]; do | 
|---|
| 45 | groupnr=1 | 
|---|
| 46 | while [ $groupnr -le $2 ]; do | 
|---|
| 47 | if [ ! -e "${DIR}/ProcRuns${groupnr}" ]; then | 
|---|
| 48 | MaxNodes=`cat ${DIR}/ProcGroup${groupnr} | awk 'END{print NR}'` | 
|---|
| 49 | gamma=`grep ProcPEGamma $1 | awk -F"\t" {'print $2'}` | 
|---|
| 50 | psi=`grep ProcPEPsi $1 | awk -F"\t" {'print $2'}` | 
|---|
| 51 | let nodes=$gamma*$psi | 
|---|
| 52 | if [ $nodes -gt $MaxNodes ]; then | 
|---|
| 53 | echo "Process $1 needs too many nodes! Breaking." | tee -a dynamic.log | 
|---|
| 54 | exit 1 | 
|---|
| 55 | fi | 
|---|
| 56 | echo "touch ${DIR}/ProcRuns${groupnr}" >"${DIR}/ProcBatch${groupnr}" | 
|---|
| 57 | echo "${MPIRUN} -machinefile ${DIR}/ProcGroup${groupnr} -np $nodes ${PCP} -a 86000 $1 2>/dev/null >/dev/null" >>"${DIR}/ProcBatch${groupnr}" | 
|---|
| 58 | echo "rm -f ${DIR}/ProcRuns${groupnr}" >>"${DIR}/ProcBatch${groupnr}" | 
|---|
| 59 | /bin/sh "${DIR}/ProcBatch${groupnr}" & | 
|---|
| 60 | started=1 | 
|---|
| 61 | let groupnr=${2}+1 | 
|---|
| 62 | else | 
|---|
| 63 | let groupnr=$groupnr+1 | 
|---|
| 64 | fi | 
|---|
| 65 | done | 
|---|
| 66 | # wait a few seconds | 
|---|
| 67 | sleep 5 | 
|---|
| 68 | done | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | #PBS_NODEFILE="${DIR}/machines" | 
|---|
| 72 |  | 
|---|
| 73 | # get command line options | 
|---|
| 74 | if [ -z $4 ]; then | 
|---|
| 75 | echo "Usage: $0 <config file> <Order> <max. bond distance> <MaxNodes> [MaxMDsteps]" | 
|---|
| 76 | echo -e "\t<config file> the pcp config file of the total molecule" | 
|---|
| 77 | echo -e "\t<Order> the highest bond order (i.e. the cutoff number in ANOVA series expansion)" | 
|---|
| 78 | echo -e "\t<max. bond distance> maximum distance to look for bonds (bonds are associated by element covalent radii criterion)" | 
|---|
| 79 | echo -e "\t[MaxMDSteps] overrides given MaxOuterStep in config file" | 
|---|
| 80 | exit 1; | 
|---|
| 81 | else | 
|---|
| 82 | arg=$1 | 
|---|
| 83 | mainname=`grep mainname $arg | awk -F"\t" {'print $2'}` | 
|---|
| 84 | order=$2 | 
|---|
| 85 | distance=$3 | 
|---|
| 86 | MaxNodes=$4 | 
|---|
| 87 | if [ -z $5 ]; then | 
|---|
| 88 | MaxSteps=`grep MaxOuterStep $arg | awk -F"\t" {'print $2'}` | 
|---|
| 89 | else | 
|---|
| 90 | MaxSteps=$5 | 
|---|
| 91 | fi | 
|---|
| 92 | echo "Going to run for a total of $MaxSteps steps, bond order $order and maximum distance $distance of config file $arg with a total of $MaxNodes nodes." | tee -a dynamic.log | 
|---|
| 93 | fi | 
|---|
| 94 |  | 
|---|
| 95 |  | 
|---|
| 96 | # get the directory | 
|---|
| 97 | DIR=`dirname $arg` | 
|---|
| 98 | if [ -z "`grep $DIR $arg`" ]; then | 
|---|
| 99 | echo "Cannot find the directory $DIR in the config file." | tee -a dynamic.log | 
|---|
| 100 | exit 1; | 
|---|
| 101 | else | 
|---|
| 102 | echo "Using $DIR as directory." | tee -a dynamic.log | 
|---|
| 103 | fi | 
|---|
| 104 |  | 
|---|
| 105 |  | 
|---|
| 106 | # delete old processor group files | 
|---|
| 107 | rm ${DIR}/ProcGroup* -f | 
|---|
| 108 | rm ${DIR}/ProcRuns* -f | 
|---|
| 109 | rm ${DIR}/ProcBatch* -f | 
|---|
| 110 |  | 
|---|
| 111 | # put nodes into groups | 
|---|
| 112 | gamma=`grep ProcPEGamma $arg | awk -F"\t" {'print $2'}` | 
|---|
| 113 | psi=`grep ProcPEPsi $arg | awk -F"\t" {'print $2'}` | 
|---|
| 114 | let nodes=$gamma*$psi | 
|---|
| 115 | let divisor=$MaxNodes/$nodes | 
|---|
| 116 | echo "Using $divisor processor groups." | tee -a dynamic.log | 
|---|
| 117 | nodenr=0 | 
|---|
| 118 | groupnr=1 | 
|---|
| 119 | for node in `cat <$PBS_NODEFILE`; do | 
|---|
| 120 | let nodenr=$nodenr+1 | 
|---|
| 121 | #echo "Current node $nodenr is $node." | tee -a dynamic.log | 
|---|
| 122 | let currentgrouplimit=$groupnr*$nodes | 
|---|
| 123 | if [ $currentgrouplimit -lt $nodenr ]; then | 
|---|
| 124 | let groupnr=$groupnr+1 | 
|---|
| 125 | fi | 
|---|
| 126 | #echo "Putting into group $groupnr." | tee -a dynamic.log | 
|---|
| 127 | echo "$node" >>"${DIR}/ProcGroup${groupnr}" | 
|---|
| 128 | done | 
|---|
| 129 | i=0 | 
|---|
| 130 | while [ $i -lt $groupnr ]; do | 
|---|
| 131 | let i=$i+1 | 
|---|
| 132 | echo "Group nr. $i" | tee -a dynamic.log | 
|---|
| 133 | echo "===========" | tee -a dynamic.log | 
|---|
| 134 | cat <"${DIR}/ProcGroup${i}" | 
|---|
| 135 | cat <"${DIR}/ProcGroup${i}" >>dynamic.log | 
|---|
| 136 | echo -e "\n" | tee -a dynamic.log | 
|---|
| 137 | done | 
|---|
| 138 |  | 
|---|
| 139 | # copy first conf | 
|---|
| 140 | cp $arg ${arg}.MD | 
|---|
| 141 | cp $arg ${arg}.MD.MD | 
|---|
| 142 |  | 
|---|
| 143 | # create fake pcp.energy.all by parsing a bit of the config file | 
|---|
| 144 | MaxLevel=`grep MaxLevel $arg | awk -F"\t" '{print $2'}` | 
|---|
| 145 | echo -e "Time\tTotal\tKinetic\tNonLocal\tCorrelation\tExchange\tPseudo\tHartree\t-Gauss\tEwald\tIonKin\tETotal\t" >${DIR}/pcp.full.energy.all | 
|---|
| 146 | j=0 | 
|---|
| 147 | while [ $j -lt $MaxLevel ]; do | 
|---|
| 148 | let j=$j+1 | 
|---|
| 149 | i=0 | 
|---|
| 150 | while [ $i -lt 12 ]; do | 
|---|
| 151 | let i=$i+1 | 
|---|
| 152 | printf "%e\t" 0 >>${DIR}/pcp.full.energy.all | 
|---|
| 153 | done | 
|---|
| 154 | echo -n -e "\n" >>${DIR}/pcp.full.energy.all | 
|---|
| 155 | done | 
|---|
| 156 | echo "$MaxLevel lines created in ${DIR}/pcp.full.energy.all." | 
|---|
| 157 |  | 
|---|
| 158 | # create fake pcp.forces.all by parsing a bit of the config file | 
|---|
| 159 | MaxTypes=`grep MaxTypes $arg | awk -F"\t" '{print $2'}` | 
|---|
| 160 | MaxIons=0 | 
|---|
| 161 | i=0 | 
|---|
| 162 | echo -e "Type\tNo\tPos0\tPos1\tPos2\tTotal0\tTotal1\tTotal2\tLocal0\tLocal1\tLocal2\tNLocal0\tNLocal1\tNLocal2\tMagnetic0\tMagnetic1\tMagnetic2\tEwald0\tEwald1\tEwald2" >${DIR}/pcp.full.forces.all | 
|---|
| 163 | while [ $i -lt $MaxTypes ]; do | 
|---|
| 164 | let type=$i+1 | 
|---|
| 165 | j=`grep -E "^Ion_Type${type}[^_]+" $arg | awk -F"\t" '{print $2'}` | 
|---|
| 166 | echo "Ion type ${type} has $j ions." | 
|---|
| 167 | ionnr=0 | 
|---|
| 168 | while [ $ionnr -lt $j ]; do | 
|---|
| 169 | echo -n -e "$i\t$ionnr\t" >>${DIR}/pcp.full.forces.all | 
|---|
| 170 | k=0 | 
|---|
| 171 | while [ $k -lt 18 ]; do | 
|---|
| 172 | printf "%e\t" 0 >>${DIR}/pcp.full.forces.all | 
|---|
| 173 | let k=$k+1 | 
|---|
| 174 | done | 
|---|
| 175 | echo -n -e "\n" >>${DIR}/pcp.full.forces.all | 
|---|
| 176 | let ionnr=$ionnr+1 | 
|---|
| 177 | done | 
|---|
| 178 | let MaxIons=$MaxIons+$j | 
|---|
| 179 | let i=$i+1 | 
|---|
| 180 | done | 
|---|
| 181 | echo -e "MeanForce:\t0." >>${DIR}/pcp.full.forces.all | 
|---|
| 182 | echo "$MaxIons lines created in ${DIR}/pcp.full.forces.all." | 
|---|
| 183 |  | 
|---|
| 184 | i=1; | 
|---|
| 185 | while [ $i -le $MaxSteps ]; do | 
|---|
| 186 | # break down the molecule with molecuilder | 
|---|
| 187 | sed -i -e "s#MaxOuterStep.*\##MaxOuterStep\t0\t\##" $arg.MD.MD | 
|---|
| 188 | echo -n "Fragmenting ... " | tee -a dynamic.log | 
|---|
| 189 | PWD=`pwd` | 
|---|
| 190 | cd `dirname ${MOLECUILDER}` | 
|---|
| 191 | ./`basename ${MOLECUILDER}` ${arg}.MD.MD -f $distance $order A | 
|---|
| 192 | check | 
|---|
| 193 | cd $PWD | 
|---|
| 194 | echo "done." | tee -a dynamic.log | 
|---|
| 195 |  | 
|---|
| 196 | # get the number of digits of the fragment count | 
|---|
| 197 | digits=1 | 
|---|
| 198 | while [ ! -e ${DIR}/BondFragment`printf "%0${digits}d" 0`.conf ]; do | 
|---|
| 199 | let digits=$digits+1 | 
|---|
| 200 | done | 
|---|
| 201 | echo "Found $digits digits for the fragment number." | tee -a dynamic.log | 
|---|
| 202 |  | 
|---|
| 203 | # get the fragment count | 
|---|
| 204 | frag=0 | 
|---|
| 205 | while [ -e ${DIR}/BondFragment`printf "%0${digits}d" $frag`.conf ]; do | 
|---|
| 206 | # unset MaxOuterStep in config file | 
|---|
| 207 | sed -i -e "s#MaxOuterStep.*\##MaxOuterStep\t0\t\##" ${DIR}/BondFragment`printf "%0${digits}d" $frag`.conf | 
|---|
| 208 | mkdir -p ${DIR}/BondFragment`printf "%0${digits}d" $frag` | 
|---|
| 209 | let frag=$frag+1 | 
|---|
| 210 | done | 
|---|
| 211 | echo "There are $frag fragments." | tee -a dynamic.log | 
|---|
| 212 |  | 
|---|
| 213 | # evaluate each fragment | 
|---|
| 214 | j=0; | 
|---|
| 215 | while [ $j -lt $frag ]; do | 
|---|
| 216 | number=`printf "%0${digits}d" $j` | 
|---|
| 217 | echo -n  "Starting calculation of Fragment $number at step $i ... " | tee -a dynamic.log | 
|---|
| 218 | MultiRunSim ${DIR}/BondFragment${number}.conf $divisor | 
|---|
| 219 | echo "done." | tee -a dynamic.log | 
|---|
| 220 | let j=$j+1 | 
|---|
| 221 | done | 
|---|
| 222 |  | 
|---|
| 223 | # wait till all ProcRuns files are gone | 
|---|
| 224 | echo "Waiting for all running jobs at step $i to end ... " | tee -a dynamic.log | 
|---|
| 225 | while [ ! -z "`ls ${DIR}/ProcRuns*`" ]; do | 
|---|
| 226 | sleep 15 | 
|---|
| 227 | done | 
|---|
| 228 | echo "done." | tee -a dynamic.log | 
|---|
| 229 |  | 
|---|
| 230 | # join the resulting forces into a single file | 
|---|
| 231 | cp ${DIR}/pcp.full.energy.all ${DIR}/pcp.energy.all | 
|---|
| 232 | cp ${DIR}/pcp.full.forces.all ${DIR}/pcp.forces.all | 
|---|
| 233 | echo -n "Joining fragment energies ... " | tee -a dynamic.log | 
|---|
| 234 | ${JOINER} ${DIR}/ $mainname >/dev/null 2>/dev/null | 
|---|
| 235 | check | 
|---|
| 236 | echo "done." | tee -a dynamic.log | 
|---|
| 237 |  | 
|---|
| 238 | # move the ions by calling pcp with this force file | 
|---|
| 239 | sed -e "s#MaxOuterStep.*\##MaxOuterStep\t$i\t\##" ${arg}.MD.MD >${arg}.MD | 
|---|
| 240 | echo -n "Moving ions with obtained forces at step $i ... " | tee -a dynamic.log | 
|---|
| 241 | RunSim ${arg}.MD $PBS_NODEFILE -F "${DIR}/pcp.Order${order}.forces.all" | 
|---|
| 242 | echo "done" | tee -a dynamic.log | 
|---|
| 243 |  | 
|---|
| 244 | # last of all, put "joined" energy and forces under this step | 
|---|
| 245 | cp ${DIR}/pcp.Order${order}.energy.all ${DIR}/pcp.step${i}.energy.all | 
|---|
| 246 | cp ${DIR}/pcp.Order${order}.forces.all ${DIR}/pcp.step${i}.forces.all | 
|---|
| 247 |  | 
|---|
| 248 | # next step | 
|---|
| 249 | let i=$i+1 | 
|---|
| 250 | done | 
|---|
| 251 |  | 
|---|
| 252 | # draw densities of each step | 
|---|
| 253 | sed -e "s#DoOutVis.*\##DoOutVis\t2\t\##" ${arg}.MD.MD >${arg}.MD | 
|---|
| 254 | echo -n "Calling simulation to draw final densities of all steps ... " | tee -a dynamic.log | 
|---|
| 255 | RunSim ${arg}.MD $PBS_NODEFILE | 
|---|
| 256 | echo "done." | tee -a dynamic.log | 
|---|
| 257 |  | 
|---|
| 258 | exit 0 | 
|---|