![]() |
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 /** \file nemd.c 00022 00023 For more information see \ref nemd.h 00024 */ 00025 #include "nemd.h" 00026 #include <stdio.h> 00027 #include "integrate.h" 00028 #include "communication.h" 00029 #include "errorhandling.h" 00030 #include "grid.h" 00031 00032 /************************************************************/ 00033 00034 00035 int nemd_method = NEMD_METHOD_OFF; 00036 00037 #ifdef NEMD 00038 Nemd nemddata = { -1, 0, 0, 0.0, 1.0, NULL, 0, 0, NULL, 0.0, 0.0, 0.0, 0}; 00039 00040 /** \name Privat Functions */ 00041 /************************************************************/ 00042 /*@{*/ 00043 00044 /** Free all associated memory. */ 00045 int nemd_free(void) 00046 { 00047 INTEG_TRACE(fprintf(stderr,"%d: nemd_free\n",this_node)); 00048 if(nemddata.n_exchange > 0) { 00049 free(nemddata.slab[nemddata.mid_slab].fastest); 00050 free(nemddata.slab[nemddata.top_slab].fastest); 00051 } 00052 free(nemddata.velocity_profile); 00053 free(nemddata.slab); 00054 nemddata.n_slabs = -1; 00055 nemddata.mid_slab = 0; 00056 nemddata.top_slab = 0; 00057 nemddata.thickness = 0.0; 00058 nemddata.invthickness = 1.0; 00059 nemddata.velocity_profile = NULL; 00060 nemddata.profile_norm = 0; 00061 nemddata.n_exchange = 0; 00062 nemddata.slab = NULL; 00063 nemddata.shear_rate = 0.0; 00064 nemddata.slab_vel = 0.0; 00065 return ES_OK; 00066 } 00067 00068 /** Initialize all data structures for nemd. */ 00069 void nemd_init(int n_slabs, int n_exchange, double shear_rate) 00070 { 00071 int i; 00072 00073 INTEG_TRACE(fprintf(stderr,"%d: nemd_init: n_slabs=%d n_exchange=%d\n",this_node, n_slabs, n_exchange)); 00074 00075 /* check node grid */ 00076 if( n_nodes > 1 ) { 00077 char *errtxt = runtime_error(128); 00078 ERROR_SPRINTF(errtxt, "{037 NEMD is a single node feature} "); 00079 return; 00080 } 00081 00082 /* first free old structures befor initializing new ones */ 00083 if(nemddata.n_slabs > -1) nemd_free(); 00084 /* exit nemd integration */ 00085 if(n_slabs == 0) return; 00086 00087 /* fill nemd structure */ 00088 nemddata.n_slabs = n_slabs; 00089 nemddata.top_slab = 0; 00090 nemddata.mid_slab = n_slabs/2; 00091 00092 nemddata.thickness = box_l[2]/(double)nemddata.n_slabs; 00093 nemddata.invthickness = 1.0 / nemddata.thickness; 00094 00095 nemddata.shear_rate = shear_rate; 00096 nemddata.slab_vel = time_step*shear_rate*box_l[2]/4.0; 00097 00098 nemddata.n_exchange = n_exchange; 00099 00100 nemddata.slab = (Slab *)malloc(nemddata.n_slabs*sizeof(Slab)); 00101 nemddata.velocity_profile = (double *)malloc(nemddata.n_slabs*sizeof(double)); 00102 00103 nemddata.momentum = 0.0; 00104 nemddata.momentum_norm = 0; 00105 00106 /* initialize slabs and velocity profile */ 00107 for(i=0;i<nemddata.n_slabs;i++) { 00108 nemddata.velocity_profile[i] = 0.0; 00109 00110 nemddata.slab[i].v_mean = 0.0; 00111 nemddata.slab[i].n_parts_in_slab = 0; 00112 nemddata.slab[i].v_min = 0.0; 00113 nemddata.slab[i].ind_min = 0; 00114 nemddata.slab[i].fastest = NULL; 00115 nemddata.slab[i].n_fastest = 0; 00116 nemddata.slab[i].vel_diff = 0.0; 00117 } 00118 /* allocate arrays for indices of fastest particles in slab */ 00119 if(nemddata.n_exchange > 0) { 00120 nemddata.slab[nemddata.top_slab].fastest = (int *)malloc(nemddata.n_exchange*sizeof(int)); 00121 nemddata.slab[nemddata.mid_slab].fastest = (int *)malloc(nemddata.n_exchange*sizeof(int)); 00122 } 00123 for(i=0;i<nemddata.n_exchange;i++) { 00124 nemddata.slab[nemddata.top_slab].fastest[i] = -1; 00125 nemddata.slab[nemddata.mid_slab].fastest[i] = -1; 00126 } 00127 nemddata.slab[nemddata.top_slab].v_min = -1e10; 00128 nemddata.slab[nemddata.mid_slab].v_min = +1e10; 00129 } 00130 00131 00132 00133 /*@}*/ 00134 00135 00136 void nemd_change_momentum() 00137 { 00138 int i; 00139 double tmp_v0; 00140 Slab *mid_slab, *top_slab; 00141 00142 if(nemd_method == NEMD_METHOD_OFF) return; 00143 00144 INTEG_TRACE(fprintf(stderr,"%d: nemd_change_momentum: Method %d\n",this_node,nemd_method)); 00145 00146 mid_slab = &nemddata.slab[nemddata.mid_slab]; 00147 top_slab = &nemddata.slab[nemddata.top_slab]; 00148 00149 if(nemd_method == NEMD_METHOD_EXCHANGE ) { 00150 /* exit if there are not enough particles */ 00151 INTEG_TRACE(fprintf(stderr,"%d: parts_in_slabs: top %d mid %d\n",this_node,top_slab->n_parts_in_slab,mid_slab->n_parts_in_slab)); 00152 if(mid_slab->n_fastest != nemddata.n_exchange || 00153 top_slab->n_fastest != nemddata.n_exchange) { 00154 char *errtxt = runtime_error(128 + ES_INTEGER_SPACE); 00155 ERROR_SPRINTF(errtxt,"{038 nemd_exchange_momentum: Not enough particles in slab!} "); 00156 /* cannot continue */ 00157 return; 00158 } 00159 00160 /* perform momentum exchange */ 00161 for(i=0;i<nemddata.n_exchange;i++) { 00162 /* store momentum change */ 00163 nemddata.momentum += local_particles[top_slab->fastest[i]]->m.v[0]; 00164 nemddata.momentum -= local_particles[mid_slab->fastest[i]]->m.v[0]; 00165 tmp_v0 = local_particles[mid_slab->fastest[i]]->m.v[0]; 00166 local_particles[mid_slab->fastest[i]]->m.v[0] = local_particles[top_slab->fastest[i]]->m.v[0]; 00167 local_particles[top_slab->fastest[i]]->m.v[0] = tmp_v0; 00168 } 00169 00170 /* prepare next round */ 00171 top_slab->n_fastest = 0; 00172 top_slab->v_min = -1e10; 00173 mid_slab->n_fastest = 0; 00174 mid_slab->v_min = 1e10; 00175 } 00176 else if (nemd_method == NEMD_METHOD_SHEARRATE) { 00177 double vel_mean; 00178 /* calculate velocity difference vel_diff = vel_required - vel_actual */ 00179 vel_mean = top_slab->v_mean/(double)top_slab->n_parts_in_slab; 00180 top_slab->vel_diff = nemddata.slab_vel - vel_mean; 00181 vel_mean = mid_slab->v_mean/(double)mid_slab->n_parts_in_slab; 00182 mid_slab->vel_diff = - (nemddata.slab_vel + vel_mean); 00183 /* store momentum change */ 00184 nemddata.momentum += top_slab->n_parts_in_slab*top_slab->vel_diff; 00185 nemddata.momentum -= mid_slab->n_parts_in_slab*mid_slab->vel_diff; 00186 } 00187 nemddata.momentum_norm ++; 00188 } 00189 00190 /************************************************************/ 00191 00192 void nemd_store_velocity_profile() 00193 { 00194 int i; 00195 00196 if(nemddata.n_slabs == -1) return; 00197 INTEG_TRACE(fprintf(stderr,"%d: nemd_store_velocity_profile:\n",this_node)); 00198 00199 for(i=0;i<nemddata.n_slabs;i++) { 00200 if(nemddata.slab[i].n_parts_in_slab == 0) fprintf(stderr,"Zero particles in slab %d!!!\n",i); 00201 nemddata.velocity_profile[i] += nemddata.slab[i].v_mean/(double)nemddata.slab[i].n_parts_in_slab; 00202 nemddata.slab[i].v_mean = 0.0; 00203 nemddata.slab[i].n_parts_in_slab = 0; 00204 } 00205 nemddata.profile_norm++; 00206 } 00207 00208 /************************************************************/ 00209 00210 #endif 00211
1.7.5.1