ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
nemd.c
Go to the documentation of this file.
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