ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/brains/SimCreator.cpp
(Generate patch)

Comparing branches/new_design/OOPSE-2.0/src/brains/SimCreator.cpp (file contents):
Revision 1712 by tim, Thu Nov 4 20:55:01 2004 UTC vs.
Revision 1727 by tim, Thu Nov 11 16:41:58 2004 UTC

# Line 22 | Line 22
22   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23   *
24   */
25
26 /**
27  * @file SimCreator.cpp
28  * @author tlin
29  * @date 11/03/2004
30  * @time 13:51am
31  * @version 1.0
32  */
25  
26 < #include "brains/SimCreator.hpp"  
26 > /**
27 > * @file SimCreator.cpp
28 > * @author tlin
29 > * @date 11/03/2004
30 > * @time 13:51am
31 > * @version 1.0
32 > */
33 >
34 > #include "brains/SimCreator.hpp"
35   namespace oopse {
36  
37   void SimSetup::parseFile(char* mdfile,  MakeStamps* stamps, Globals* globals){
# Line 63 | Line 63 | SimModel* SimCreator::createSim(const std::string& mdf
63   }
64  
65  
66 < SimModel* SimCreator::createSim(const std::string& mdfile) {
67 <    MakeStamps* stamps;
66 > SimInfo* SimCreator::createSim(const std::string& mdfile) {
67 >    MakeStamps* stamps = new MakeStamps();
68      
69      Globals* globals = new Globals();
70  
# Line 72 | Line 72 | SimModel* SimCreator::createSim(const std::string& mdf
72      parseFile(mdfile, stamps, globals);
73  
74      //create the force field
75 <    ForceFiled* ff = ForceFiledFactory::getInstance()->createForceField(globals->getForceField());
75 >    ForceFiled* ff = ForceFieldFactory::getInstance()->createObject(globals->getForceField());
76      
77 <    //create SimModel
78 <    model = new SimInfo();
77 >    //create SimInfo
78 >    SimInfo* info = new SimInfo();
79 >    info->setGlobals(globals);
80 >    info->setForceField(ff);
81 >
82 >    //extract the molecule stamps and add them into SimInfo
83 >    compList(stamps, info);
84      
85 <    //gather parameters
86 <    gatherParameters(model);
85 >    //gather parameters (SimCreator only retrieves the parameters which will be used to create
86 >    // the simulation)
87 >    gatherParameters(info);
88      
83
84
89      //divide the molecules and determine the global index of molecules
90 <
90 >    
91      //create the molecules
92 +    createMolecules(info);
93  
94 <    //create atoms, bonds, bend, torsions, rigidbodies
95 <
94 >    //set the global index of atoms, rigidbodies and cutoffgroups (only need to be set once, the
95 >    //global index will never change again). Local indices of atoms and rigidbodies are already set by
96 >    //MoleculeCreator class which actually delegates the responsibility to LocalIndexManager.
97 >    setGlobalIndices(info);
98 >    
99      //allocate memory for DataStorage(circular reference, need to break it)
100 <    model->setSnapshotManager(new SimSnapshotManager(model);
100 >    info->setSnapshotManager(new SimSnapshotManager(info);
101      
102 <    //load initial coordinates
103 <    DumpReader reader();
104 <    reader.readFrame(model);
102 >    //load initial coordinates, some extra information are pushed into SimInfo's property map ( such as
103 >    //eta, chi for NPT integrator)
104 >    DumpReader reader(info->getInitFilename());
105 >    int nframes = reader->getNframes();
106 >
107 >    if (nframes > 0) {
108 >        reader.readFrame(info, nframes - 1);
109 >    } else {
110 >        //invalid initial coordinate file
111 >        
112 >    }
113 >
114      
115      //initialize fortran    
116 <    return model;
116 >    
117 >    return info;
118   }    
119  
120 < void SimCreator::gatherParameters(SimModel* model) {
121 <    model->addProperty(new StringGenericData("Ensemble", globals->getForceFiled()));
122 <    model->addProperty(new DoubleGenericData("dt"), globals->getDt());
120 > void SimCreator::gatherParameters(SimInfo* info) {
121 >    //model->addProperty(new StringGenericData("Ensemble", globals->getForceFiled()));
122 >    //model->addProperty(new DoubleGenericData("dt"), globals->getDt());
123 >
124 >    //setup seed for random number generator
125 >    int seedValue;
126 >    Globals* globals = info->getGlobals();
127 >    
128 >    if (globals->haveSeed()){
129 >        seedValue = globals->getSeed();
130 >
131 >        if(seedValue / 1000000000 == 0){
132 >            sprintf(painCave.errMsg,
133 >            "Seed for sprng library should contain at least 9 digits\n"
134 >            "OOPSE will generate a seed for user\n");
135 >            painCave.isFatal = 0;
136 >            simError();
137 >
138 >    //using seed generated by system instead of invalid seed set by user
139 > #ifndef IS_MPI
140 >            seedValue = make_sprng_seed();
141 > #else
142 >            if (worldRank == 0){
143 >                seedValue = make_sprng_seed();
144 >            }
145 >            MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);  
146 > #endif      
147 >        } //end if (seedValue /1000000000 == 0)
148 >    } else{
149 >    
150 > #ifndef IS_MPI
151 >        seedValue = make_sprng_seed();
152 > #else
153 >        if (worldRank == 0){
154 >            seedValue = make_sprng_seed();
155 >        }
156 >        MPI_Bcast(&seedValue, 1, MPI_INT, 0, MPI_COMM_WORLD);  
157 > #endif
158 >    }//end of globals->haveSeed()
159 >    info->setSeed(seedValue);
160 >
161 >    //
162 >    std::string prefix;
163 > #ifdef IS_MPI
164 >    if (worldRank == 0){
165 > #endif // is_mpi
166 >      
167 >        if(globals->haveFinalConfig()) {
168 >            prefix = getPrefix(globals->getFinalConfig());  
169 >        } else {
170 >            prefix = getPrefix(mdfile_);
171 >        }
172 >        
173 >        info->setFinalConfFileName(prefix + ".eor");
174 >        info->setDumpFileName(prefix + ".dump");
175 >        info->setStatFileName(prefix + ".stat");
176 >
177 > #ifdef IS_MPI
178 >    }
179 > #endif    
180 >
181 >
182 >
183   }
184  
185   #ifdef IS_MPI
186 < void SimCreator::mpiMolDivide() {
186 > void SimCreator::divideMolecules(SimInfo* info){
187 >    int nComponents;
188 >    MoleculeStamp ** compStamps;
189 >    randomSPRNG * myRandom;
190 >    int * componentsNmol;
191 >    int * AtomsPerProc;
192  
193 +    double numerator;
194 +    double denominator;
195 +    double precast;
196 +    double x;
197 +    double y;
198 +    double a;
199 +    int old_atoms;
200 +    int add_atoms;
201 +    int new_atoms;
202  
203 +    int nTarget;
204 +    int molIndex;
205 +    int atomIndex;
206 +    int done;
207 +    int i;
208 +    int j;
209 +    int loops;
210 +    int which_proc;
211 +    int nmol_global,
212 +    nmol_local;
213 +    int natoms_global,
214 +
215 +    int baseSeed = info->getSeed();
216 +    CutoffGroupStamp * cg;
217 +
218 +    nComponents = info->nComponents;
219 +    compStamps = info->compStamps;
220 +    componentsNmol = info->componentsNmol;
221 +    AtomsPerProc = new int[parallelData->nProcessors];
222 +
223 +    parallelData->nMolGlobal = info->n_mol;
224 +
225 +    if (parallelData->nProcessors > parallelData->nMolGlobal) {
226 +        sprintf(painCave.errMsg,
227 +                "nProcessors (%d) > nMol (%d)\n"
228 +                    "\tThe number of processors is larger than\n"
229 +                    "\tthe number of molecules.  This will not result in a \n"
230 +                    "\tusable division of atoms for force decomposition.\n"
231 +                    "\tEither try a smaller number of processors, or run the\n"
232 +                    "\tsingle-processor version of OOPSE.\n",
233 +                parallelData->nProcessors,
234 +                parallelData->nMolGlobal);
235 +
236 +        painCave.isFatal = 1;
237 +        simError();
238 +    }
239 +
240 +    myRandom = new randomSPRNG(baseSeed);
241 +
242 +    a = 3.0 * parallelData->nMolGlobal / parallelData->nAtomsGlobal;
243 +
244 +    // Initialize things that we'll send out later:
245 +    for( i = 0; i < parallelData->nProcessors; i++ ) {
246 +        AtomsPerProc[i] = 0;
247 +    }
248 +
249 +    for( i = 0; i < parallelData->nMolGlobal; i++ ) {
250 +        // default to an error condition:
251 +        MolToProcMap[i] = -1;
252 +    }
253 +
254 +    if (parallelData->myNode == 0) {
255 +        numerator = info->n_atoms;
256 +        denominator = parallelData->nProcessors;
257 +        precast = numerator / denominator;
258 +        nTarget = (int)(precast + 0.5);
259 +
260 +        // Build the array of molecule component types first
261 +        molIndex = 0;
262 +
263 +        for( i = 0; i < nComponents; i++ ) {
264 +            for( j = 0; j < componentsNmol[i]; j++ ) {
265 +                molIndex++;
266 +            }
267 +        }
268 +
269 +        for( i = 0; i < molIndex; i++ ) {
270 +            done = 0;
271 +            loops = 0;
272 +
273 +            while (!done) {
274 +                loops++;
275 +
276 +                // Pick a processor at random
277 +
278 +                which_proc
279 +
280 +                = (int) (myRandom->getRandom() * parallelData->nProcessors);
281 +
282 +                // How many atoms does this processor have?
283 +
284 +                old_atoms = AtomsPerProc[which_proc];
285 +                add_atoms = compStamps[MolComponentType[i]]->getNAtoms();
286 +                new_atoms = old_atoms + add_atoms;
287 +
288 +                // If we've been through this loop too many times, we need
289 +                // to just give up and assign the molecule to this processor
290 +                // and be done with it.
291 +
292 +                if (loops > 100) {
293 +                    sprintf(
294 +                        painCave.errMsg,
295 +                        "I've tried 100 times to assign molecule %d to a "
296 +                            " processor, but can't find a good spot.\n"
297 +                            "I'm assigning it at random to processor %d.\n",
298 +                        i,
299 +                        which_proc);
300 +
301 +                    painCave.isFatal = 0;
302 +                    simError();
303 +
304 +                    MolToProcMap[i] = which_proc;
305 +                    AtomsPerProc[which_proc] += add_atoms;
306 +
307 +                    done = 1;
308 +                    continue;
309 +                }
310 +
311 +                // If we can add this molecule to this processor without sending
312 +                // it above nTarget, then go ahead and do it:
313 +
314 +                if (new_atoms <= nTarget) {
315 +                    MolToProcMap[i] = which_proc;
316 +                    AtomsPerProc[which_proc] += add_atoms;
317 +
318 +                    done = 1;
319 +                    continue;
320 +                }
321 +
322 +                // The only situation left is when new_atoms > nTarget.  We
323 +                // want to accept this with some probability that dies off the
324 +                // farther we are from nTarget
325 +
326 +                // roughly:  x = new_atoms - nTarget
327 +                //           Pacc(x) = exp(- a * x)
328 +                // where a = penalty / (average atoms per molecule)
329 +
330 +                x = (double)(new_atoms - nTarget);
331 +                y = myRandom->getRandom();
332 +
333 +                if (y < exp(- a * x)) {
334 +                    MolToProcMap[i] = which_proc;
335 +                    AtomsPerProc[which_proc] += add_atoms;
336 +
337 +                    done = 1;
338 +                    continue;
339 +                } else { continue; }
340 +            }
341 +        }
342 +
343 +        // Spray out this nonsense to all other processors:
344 +
345 +        MPI_Bcast(MolToProcMap, parallelData->nMolGlobal, MPI_INT, 0,
346 +                  MPI_COMM_WORLD);
347 +    } else {
348 +
349 +    // Listen to your marching orders from processor 0:
350 +
351 +        MPI_Bcast(MolToProcMap, parallelData->nMolGlobal, MPI_INT, 0,
352 +                  MPI_COMM_WORLD); }
353 +
354 +    // Let's all check for sanity:
355 +
356 +    nmol_local = 0;
357 +
358 +    for( i = 0; i < parallelData->nMolGlobal; i++ ) {
359 +        if (MolToProcMap[i] == parallelData->myNode) {
360 +            nmol_local++;
361 +        }
362 +    }
363 +
364 +    MPI_Allreduce(&nmol_local, &nmol_global, 1, MPI_INT, MPI_SUM,
365 +                  MPI_COMM_WORLD);
366 +
367 +    if (nmol_global != info->n_mol) {
368 +        sprintf(painCave.errMsg,
369 +                "The sum of all nmol_local, %d, did not equal the "
370 +                    "total number of molecules, %d.\n",
371 +                nmol_global,
372 +                info->n_mol);
373 +
374 +        painCave.isFatal = 1;
375 +        simError();
376 +    }
377 +
378 +    sprintf(checkPointMsg,
379 +            "Successfully divided the molecules among the processors.\n");
380 +    MPIcheckPoint();
381 +
382   }
383 + #endif
384  
385 + Molecule* SimCreator::createMolecules(SimInfo* info) {
386 +    MoleculeCreator molCreator;
387 +    int stampId;
388 +
389 +    
390 +    for (int i = 0; i < info->getNGlobalMolecules(); i++){
391 +        if (info->getMolToProc(i) == worldRank){
392 +
393 +            stampId = info->getMoleculeStampId(i);
394 +            Molecule* mol = molCreator.createMolecule(info->getForceField(),
395 +                                                                                info->getMoleculeStamp(stampId), stampId, i);
396 +                        
397 +            info->addMolecule(mol);
398 +        }
399 +    }        
400 +      
401 + }
402 +
403 + void SimSetup::compList(MakeStamps* stamps,SimInfo* info) {
404 +    int i;
405 +    char* id;
406 +    MoleculeStamp* currentStamp;
407 +    Component* the_components = info->getGlobals()->getComponents();
408 +    int n_components = info->getGlobals()->getNComponents();
409 +
410 +    if (!globals->haveNMol()){
411 +        // we don't have the total number of molecules, so we assume it is
412 +        // given in each component
413 +
414 +        for (i = 0; i < n_components; i++){
415 +            if (!the_components[i]->haveNMol()){
416 +                // we have a problem
417 +                sprintf(painCave.errMsg,
418 +                    "SimSetup Error. No global NMol or component NMol given.\n"
419 +                    "\tCannot calculate the number of atoms.\n");
420 +                painCave.isFatal = 1;
421 +                simError();
422 +            }
423 +
424 +            id = the_components[i]->getType();
425 +            currentStamp = stamps->extractMolStamp(id);
426 +            if (currentStamp == NULL){
427 +                sprintf(painCave.errMsg,
428 +                    "SimSetup error: Component \"%s\" was not found in the "
429 +                    "list of declared molecules\n",
430 +                    id);
431 +                painCave.isFatal = 1;
432 +                simError();
433 +            }      
434 +
435 +            info->addMoleculeStamp(currentStamp, the_components[i]->getNMol);
436 +          
437 +        } //end for (i = 0; i < n_components; i++)
438 +        
439 +    } else{
440 +        sprintf(painCave.errMsg,
441 +                "SimSetup error.\n"
442 +                "\tSorry, the ability to specify total"
443 +                " nMols and then give molfractions in the components\n"
444 +                "\tis not currently supported."
445 +                " Please give nMol in the components.\n");
446 +        painCave.isFatal = 1;
447 +        simError();
448 +    }
449 +  
450 + #ifdef IS_MPI
451 +  strcpy(checkPointMsg, "Component stamps successfully extracted\n");
452 +  MPIcheckPoint();
453 + #endif // is_mpi
454 + }
455 +
456 + void SimCreator::setGlobalIndices(SimInfo* info) {
457 +    typename SimInfo::MoleculeIterator mi;
458 +    typename Molecule::AtomIterator ai;
459 +    typename Molecule::RigidBodyIterator ri;
460 +    typename Molecule::CutoffGroupIterator ci;
461 +    Molecule* mol;
462 +    Atom* atom;
463 +    RigidBody* rb;
464 +    CutoffGroup* cg;
465 +    int beginAtomIndex;
466 +    int beginRigidBodyIndex;
467 +    int beginCutoffGroupIndex;
468 +
469 + #ifdef IS_MPI
470 +    beginAtomIndex = 0;
471 +    beginRigidBodyIndex = 0;
472 +    beginCutoffGroupIndex = 0;
473 + #else
474 +    int nproc;
475 +    int myNode;
476 +
477 +    myNode = worldRank;
478 +    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
479 +    
480 +    std::vector<int> tmpAtomsInProc(nproc, 0);
481 +    std::vector<int> tmpRigidBodiesInProc(nproc, 0);
482 +    std::vector<int> tmpCutoffGroupsInProc(nproc, 0);    
483 +    std::vector<int> NumAtomsInProc(nproc, 0);
484 +    std::vector<int> NumRigidBodiesInProc(nproc, 0);
485 +    std::vector<int> NumCutoffGroupsInProc(nproc, 0);
486 +
487 +    tmpAtomInProc[myNode] = info->getNAtoms();
488 +    tmpRigidBodiesInProc[myNode] = info->getNRigidBodiess();
489 +    tmpCutoffGroupsInProc[myNode] = info->getNCutoffGroupss();
490 +    
491 +    //do MPI_ALLREDUCE to exchange the total number of atoms, rigidbodies and cutoff groups
492 +    MPI_Allreduce(&tmpAtomsInProc[0], &NumAtomsInProc[0], nproc, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
493 +    MPI_Allreduce(&tmpRigidBodiesInProc[0], &NumRigidBodiesInProc[0], nproc, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
494 +    MPI_Allreduce(&tmpCutoffGroupsInProc[0], &NumCutoffGroupsInProc[0], nproc, MPI_INT,MPI_SUM, MPI_COMM_WORLD);
495 +
496 +    beginAtomIndex = 0;
497 +    beginRigidBodyIndex = 0;
498 +    beginCutoffGroupIndex = 0;
499 +
500 +    for (int i = 0; i < nproc; i++) {
501 +        beginAtomIndex += NumAtomsInProc[i];
502 +        beginRigidBodyIndex += NumRigidBodiesInProc[i];
503 +        beginCutoffGroupIndex += NumCutoffGroupsInProc[i];        
504 +    }
505 +    
506   #endif
507 +    
508 +    for (mol = info->beginMolecule(mi); mol != NULL; mol  = info->nextMolecule(mi)) {
509 +
510 +        //local index(index in DataStorge) of atom is important
511 +        for (atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
512 +            atom->setGlobalIndex(beginAtomIndex++);
513 +        }
514 +
515 +        for (rb = mol->beginRigidBody(ri); rb != NULL; rb = mol->nextRigidBody(ri)) {
516 +            rb->setGlobalIndex(beginRigidBodyIndex++);
517 +        }
518 +        
519 +        //local index of cutoff group is trivial, it only depends on the order of travesing
520 +        for (cg = mol->beginCutoffGroup(ci); cg != NULL; cg = mol->nextCutoffGroup(ci)) {
521 +            cg->setGlobalIndex(beginCutoffGroupIndex++);
522 +        }        
523 +        
524 +    }
525 + }
526 +
527   } //end namespace oopse

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines