![]() |
ESPResSo 3.2.0-167-g2c9ead1-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 <stdio.h> 00024 #include <stdlib.h> 00025 #include <string.h> 00026 #include <math.h> 00027 #include "domain_decomposition.h" 00028 #include "rattle.h" 00029 00030 int n_rigidbonds = 0; 00031 00032 #ifdef BOND_CONSTRAINT 00033 00034 /** \name Private functions */ 00035 /************************************************************/ 00036 /*@{*/ 00037 00038 /** Calculates the corrections required for each of the particle coordinates 00039 according to the RATTLE algorithm. Invoked from \ref correct_pos_shake()*/ 00040 void compute_pos_corr_vec(int *repeat_); 00041 00042 /** Positional Corrections are added to the current particle positions. Invoked from \ref correct_pos_shake() */ 00043 void app_pos_correction(); 00044 00045 /** Transfers temporarily the current forces from f.f[3] of the \ref Particle 00046 structure to r.p_old[3] location and also intializes velocity correction 00047 vector. Invoked from \ref correct_vel_shake()*/ 00048 void transfer_force_init_vel(); 00049 00050 /** Calculates corrections of the current particle velocities according to RATTLE 00051 algorithm. Invoked from \ref correct_vel_shake()*/ 00052 void compute_vel_corr_vec(int *repeat_); 00053 00054 /** Velocity corrections are added to the current particle velocities. Invoked from 00055 \ref correct_vel_shake()*/ 00056 void apply_vel_corr(); 00057 00058 /**Invoked from \ref correct_vel_shake(). Put back the forces from r.p_old to f.f*/ 00059 void revert_force(); 00060 00061 /**For debugging purpose--prints the bond lengths between particles that have 00062 rigid_bonds*/ 00063 void print_bond_len(); 00064 00065 /*@}*/ 00066 00067 /*Initialize old positions (particle positions at previous time step) 00068 of the particles*/ 00069 void save_old_pos() 00070 { 00071 int c, i, j, np; 00072 Particle *p; 00073 Cell *cell; 00074 for (c = 0; c < local_cells.n; c++) 00075 { 00076 cell = local_cells.cell[c]; 00077 p = cell->part; 00078 np = cell->n; 00079 for(i = 0; i < np; i++) { 00080 for(j=0;j<3;j++) 00081 p[i].r.p_old[j]=p[i].r.p[j]; 00082 } //for i loop 00083 }// for c loop 00084 00085 for (c = 0; c < ghost_cells.n; c++) 00086 { 00087 cell = ghost_cells.cell[c]; 00088 p = cell->part; 00089 np = cell->n; 00090 for(i = 0; i < np; i++) { 00091 for(j=0;j<3;j++) 00092 p[i].r.p_old[j]=p[i].r.p[j]; 00093 } 00094 } 00095 } 00096 00097 /**Initialize the correction vector. The correction vector is stored in f.f of particle strcuture. */ 00098 void init_correction_vector() 00099 { 00100 00101 int c, i, j, np; 00102 Particle *p; 00103 Cell *cell; 00104 00105 for (c = 0; c < local_cells.n; c++) 00106 { 00107 cell = local_cells.cell[c]; 00108 p = cell->part; 00109 np = cell->n; 00110 for(i = 0; i < np; i++) { 00111 for(j=0;j<3;j++) 00112 p[i].f.f[j] = 0.0; 00113 } //for i loop 00114 }// for c loop 00115 00116 for (c = 0; c < ghost_cells.n; c++) 00117 { 00118 cell = ghost_cells.cell[c]; 00119 p = cell->part; 00120 np = cell->n; 00121 for(i = 0; i < np; i++) { 00122 for(j=0;j<3;j++) 00123 p[i].f.f[j] = 0.0; 00124 } 00125 } 00126 } 00127 00128 /**Compute positional corrections*/ 00129 void compute_pos_corr_vec(int *repeat_) 00130 { 00131 Bonded_ia_parameters *ia_params; 00132 int i, j, k, c, np, cnt=-1; 00133 Cell *cell; 00134 Particle *p, *p1, *p2; 00135 double r_ij_t[3], r_ij[3], r_ij_dot, G, pos_corr, r_ij2; 00136 00137 for (c = 0; c < local_cells.n; c++) { 00138 cell = local_cells.cell[c]; 00139 p = cell->part; 00140 np = cell->n; 00141 for(i = 0; i < np; i++) { 00142 p1 = &p[i]; 00143 k=0; 00144 while(k<p1->bl.n) { 00145 ia_params = &bonded_ia_params[p1->bl.e[k++]]; 00146 if( ia_params->type == BONDED_IA_RIGID_BOND ) { 00147 cnt++; 00148 p2 = local_particles[p1->bl.e[k++]]; 00149 if (!p2) { 00150 char *errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 00151 ERROR_SPRINTF(errtxt,"{051 rigid bond broken between particles %d and %d (particles not stored on the same node)} ", 00152 p1->p.identity, p1->bl.e[k-1]); 00153 return; 00154 } 00155 00156 get_mi_vector(r_ij , p1->r.p , p2->r.p ); 00157 r_ij2 = sqrlen(r_ij); 00158 if(fabs(1.0 - r_ij2/ia_params->p.rigid_bond.d2) > ia_params->p.rigid_bond.p_tol) { 00159 get_mi_vector(r_ij_t, p1->r.p_old, p2->r.p_old); 00160 r_ij_dot = scalar(r_ij_t, r_ij); 00161 G = 0.50*(ia_params->p.rigid_bond.d2 - r_ij2 )/r_ij_dot; 00162 #ifdef MASS 00163 G /= (PMASS(*p1)+PMASS(*p2)); 00164 #else 00165 G /= 2; 00166 #endif 00167 for (j=0;j<3;j++) { 00168 pos_corr = G*r_ij_t[j]; 00169 p1->f.f[j] += pos_corr*PMASS(*p2); 00170 p2->f.f[j] -= pos_corr*PMASS(*p1); 00171 } 00172 /*Increase the 'repeat' flag by one */ 00173 *repeat_ = *repeat_ + 1; 00174 } 00175 } 00176 else 00177 /* skip bond partners of nonrigid bond */ 00178 k+=ia_params->num; 00179 } //while loop 00180 } //for i loop 00181 } //for c loop 00182 } 00183 00184 /**Apply corrections to each particle**/ 00185 void app_pos_correction() 00186 { 00187 int c, i, j, np; 00188 Particle *p, *p1; 00189 Cell *cell; 00190 00191 00192 /*Apply corrections*/ 00193 for (c = 0; c < local_cells.n; c++) 00194 { 00195 cell = local_cells.cell[c]; 00196 p = cell->part; 00197 np = cell->n; 00198 for(i = 0; i < np; i++) { 00199 p1 = &p[i]; 00200 for (j=0;j<3;j++) { 00201 p1->r.p[j] += p1->f.f[j]; 00202 p1->m.v[j] += p1->f.f[j]; 00203 } 00204 00205 /**Completed for one particle*/ 00206 } //for i loop 00207 } //for c loop 00208 } 00209 00210 void correct_pos_shake() 00211 { 00212 int repeat_, cnt=0; 00213 int repeat=1; 00214 00215 while (repeat!=0 && cnt<SHAKE_MAX_ITERATIONS) 00216 { 00217 init_correction_vector(); 00218 repeat_ = 0; 00219 compute_pos_corr_vec(&repeat_); 00220 ghost_communicator(&cell_structure.collect_ghost_force_comm); 00221 app_pos_correction(); 00222 /**Ghost Positions Update*/ 00223 ghost_communicator(&cell_structure.update_ghost_pos_comm); 00224 if(this_node==0) 00225 MPI_Reduce(&repeat_, &repeat, 1, MPI_INT, MPI_SUM, 0, comm_cart); 00226 else 00227 MPI_Reduce(&repeat_, NULL, 1, MPI_INT, MPI_SUM, 0, comm_cart); 00228 MPI_Bcast(&repeat, 1, MPI_INT, 0, comm_cart); 00229 00230 cnt++; 00231 }// while(repeat) loop 00232 if (cnt >= SHAKE_MAX_ITERATIONS) { 00233 char *errtxt = runtime_error(100 + ES_INTEGER_SPACE); 00234 ERROR_SPRINTF(errtxt, "{053 RATTLE failed to converge after %d iterations} ", cnt); 00235 } 00236 00237 check_resort_particles(); 00238 } 00239 00240 /**The forces are transfered temporarily from f.f member of particle structure to r.p_old, 00241 which is idle now and initialize the velocity correction vector to zero at f.f[3] 00242 of Particle structure*/ 00243 void transfer_force_init_vel() 00244 { 00245 00246 int c, i, j, np; 00247 Particle *p; 00248 Cell *cell; 00249 00250 for (c = 0; c < local_cells.n; c++) 00251 { 00252 cell = local_cells.cell[c]; 00253 p = cell->part; 00254 np = cell->n; 00255 for(i = 0; i < np; i++) { 00256 for(j=0;j<3;j++) 00257 { 00258 p[i].r.p_old[j]=p[i].f.f[j]; 00259 p[i].f.f[j]=0.0; 00260 } 00261 } //for i loop 00262 }// for c loop 00263 00264 for (c = 0; c < ghost_cells.n; c++) 00265 { 00266 cell = ghost_cells.cell[c]; 00267 p = cell->part; 00268 np = cell->n; 00269 for(i = 0; i < np; i++) { 00270 for(j=0;j<3;j++) 00271 { 00272 p[i].r.p_old[j]=p[i].f.f[j]; 00273 p[i].f.f[j]=0.0; 00274 } 00275 } 00276 } 00277 } 00278 00279 /** Velocity correction vectors are computed*/ 00280 void compute_vel_corr_vec(int *repeat_) 00281 { 00282 Bonded_ia_parameters *ia_params; 00283 int i, j, k, c, np; 00284 Cell *cell; 00285 Particle *p, *p1, *p2; 00286 double v_ij[3], r_ij[3], K, vel_corr; 00287 00288 for (c = 0; c < local_cells.n; c++) 00289 { 00290 cell = local_cells.cell[c]; 00291 p = cell->part; 00292 np = cell->n; 00293 for(i = 0; i < np; i++) { 00294 p1 = &p[i]; 00295 k=0; 00296 while(k<p1->bl.n) 00297 { 00298 ia_params = &bonded_ia_params[p1->bl.e[k++]]; 00299 if( ia_params->type == BONDED_IA_RIGID_BOND ) 00300 { 00301 p2 = local_particles[p1->bl.e[k++]]; 00302 if (!p2) { 00303 char *errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 00304 ERROR_SPRINTF(errtxt,"{054 rigid bond broken between particles %d and %d (particles not stored on the same node)} ", 00305 p1->p.identity, p1->bl.e[k-1]); 00306 return; 00307 } 00308 00309 vecsub(p1->m.v, p2->m.v, v_ij); 00310 get_mi_vector(r_ij, p1->r.p, p2->r.p); 00311 if(fabs(scalar(v_ij, r_ij)) > ia_params->p.rigid_bond.v_tol) 00312 { 00313 K = scalar(v_ij, r_ij)/ia_params->p.rigid_bond.d2; 00314 #ifdef MASS 00315 K /= (PMASS(*p1) + PMASS(*p2)); 00316 #else 00317 K /= 2.0; 00318 #endif 00319 for (j=0;j<3;j++) 00320 { 00321 vel_corr = K*r_ij[j]; 00322 p1->f.f[j] -= vel_corr*PMASS(*p2); 00323 p2->f.f[j] += vel_corr*PMASS(*p1); 00324 } 00325 *repeat_ = *repeat_ + 1 ; 00326 } 00327 } 00328 else 00329 k += ia_params->num; 00330 } //while loop 00331 } //for i loop 00332 } //for c loop 00333 } 00334 00335 /**Apply velocity corrections*/ 00336 void apply_vel_corr() 00337 { 00338 00339 int c, i, j, np; 00340 Particle *p, *p1; 00341 Cell *cell; 00342 00343 /*Apply corrections*/ 00344 for (c = 0; c < local_cells.n; c++) 00345 { 00346 cell = local_cells.cell[c]; 00347 p = cell->part; 00348 np = cell->n; 00349 for(i = 0; i < np; i++) { 00350 p1 = &p[i]; 00351 for (j=0;j<3;j++) { 00352 p1->m.v[j] += p1->f.f[j]; 00353 00354 } 00355 /**Completed for one particle*/ 00356 } //for i loop 00357 } //for c loop 00358 00359 } 00360 00361 /**Put back the forces from r.p_old to f.f*/ 00362 void revert_force() 00363 { 00364 int c, i, j, np; 00365 Particle *p; 00366 Cell *cell; 00367 for (c = 0; c < local_cells.n; c++) 00368 { 00369 cell = local_cells.cell[c]; 00370 p = cell->part; 00371 np = cell->n; 00372 for(i = 0; i < np; i++) { 00373 for(j=0;j<3;j++) 00374 p[i].f.f[j]=p[i].r.p_old[j]; 00375 00376 } //for i loop 00377 }// for c loop 00378 00379 00380 for (c = 0; c < ghost_cells.n; c++) 00381 { 00382 cell = ghost_cells.cell[c]; 00383 p = cell->part; 00384 np = cell->n; 00385 for(i = 0; i < np; i++) 00386 { 00387 for(j=0;j<3;j++) 00388 p[i].f.f[j]=p[i].r.p_old[j]; 00389 } 00390 } 00391 } 00392 00393 void correct_vel_shake() 00394 { 00395 int repeat_, repeat=1, cnt=0; 00396 /**transfer the current forces to r.p_old of the particle structure so that 00397 velocity corrections can be stored temporarily at the f.f[3] of the particle 00398 structure */ 00399 transfer_force_init_vel(); 00400 while (repeat!=0 && cnt<SHAKE_MAX_ITERATIONS) 00401 { 00402 init_correction_vector(); 00403 repeat_ = 0; 00404 compute_vel_corr_vec(&repeat_); 00405 ghost_communicator(&cell_structure.collect_ghost_force_comm); 00406 apply_vel_corr(); 00407 ghost_communicator(&cell_structure.update_ghost_pos_comm); 00408 if(this_node == 0) 00409 MPI_Reduce(&repeat_, &repeat, 1, MPI_INT, MPI_SUM, 0, comm_cart); 00410 else 00411 MPI_Reduce(&repeat_, NULL, 1, MPI_INT, MPI_SUM, 0, comm_cart); 00412 00413 MPI_Bcast(&repeat, 1, MPI_INT, 0, comm_cart); 00414 cnt++; 00415 } 00416 00417 if (cnt >= SHAKE_MAX_ITERATIONS) { 00418 fprintf(stderr, "%d: VEL CORRECTIONS IN RATTLE failed to converge after %d iterations !!\n", this_node, cnt); 00419 errexit(); 00420 } 00421 /**Puts back the forces from r.p_old to f.f[3]*/ 00422 revert_force(); 00423 } 00424 00425 00426 void print_bond_len() 00427 { 00428 int i, k, c, np; 00429 Cell *cell; 00430 Particle *p; 00431 Bonded_ia_parameters *b_ia; 00432 double r_ij[3]; 00433 printf("%d: ", this_node); 00434 for (c = 0; c < local_cells.n; c++) { 00435 cell = local_cells.cell[c]; 00436 p = cell->part; 00437 np = cell->n; 00438 for(i = 0; i < np; i++) { 00439 k=0; 00440 while(k<p[i].bl.n) 00441 { 00442 b_ia = &bonded_ia_params[p[i].bl.e[k]]; 00443 if(b_ia->type == BONDED_IA_RIGID_BOND) 00444 { 00445 Particle *p2 = local_particles[p[i].bl.e[k++]]; 00446 if (!p2) { 00447 char *errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 00448 ERROR_SPRINTF(errtxt,"{056 rigid bond broken between particles %d and %d (particles not stored on the same node)} ", p[i].p.identity, p[i].bl.e[k-1]); 00449 return; 00450 } 00451 00452 get_mi_vector(r_ij, p[i].r.p , p2->r.p); 00453 printf(" bl (%d %d): %f\t", p[i].p.identity, p2->p.identity,sqrlen(r_ij)); 00454 } 00455 else 00456 k += b_ia->num; 00457 } //while k loop 00458 } //for i loop 00459 }// for c loop 00460 printf("\n"); 00461 } 00462 00463 /***************************************************************************** 00464 * setting parameters 00465 *****************************************************************************/ 00466 int rigid_bond_set_params(int bond_type, double d, double p_tol, double v_tol) 00467 { 00468 if(bond_type < 0) 00469 return ES_ERROR; 00470 00471 make_bond_type_exist(bond_type); 00472 00473 bonded_ia_params[bond_type].p.rigid_bond.d2 = d*d; 00474 bonded_ia_params[bond_type].p.rigid_bond.p_tol = 2.0*p_tol; 00475 bonded_ia_params[bond_type].p.rigid_bond.v_tol = v_tol*time_step; 00476 bonded_ia_params[bond_type].type = BONDED_IA_RIGID_BOND; 00477 bonded_ia_params[bond_type].num = 1; 00478 n_rigidbonds += 1; 00479 mpi_bcast_ia_params(bond_type, -1); 00480 mpi_bcast_parameter(FIELD_RIGIDBONDS); 00481 00482 return ES_OK; 00483 } 00484 00485 #endif
1.7.5.1