![]() |
ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
|
00001 /* 00002 Copyright (C) 2010,2012,2013 The ESPResSo project 00003 Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 00004 Max-Planck-Institute for Polymer Research, Theory Group 00005 00006 This file is part of ESPResSo. 00007 00008 ESPResSo is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation, either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 ESPResSo is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 */ 00021 00022 #include <mpi.h> 00023 #include "utils.h" 00024 #include "grid.h" 00025 #include "molforces.h" 00026 #include "topology.h" 00027 #include "particle_data.h" 00028 #include "cells.h" 00029 #include "communication.h" 00030 #include "forces.h" 00031 00032 /** \file molforces.c 00033 * Routines for calculating and applying trap forces upon molecules. 00034 * This trap force can be set to 00035 * - a harmonic potential with a restlength of zero on the molecular centre of mass 00036 * - a drag on the molecular velocity 00037 * - a cancelation of the total force on the molecule (including thermostat forces) 00038 * The centre of mass can be fixed to an absolute position or to a relative position in the 00039 * simulation box. 00040 * The molecular trap forces is distributed evenly upon all particles in a molecule. 00041 * (see \ref topology.c and \ref molforces.c) 00042 */ 00043 00044 #ifdef MOLFORCES 00045 00046 00047 /* global variable which indicates whether any molecules are trapped */ 00048 /* set in mpi_sync_topo_part_info_slave and set_molecule_trap */ 00049 int IsTrapped = 0; 00050 00051 void apply_mol_constraints() 00052 { 00053 Particle *p; 00054 int i, np, c, mi; 00055 Cell *cell; 00056 int j; 00057 00058 for (c = 0; c < local_cells.n; c++) { 00059 cell = local_cells.cell[c]; 00060 p = cell->part; 00061 np = cell->n; 00062 for(i = 0; i < np; i++) { 00063 mi = p[i].p.mol_id; 00064 for(j = 0; j < 3; j++) { 00065 /* Applies the trap force for this coordinate and this particle. */ 00066 p[i].f.f[j] += topology[mi].trap_force[j]; 00067 } 00068 } 00069 } 00070 } 00071 00072 /* calculates the force applies by traps on all molecules */ 00073 void calc_trap_force() 00074 { 00075 Molecule *m; 00076 int mi,j; 00077 #ifdef EXTERNAL_FORCES 00078 double trappos; 00079 #endif 00080 00081 00082 if ( !topo_part_info_synced ) { 00083 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00084 ERROR_SPRINTF(errtxt, "{ 093 can't calculate moltrap: must execute analyse set topo_part_sync first }"); 00085 return; 00086 } else { 00087 00088 m = &topology[0]; 00089 00090 for (mi = 0; mi < n_molecules; mi++) { 00091 m = &topology[mi]; 00092 for(j = 0; j < 3; j++) { 00093 #ifdef EXTERNAL_FORCES 00094 if (m->trap_flag & COORD_FIXED(j)) { 00095 /* Is the molecule trapped at a certain position in space? */ 00096 if (m->isrelative == 1) { 00097 /* Is the trap set to absolute coordinates... */ 00098 trappos = m->trap_center[j]*box_l[j]; 00099 } else { 00100 /* or to relative ones? */ 00101 trappos = m->trap_center[j]; 00102 } 00103 m->trap_force[j] = 0; 00104 /* the trap_force holding the molecule to the set position in calculated */ 00105 m->trap_force[j] += -((m->com[j]-trappos)*m->trap_spring_constant)/(double)(m->part.n); 00106 /* the drag force applied to the molecule is calculated */ 00107 m->trap_force[j] += -(m->v[j]*m->drag_constant)/(double)(m->part.n); 00108 /* the force applies by the traps is added to fav */ 00109 /* favcounter counts how many times we have added the force to fav since last time "analyze mol force" was called */ 00110 /* upon Espresso initialization it is set to -1 because in the first call of "integrate" there is an extra initial time step */ 00111 /* calling "analyze mol force" resets favcounter to 0 */ 00112 if (m->favcounter > -1) m->fav[j] -= m->v[j]*m->drag_constant + (m->com[j]-trappos)*m->trap_spring_constant; 00113 } 00114 if (m->noforce_flag & COORD_FIXED(j)) { 00115 /* the trap force required to cancel out the total force acting on the molecule is calculated */ 00116 m->trap_force[j] -= m->f[j]/(double)m->part.n; 00117 if (m->favcounter > -1) m->fav[j] -= m->f[j]; 00118 } 00119 #endif 00120 } 00121 m->favcounter++; 00122 } 00123 } 00124 } 00125 00126 /* A list of trapped molecules present on this node is created (local_trapped_mols)*/ 00127 void get_local_trapped_mols (IntList *local_trapped_mols) 00128 { 00129 int c, i, mol, j, fixed; 00130 00131 for (c = 0; c < local_cells.n; c++) { 00132 for(i = 0; i < local_cells.cell[c]->n; i++) { 00133 mol = local_cells.cell[c]->part[i].p.mol_id; 00134 if ( mol >= n_molecules ) { 00135 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00136 ERROR_SPRINTF(errtxt, "{ 094 can't calculate molforces no such molecule as %d }",mol); 00137 return; 00138 } 00139 00140 /* Check to see if this molecule is fixed */ 00141 fixed =0; 00142 for(j = 0; j < 3; j++) { 00143 #ifdef EXTERNAL_FORCES 00144 if (topology[mol].trap_flag & COORD_FIXED(j)) fixed = 1; 00145 if (topology[mol].noforce_flag & COORD_FIXED(j)) fixed = 1; 00146 #endif 00147 } 00148 if (fixed) { 00149 /* if this molecule isn't already in local_trapped_mols then add it in */ 00150 if (!intlist_contains(local_trapped_mols,mol)) { 00151 realloc_intlist(local_trapped_mols, local_trapped_mols->max + 1); 00152 local_trapped_mols->e[local_trapped_mols->max-1] = mol; 00153 local_trapped_mols->n = local_trapped_mols->max; 00154 } 00155 } 00156 } 00157 } 00158 } 00159 00160 /* Calculate forces, mass, and unnormalized center of mass and velocity*/ 00161 /* This is only done for the trapped molecules to save time */ 00162 void calc_local_mol_info (IntList *local_trapped_mols) 00163 { 00164 int mi, i,j, mol; 00165 Particle *p; 00166 int np, c; 00167 Cell *cell; 00168 int lm; 00169 int fixed; 00170 00171 /* First reset all molecule masses,forces,centers of mass*/ 00172 for ( mi = 0 ; mi < n_molecules ; mi++ ) { 00173 topology[mi].mass = 0; 00174 for ( i = 0 ; i < 3 ; i++) { 00175 topology[mi].f[i] = 0.0; 00176 topology[mi].com[i] = 0.0; 00177 topology[mi].v[i] = 0.0; 00178 } 00179 } 00180 00181 for (c = 0; c < local_cells.n; c++) { 00182 cell = local_cells.cell[c]; 00183 p = cell->part; 00184 np = cell->n; 00185 for(i = 0; i < np; i++) { 00186 mol = p[i].p.mol_id; 00187 if ( mol >= n_molecules ) { 00188 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00189 ERROR_SPRINTF(errtxt, "{ 094 can't calculate molforces no such molecule as %d }",mol); 00190 return; 00191 } 00192 00193 /* Check to see if this molecule is fixed */ 00194 fixed =0; 00195 for(j = 0; j < 3; j++) { 00196 #ifdef EXTERNAL_FORCES 00197 if (topology[mol].trap_flag & COORD_FIXED(j)) fixed = 1; 00198 if (topology[mol].noforce_flag & COORD_FIXED(j)) fixed = 1; 00199 #endif 00200 } 00201 if (fixed) { 00202 topology[mol].mass += PMASS(p[i]); 00203 /* Unfold the particle */ 00204 unfold_position(p[i].r.p,p[i].l.i); 00205 for ( j = 0 ; j < 3 ; j++ ) { 00206 topology[mol].f[j] += p[i].f.f[j]; 00207 topology[mol].com[j] += p[i].r.p[j]*PMASS(p[i]); 00208 topology[mol].v[j] += p[i].m.v[j]*PMASS(p[i]); 00209 } 00210 /* Fold the particle back */ 00211 fold_position(p[i].r.p,p[i].l.i); 00212 00213 } 00214 } 00215 } 00216 00217 /* Final normalisation of centers of mass and velocity*/ 00218 for ( lm = 0 ; lm < local_trapped_mols->n; lm++ ) { 00219 mi = local_trapped_mols->e[lm]; 00220 for ( i = 0 ; i < 3 ; i++) { 00221 topology[mi].com[i] = topology[mi].com[i]/(double)(topology[mi].mass); 00222 topology[mi].v[i] = topology[mi].v[i]/(double)(topology[mi].mass); 00223 } 00224 } 00225 00226 } 00227 00228 /* Receives molecule information from the slave nodes. Combines this information, 00229 calculates trap forces, and returns information to slave nodes */ 00230 00231 void mpi_comm_mol_info(IntList *local_trapped_mols) { 00232 int i, j, k, mol, count; 00233 double com[3] = {0,0,0}; 00234 double v[3] = {0,0,0}; 00235 double f[3] = {0,0,0}; 00236 double mass = 0; 00237 /* number of trapped molecules on each node */ 00238 int *n_local_mols; 00239 /* sum of all elements of n_local_mols */ 00240 int sum_n_local_mols; 00241 /* lists of which molecules are on each node in order of ascending node number */ 00242 int *local_mols; 00243 MPI_Status status; 00244 00245 n_local_mols = malloc(n_nodes*sizeof(int)); 00246 sum_n_local_mols = 0; 00247 00248 /* Everyone tells me how many trapped molecules are on their node */ 00249 for (i=1; i <n_nodes; i++) { 00250 MPI_Recv(&(n_local_mols[i]),1,MPI_INT,i,99,comm_cart,&status); 00251 } 00252 00253 for (i=1; i <n_nodes; i++) { 00254 sum_n_local_mols += n_local_mols[i]; 00255 } 00256 local_mols = malloc(sum_n_local_mols*sizeof(int)); 00257 00258 /* Everyone tells me which trapped molecules are on their node */ 00259 count = 0; 00260 for (i=1; i <n_nodes; i++) { 00261 MPI_Recv(&(local_mols[count]),n_local_mols[i],MPI_INT,i,99,comm_cart,&status); 00262 count += n_local_mols[i]; 00263 } 00264 00265 /* Initialise the centre of masses, velocities and forces to 0 00266 except for molecules present on master node which are initialized to the local values on the master node 00267 The centre of masses and velocities are weighted by the total mass on the master node */ 00268 for (i = 0; i < n_molecules; i++) { 00269 mol =i; 00270 if (intlist_contains(local_trapped_mols,i)) { 00271 for (j = 0; j < 3; j++) { 00272 topology[mol].com[j] = topology[mol].com[j] * topology[mol].mass; 00273 topology[mol].v[j] = topology[mol].v[j] * topology[mol].mass; 00274 topology[mol].f[j] = topology[mol].f[j]; 00275 } 00276 } else { 00277 topology[mol].mass = 0; 00278 for (j = 0; j < 3; j++) { 00279 topology[mol].com[j] = 0; 00280 topology[mol].v[j] = 0; 00281 topology[mol].f[j] = 0; 00282 } 00283 } 00284 } 00285 00286 /* The masses, coms, velocities and forces for trapped molecules are received from the slave nodes. 00287 They are added into the running sums in topology[mol] */ 00288 count = 0; 00289 for (i = 1; i < n_nodes; i++) { 00290 for (j = 0; j < n_local_mols[i]; j++) { 00291 mol = local_mols[count]; 00292 count += 1; 00293 MPI_Recv(&mass,1,MPI_DOUBLE,i,99,comm_cart,&status); 00294 MPI_Recv(com,3,MPI_DOUBLE,i,99,comm_cart,&status); 00295 MPI_Recv(v,3,MPI_DOUBLE,i,99,comm_cart,&status); 00296 MPI_Recv(f,3,MPI_DOUBLE,i,99,comm_cart,&status); 00297 topology[mol].mass = topology[mol].mass + mass; 00298 for (k = 0; k< 3; k++) { 00299 topology[mol].com[k] += com[k]*mass; 00300 topology[mol].v[k] += v[k]*mass; 00301 topology[mol].f[k] += f[k]; 00302 } 00303 } 00304 } 00305 00306 /* The centre of masses and velocities are renormalized by the total molecular weights */ 00307 for (mol = 0; mol < n_molecules; mol++) { 00308 for (k=0;k <3; k ++) { 00309 topology[mol].com[k] = topology[mol].com[k]/topology[mol].mass; 00310 topology[mol].v[k] = topology[mol].v[k]/topology[mol].mass; 00311 } 00312 } 00313 00314 /* The force exerted by the traps on the molecules are calculated */ 00315 calc_trap_force(); 00316 00317 /* The molecule information and trap forces are sent back to the slave nodes. */ 00318 count = 0; 00319 for (i = 1; i < n_nodes ; i++) { 00320 for (j = 0; j < n_local_mols[i]; j++) { 00321 mol = local_mols[count]; 00322 count += 1; 00323 MPI_Send(&(topology[mol].mass),1,MPI_DOUBLE,i,99,comm_cart); 00324 MPI_Send(topology[mol].com,3,MPI_DOUBLE,i,99,comm_cart); 00325 MPI_Send(topology[mol].v,3,MPI_DOUBLE,i,99,comm_cart); 00326 MPI_Send(topology[mol].f,3,MPI_DOUBLE,i,99,comm_cart); 00327 MPI_Send(topology[mol].trap_force,3,MPI_DOUBLE,i,99,comm_cart); 00328 } 00329 } 00330 00331 free(local_mols); 00332 free(n_local_mols); 00333 00334 } 00335 00336 /* Send molecule information to the master node. 00337 Recieve the combined molecule information and the trap forces */ 00338 00339 void mpi_comm_mol_info_slave(IntList *local_trapped_mols) { 00340 int i, mol; 00341 MPI_Status status; 00342 00343 /* Tells master how many trapped molecules are on this node */ 00344 MPI_Send(&(local_trapped_mols->n),1,MPI_INT,0,99,comm_cart); 00345 00346 /* Tells master which trapped molecules are on this node */ 00347 MPI_Send(local_trapped_mols->e,local_trapped_mols->n,MPI_INT,0,99,comm_cart); 00348 00349 for (i = 0; i < local_trapped_mols->n ; i++) { 00350 mol = local_trapped_mols->e[i]; 00351 /* Send all the masses and coms of the local molecules to the master node */ 00352 MPI_Send(&(topology[mol].mass),1,MPI_DOUBLE,0,99,comm_cart); 00353 MPI_Send(topology[mol].com,3,MPI_DOUBLE,0,99,comm_cart); 00354 MPI_Send(topology[mol].v,3,MPI_DOUBLE,0,99,comm_cart); 00355 MPI_Send(topology[mol].f,3,MPI_DOUBLE,0,99,comm_cart); 00356 } 00357 00358 for (i = 0; i < local_trapped_mols->n ; i++) { 00359 /* Receive all the masses and coms of the local molecules to the master node including info from other nodes*/ 00360 mol = local_trapped_mols->e[i]; 00361 MPI_Recv(&(topology[mol].mass),1,MPI_DOUBLE,0,99,comm_cart,&status); 00362 MPI_Recv(topology[mol].com,3,MPI_DOUBLE,0,99,comm_cart,&status); 00363 MPI_Recv(topology[mol].v,3,MPI_DOUBLE,0,99,comm_cart,&status); 00364 MPI_Recv(topology[mol].f,3,MPI_DOUBLE,0,99,comm_cart,&status); 00365 MPI_Recv(topology[mol].trap_force,3,MPI_DOUBLE,0,99,comm_cart,&status); 00366 } 00367 00368 } 00369 00370 /** 00371 Calculate the center of mass, total mass, velocity, total force, and trap force on all trapped molecules 00372 */ 00373 void calc_mol_info () { 00374 00375 /* list of trapped molecules on this node */ 00376 IntList local_trapped_mols; 00377 00378 /* check to see if all the topology information has been synced to the various slave nodes */ 00379 if ( !topo_part_info_synced ) { 00380 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00381 ERROR_SPRINTF(errtxt, "{ 093 can't calculate molforces: must execute analyse set topo_part_sync first }"); 00382 return; 00383 } 00384 00385 init_intlist(&local_trapped_mols); 00386 00387 /* Find out which trapped molecules are on this node */ 00388 get_local_trapped_mols(&local_trapped_mols); 00389 00390 /* Calculate the center of mass, mass, velocity, force of whatever fraction of each trapped molecule is on this node*/ 00391 calc_local_mol_info(&local_trapped_mols); 00392 00393 /* Communicate all this molecular information between nodes. 00394 It is all sent to the master node which combines it, calculates the trap forces, 00395 and sends the information back */ 00396 if (this_node == 0) { 00397 mpi_comm_mol_info(&local_trapped_mols); 00398 } else { 00399 mpi_comm_mol_info_slave(&local_trapped_mols); 00400 } 00401 00402 realloc_intlist(&local_trapped_mols,0); 00403 } 00404 00405 void calc_and_apply_mol_constraints () 00406 { 00407 if (IsTrapped) { 00408 /* the molecular information and trap forces are calculated */ 00409 calc_mol_info(); 00410 /* the trap forces are applied to the particles */ 00411 apply_mol_constraints(); 00412 } 00413 } 00414 00415 #endif
1.7.5.1