ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/integrators/SMIPDForceManager.cpp
(Generate patch)

Comparing trunk/OOPSE-4/src/integrators/SMIPDForceManager.cpp (file contents):
Revision 3482 by chuckv, Fri Dec 5 16:20:39 2008 UTC vs.
Revision 3504 by gezelter, Wed May 13 22:27:29 2009 UTC

# Line 43 | Line 43
43   #include "integrators/SMIPDForceManager.hpp"
44   #include "math/CholeskyDecomposition.hpp"
45   #include "utils/OOPSEConstant.hpp"
46 #include "hydrodynamics/Sphere.hpp"
47 #include "hydrodynamics/Ellipsoid.hpp"
48 #include "utils/ElementsTable.hpp"
46   #include "math/ConvexHull.hpp"
47   #include "math/Triangle.hpp"
48  
49   namespace oopse {
50  
51 <  SMIPDForceManager::SMIPDForceManager(SimInfo* info) : ForceManager(info),
52 <                                                        forceTolerance_(1e-6),
56 <                                                        maxIterNum_(4) {
51 >  SMIPDForceManager::SMIPDForceManager(SimInfo* info) : ForceManager(info) {
52 >
53      simParams = info->getSimParams();
54      veloMunge = new Velocitizer(info);
55      
# Line 110 | Line 106 | namespace oopse {
106    
107      variance_ = 2.0 * OOPSEConstant::kb * targetTemp_ / dt_;
108  
109 <    // Build the hydroProp map:
110 <    std::map<std::string, HydroProp*> hydroPropMap;
115 <
109 >    // Build a vector of integrable objects to determine if the are
110 >    // surface atoms
111      Molecule* mol;
112      StuntDouble* integrableObject;
113      SimInfo::MoleculeIterator i;
114 <    Molecule::IntegrableObjectIterator  j;              
120 <    bool needHydroPropFile = false;
121 <    
122 <    for (mol = info->beginMolecule(i); mol != NULL;
123 <         mol = info->nextMolecule(i)) {
124 <      for (integrableObject = mol->beginIntegrableObject(j);
125 <           integrableObject != NULL;
126 <           integrableObject = mol->nextIntegrableObject(j)) {
127 <        
128 <        if (integrableObject->isRigidBody()) {
129 <          RigidBody* rb = static_cast<RigidBody*>(integrableObject);
130 <          if (rb->getNumAtoms() > 1) needHydroPropFile = true;
131 <        }
132 <        
133 <      }
134 <    }
135 <
136 <    hydroProps_.resize(info->getNIntegrableObjects());
137 <    
138 <    if (needHydroPropFile) {              
139 <      if (simParams->haveHydroPropFile()) {
140 <        hydroPropMap = parseFrictionFile(simParams->getHydroPropFile());
141 <      } else {              
142 <        sprintf( painCave.errMsg,
143 <                 "HydroPropFile must be set to a file name if SMIPDynamics\n"
144 <                 "\tis specified for rigidBodies which contain more than one atom\n"
145 <                 "\tTo create a HydroPropFile, run the \"Hydro\" program.\n\n");
146 <        painCave.severity = OOPSE_ERROR;
147 <        painCave.isFatal = 1;
148 <        simError();  
149 <      }      
150 <      
151 <
152 <
153 <
154 <
155 <
156 <      for (mol = info->beginMolecule(i); mol != NULL;
157 <           mol = info->nextMolecule(i)) {
158 <        for (integrableObject = mol->beginIntegrableObject(j);
159 <             integrableObject != NULL;
160 <             integrableObject = mol->nextIntegrableObject(j)) {
161 <
162 <          std::map<std::string, HydroProp*>::iterator iter = hydroPropMap.find(integrableObject->getType());
163 <          if (iter != hydroPropMap.end()) {
164 <            hydroProps_[integrableObject->getLocalIndex()] = iter->second;
165 <          } else {
166 <            sprintf( painCave.errMsg,
167 <                     "Can not find resistance tensor for atom [%s]\n",
168 <                     integrableObject->getType().c_str());
169 <            painCave.severity = OOPSE_ERROR;
170 <            painCave.isFatal = 1;
171 <            simError();  
172 <          }        
173 <        }
174 <      }
175 <    } else {
176 <      
177 <      std::map<std::string, HydroProp*> hydroPropMap;
178 <      for (mol = info->beginMolecule(i); mol != NULL;
179 <           mol = info->nextMolecule(i)) {
180 <        for (integrableObject = mol->beginIntegrableObject(j);
181 <             integrableObject != NULL;
182 <             integrableObject = mol->nextIntegrableObject(j)) {
183 <          Shape* currShape = NULL;
184 <
185 <          if (integrableObject->isAtom()){
186 <            Atom* atom = static_cast<Atom*>(integrableObject);
187 <            AtomType* atomType = atom->getAtomType();
188 <            if (atomType->isGayBerne()) {
189 <              DirectionalAtomType* dAtomType = dynamic_cast<DirectionalAtomType*>(atomType);              
190 <              GenericData* data = dAtomType->getPropertyByName("GayBerne");
191 <              if (data != NULL) {
192 <                GayBerneParamGenericData* gayBerneData = dynamic_cast<GayBerneParamGenericData*>(data);
193 <                
194 <                if (gayBerneData != NULL) {  
195 <                  GayBerneParam gayBerneParam = gayBerneData->getData();
196 <                  currShape = new Ellipsoid(V3Zero,
197 <                                            gayBerneParam.GB_l / 2.0,
198 <                                            gayBerneParam.GB_d / 2.0,
199 <                                            Mat3x3d::identity());
200 <                } else {
201 <                  sprintf( painCave.errMsg,
202 <                           "Can not cast GenericData to GayBerneParam\n");
203 <                  painCave.severity = OOPSE_ERROR;
204 <                  painCave.isFatal = 1;
205 <                  simError();  
206 <                }
207 <              } else {
208 <                sprintf( painCave.errMsg, "Can not find Parameters for GayBerne\n");
209 <                painCave.severity = OOPSE_ERROR;
210 <                painCave.isFatal = 1;
211 <                simError();    
212 <              }
213 <            } else {
214 <              if (atomType->isLennardJones()){
215 <                GenericData* data = atomType->getPropertyByName("LennardJones");
216 <                if (data != NULL) {
217 <                  LJParamGenericData* ljData = dynamic_cast<LJParamGenericData*>(data);
218 <                  if (ljData != NULL) {
219 <                    LJParam ljParam = ljData->getData();
220 <                    currShape = new Sphere(atom->getPos(), ljParam.sigma/2.0);
221 <                  } else {
222 <                    sprintf( painCave.errMsg,
223 <                             "Can not cast GenericData to LJParam\n");
224 <                    painCave.severity = OOPSE_ERROR;
225 <                    painCave.isFatal = 1;
226 <                    simError();          
227 <                  }      
228 <                }
229 <              } else {
230 <                int aNum = etab.GetAtomicNum((atom->getType()).c_str());
231 <                if (aNum != 0) {
232 <                  currShape = new Sphere(atom->getPos(), etab.GetVdwRad(aNum));
233 <                } else {
234 <                  sprintf( painCave.errMsg,
235 <                           "Could not find atom type in default element.txt\n");
236 <                  painCave.severity = OOPSE_ERROR;
237 <                  painCave.isFatal = 1;
238 <                  simError();          
239 <                }
240 <              }
241 <            }
242 <          }
243 <          HydroProp* currHydroProp = currShape->getHydroProp(viscosity_, targetTemp_);
244 <          std::map<std::string, HydroProp*>::iterator iter = hydroPropMap.find(integrableObject->getType());
245 <          if (iter != hydroPropMap.end()) {
246 <            hydroProps_[integrableObject->getLocalIndex()] = iter->second;
247 <          } else {
248 <            currHydroProp->complete();
249 <            hydroPropMap.insert(std::map<std::string, HydroProp*>::value_type(integrableObject->getType(), currHydroProp));
250 <            hydroProps_[integrableObject->getLocalIndex()] = currHydroProp;
251 <          }
252 <        }
253 <      }
254 <    }
114 >    Molecule::IntegrableObjectIterator  j;
115  
256    // Build a vector of integrable objects to determine if the are
257    // surface atoms
258    
116      for (mol = info_->beginMolecule(i); mol != NULL;
117           mol = info_->nextMolecule(i)) {          
118        for (integrableObject = mol->beginIntegrableObject(j);
# Line 265 | Line 122 | namespace oopse {
122        }
123      }  
124    }  
268
269  std::map<std::string, HydroProp*> SMIPDForceManager::parseFrictionFile(const std::string& filename) {
270    std::map<std::string, HydroProp*> props;
271    std::ifstream ifs(filename.c_str());
272    if (ifs.is_open()) {
273      
274    }
275    
276    const unsigned int BufferSize = 65535;
277    char buffer[BufferSize];  
278    while (ifs.getline(buffer, BufferSize)) {
279      HydroProp* currProp = new HydroProp(buffer);
280      props.insert(std::map<std::string, HydroProp*>::value_type(currProp->getName(), currProp));
281    }
282    
283    return props;
284  }
125    
126    void SMIPDForceManager::postCalculation(bool needStress){
127      SimInfo::MoleculeIterator i;
128      Molecule::IntegrableObjectIterator  j;
129      Molecule* mol;
130      StuntDouble* integrableObject;
291
292    RealType mass;
293    Vector3d pos;
294    Vector3d frc;
295    Mat3x3d A;
296    Mat3x3d Atrans;
297    Vector3d Tb;
298    Vector3d ji;
299    int index = 0;
131    
132      // Compute surface Mesh
133      surfaceMesh_->computeHull(localSites_);
# Line 307 | Line 138 | namespace oopse {
138      std::vector<Triangle> sMesh = surfaceMesh_->getMesh();
139      int nTriangles = sMesh.size();
140  
141 +    // Generate all of the necessary random forces
142 +    std::vector<Vector3d>  randNums = genTriangleForces(nTriangles, variance_);
143 +
144      // Loop over the mesh faces and apply external pressure to each
145      // of the faces
146      std::vector<Triangle>::iterator face;
147      std::vector<StuntDouble*>::iterator vertex;
148 <    int thisNumber = 0;
148 >    int thisFacet = 0;
149      for (face = sMesh.begin(); face != sMesh.end(); ++face){
150      
151        Triangle thisTriangle = *face;
# Line 320 | Line 154 | namespace oopse {
154        Vector3d unitNormal = thisTriangle.getNormal();
155        unitNormal.normalize();
156        Vector3d centroid = thisTriangle.getCentroid();
157 <      Vector3d extPressure = - unitNormal * (targetPressure_ * thisArea)
158 <        / OOPSEConstant::energyConvert;
159 <      
157 >      Vector3d facetVel = thisTriangle.getFacetVelocity();
158 >
159 >      Mat3x3d hydroTensor = thisTriangle.computeHydrodynamicTensor(viscosity_);
160 >
161 >      hydroTensor *= OOPSEConstant::viscoConvert;
162 >      Mat3x3d S;
163 >      CholeskyDecomposition(hydroTensor, S);
164 >
165 >      Vector3d extPressure = -unitNormal*(targetPressure_ * thisArea)/OOPSEConstant::energyConvert;      
166 >      Vector3d randomForce = S * randNums[thisFacet++];
167 >      Vector3d dragForce = -hydroTensor * facetVel;
168 >
169 >      Vector3d langevinForce = (extPressure + randomForce + dragForce);
170 >
171 >      // Apply triangle force to stuntdouble vertices
172        for (vertex = vertexSDs.begin(); vertex != vertexSDs.end(); ++vertex){
173          if ((*vertex) != NULL){
174 <          Vector3d vertexForce = extPressure/3.0;
175 <          (*vertex)->addFrc(vertexForce);
330 <          
174 >          Vector3d vertexForce = langevinForce / 3.0;
175 >          (*vertex)->addFrc(vertexForce);          
176            if ((*vertex)->isDirectional()){          
177              Vector3d vertexPos = (*vertex)->getPos();
178              Vector3d vertexCentroidVector = vertexPos - centroid;
# Line 336 | Line 181 | namespace oopse {
181          }  
182        }
183      }
339
340    // Now loop over all surface particles and apply the drag
341    // and random forces
342    
343    std::vector<StuntDouble*> surfaceSDs = surfaceMesh_->getSurfaceAtoms();
344    for (vertex = surfaceSDs.begin(); vertex != surfaceSDs.end(); ++vertex){
345      integrableObject = *vertex;      
346      index = integrableObject->getLocalIndex();
347      mass = integrableObject->getMass();
348      if (integrableObject->isDirectional()){
349        
350        // preliminaries for directional objects:
351        
352        A = integrableObject->getA();
353        Atrans = A.transpose();
354        Vector3d rcrLab = Atrans * hydroProps_[index]->getCOR();  
355
356        // apply random force and torque at center of resistance
357
358        Vector3d randomForceBody;
359        Vector3d randomTorqueBody;
360        genRandomForceAndTorque(randomForceBody, randomTorqueBody,
361                                index, variance_);
362        Vector3d randomForceLab = Atrans * randomForceBody;
363        Vector3d randomTorqueLab = Atrans * randomTorqueBody;
364        integrableObject->addFrc(randomForceLab);            
365        integrableObject->addTrq(randomTorqueLab + cross(rcrLab,
366                                                         randomForceLab ));
367
368        Mat3x3d I = integrableObject->getI();
369        Vector3d omegaBody;
370        
371        // What remains contains velocity explicitly, but the velocity required
372        // is at the full step: v(t + h), while we have initially the velocity
373        // at the half step: v(t + h/2).  We need to iterate to converge the
374        // friction force and friction torque vectors.
375        
376        // this is the velocity at the half-step:
184          
378        Vector3d vel =integrableObject->getVel();
379        Vector3d angMom = integrableObject->getJ();
380        
381        // estimate velocity at full-step using everything but friction forces:
382        
383        frc = integrableObject->getFrc();
384        Vector3d velStep = vel + (dt2_ /mass * OOPSEConstant::energyConvert) * frc;
385        
386        Tb = integrableObject->lab2Body(integrableObject->getTrq());
387        Vector3d angMomStep = angMom + (dt2_ * OOPSEConstant::energyConvert) * Tb;                            
388        
389        Vector3d omegaLab;
390        Vector3d vcdLab;
391        Vector3d vcdBody;
392        Vector3d frictionForceBody;
393        Vector3d frictionForceLab(0.0);
394        Vector3d oldFFL;  // used to test for convergence
395        Vector3d frictionTorqueBody(0.0);
396        Vector3d oldFTB;  // used to test for convergence
397        Vector3d frictionTorqueLab;
398        RealType fdot;
399        RealType tdot;
400
401        //iteration starts here:
402        
403        for (int k = 0; k < maxIterNum_; k++) {
404          
405          if (integrableObject->isLinear()) {
406            int linearAxis = integrableObject->linearAxis();
407            int l = (linearAxis +1 )%3;
408            int m = (linearAxis +2 )%3;
409            omegaBody[l] = angMomStep[l] /I(l, l);
410            omegaBody[m] = angMomStep[m] /I(m, m);
411            
412          } else {
413            omegaBody[0] = angMomStep[0] /I(0, 0);
414            omegaBody[1] = angMomStep[1] /I(1, 1);
415            omegaBody[2] = angMomStep[2] /I(2, 2);
416          }
417          
418          omegaLab = Atrans * omegaBody;
419          
420          // apply friction force and torque at center of resistance
421          
422          vcdLab = velStep + cross(omegaLab, rcrLab);      
423          vcdBody = A * vcdLab;
424          frictionForceBody = -(hydroProps_[index]->getXitt() * vcdBody + hydroProps_[index]->getXirt() * omegaBody);
425          oldFFL = frictionForceLab;
426          frictionForceLab = Atrans * frictionForceBody;
427          oldFTB = frictionTorqueBody;
428          frictionTorqueBody = -(hydroProps_[index]->getXitr() * vcdBody + hydroProps_[index]->getXirr() * omegaBody);
429          frictionTorqueLab = Atrans * frictionTorqueBody;
430          
431          // re-estimate velocities at full-step using friction forces:
432              
433          velStep = vel + (dt2_ / mass * OOPSEConstant::energyConvert) * (frc + frictionForceLab);
434          angMomStep = angMom + (dt2_ * OOPSEConstant::energyConvert) * (Tb + frictionTorqueBody);
435
436          // check for convergence (if the vectors have converged, fdot and tdot will both be 1.0):
437              
438          fdot = dot(frictionForceLab, oldFFL) / frictionForceLab.lengthSquare();
439          tdot = dot(frictionTorqueBody, oldFTB) / frictionTorqueBody.lengthSquare();
440          
441          if (fabs(1.0 - fdot) <= forceTolerance_ && fabs(1.0 - tdot) <= forceTolerance_)
442            break; // iteration ends here
443        }
444        
445        integrableObject->addFrc(frictionForceLab);
446        integrableObject->addTrq(frictionTorqueLab + cross(rcrLab, frictionForceLab));
447
448            
449      } else {
450        //spherical atom
451
452        Vector3d randomForce;
453        Vector3d randomTorque;
454        genRandomForceAndTorque(randomForce, randomTorque, index, variance_);
455        integrableObject->addFrc(randomForce);            
456        
457        // What remains contains velocity explicitly, but the velocity required
458        // is at the full step: v(t + h), while we have initially the velocity
459        // at the half step: v(t + h/2).  We need to iterate to converge the
460        // friction force vector.
461        
462        // this is the velocity at the half-step:
463        
464        Vector3d vel =integrableObject->getVel();
465        
466        //estimate velocity at full-step using everything but friction forces:          
467        
468        frc = integrableObject->getFrc();
469        Vector3d velStep = vel + (dt2_ / mass * OOPSEConstant::energyConvert) * frc;
470        
471        Vector3d frictionForce(0.0);
472        Vector3d oldFF;  // used to test for convergence
473        RealType fdot;
474        
475        //iteration starts here:
476        
477        for (int k = 0; k < maxIterNum_; k++) {
478          
479          oldFF = frictionForce;                            
480          frictionForce = -hydroProps_[index]->getXitt() * velStep;
481          //frictionForce = -gamma_t*velStep;
482          // re-estimate velocities at full-step using friction forces:
483          
484          velStep = vel + (dt2_ / mass * OOPSEConstant::energyConvert) * (frc + frictionForce);
485          
486          // check for convergence (if the vector has converged, fdot will be 1.0):
487          
488          fdot = dot(frictionForce, oldFF) / frictionForce.lengthSquare();
489          
490          if (fabs(1.0 - fdot) <= forceTolerance_)
491            break; // iteration ends here
492        }
493        
494        integrableObject->addFrc(frictionForce);
495                
496      }      
497    }
498        
185      veloMunge->removeComDrift();
186      veloMunge->removeAngularDrift();
187  
# Line 504 | Line 190 | namespace oopse {
190      ForceManager::postCalculation(needStress);  
191    }
192  
193 <  void SMIPDForceManager::genRandomForceAndTorque(Vector3d& force,
194 <                                                  Vector3d& torque,
195 <                                                  unsigned int index,
196 <                                                  RealType variance) {
511 <        
512 <    Vector<RealType, 6> Z;
513 <    Vector<RealType, 6> generalForce;
193 >  
194 >  std::vector<Vector3d> SMIPDForceManager::genTriangleForces(int nTriangles,
195 >                                                             RealType variance)
196 >  {
197      
198 <    Z[0] = randNumGen_.randNorm(0, variance);
199 <    Z[1] = randNumGen_.randNorm(0, variance);
200 <    Z[2] = randNumGen_.randNorm(0, variance);
201 <    Z[3] = randNumGen_.randNorm(0, variance);
519 <    Z[4] = randNumGen_.randNorm(0, variance);
520 <    Z[5] = randNumGen_.randNorm(0, variance);
198 >    // zero fill the random vector before starting:
199 >    std::vector<Vector3d> gaussRand;
200 >    gaussRand.resize(nTriangles);
201 >    std::fill(gaussRand.begin(), gaussRand.end(), V3Zero);
202      
203 <
204 <    generalForce = hydroProps_[index]->getS()*Z;
203 > #ifdef IS_MPI
204 >    if (worldRank == 0) {
205 > #endif
206 >      RealType rx, ry, rz;
207 >      for (int i = 0; i < nTriangles; i++) {
208 >        rx = randNumGen_.randNorm(0.0, variance);
209 >        ry = randNumGen_.randNorm(0.0, variance);
210 >        rz = randNumGen_.randNorm(0.0, variance);
211 >        gaussRand[i][0] = rx;
212 >        gaussRand[i][1] = ry;
213 >        gaussRand[i][2] = rz;
214 >      }
215 > #ifdef IS_MPI
216 >    }
217 > #endif
218      
219 <    force[0] = generalForce[0];
220 <    force[1] = generalForce[1];
221 <    force[2] = generalForce[2];
222 <    torque[0] = generalForce[3];
223 <    torque[1] = generalForce[4];
224 <    torque[2] = generalForce[5];    
225 <  }
219 >    // push these out to the other processors
220 >    
221 > #ifdef IS_MPI
222 >    if (worldRank == 0) {
223 >      MPI_Bcast(&gaussRand[0], nTriangles*3 , MPI_REALTYPE, 0, MPI_COMM_WORLD);
224 >    } else {
225 >      MPI_Bcast(&gaussRand[0], nTriangles*3, MPI_REALTYPE, 0, MPI_COMM_WORLD);
226 >    }
227 > #endif
228 >    
229 >    return gaussRand;
230 >  }
231   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines