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

Comparing branches/new_design/OOPSE-3.0/src/brains/SimCreator.cpp (file contents):
Revision 1726 by tim, Wed Nov 10 22:01:06 2004 UTC vs.
Revision 1727 by tim, Thu Nov 11 16:41:58 2004 UTC

# Line 183 | Line 183 | void SimCreator::mpiMolDivide(){
183   }
184  
185   #ifdef IS_MPI
186 < void SimCreator::mpiMolDivide(){
187 <
188 <    mpiSim = new mpiSimulation(info);
186 > void SimCreator::divideMolecules(SimInfo* info){
187 >    int nComponents;
188 >    MoleculeStamp ** compStamps;
189 >    randomSPRNG * myRandom;
190 >    int * componentsNmol;
191 >    int * AtomsPerProc;
192  
193 <    mpiSim->divideLabor();
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  
# Line 210 | Line 400 | Molecule* SimCreator::createMolecules(SimInfo* info) {
400        
401   }
402  
213
403   void SimSetup::compList(MakeStamps* stamps,SimInfo* info) {
404      int i;
405      char* id;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines