/// Broadcasts an InterpolationObject from rank 0 to all other ranks. /// /// It is commonly the case that the data needed to create the /// interpolation table is available on only one task (for example, only /// one task has read the data from a file). Broadcasting the table /// eliminates the need to put broadcast code in multiple table readers. /// /// \see eamBcastPotential void bcastInterpolationObject(InterpolationObject** table) { struct { int n; real_t x0, invDx; } buf; if (getMyRank() == 0) { buf.n = (*table)->n; buf.x0 = (*table)->x0; buf.invDx = (*table)->invDx; } bcastParallel(&buf, sizeof(buf), 0); if (getMyRank() != 0) { assert(*table == NULL); *table = comdMalloc(sizeof(InterpolationObject)); (*table)->n = buf.n; (*table)->x0 = buf.x0; (*table)->invDx = buf.invDx; (*table)->values = comdMalloc(sizeof(real_t) * (buf.n+3) ); (*table)->values++; } int valuesSize = sizeof(real_t) * ((*table)->n+3); bcastParallel((*table)->values-1, valuesSize, 0); }
/// Broadcasts an EamPotential from rank 0 to all other ranks. /// If the table coefficients are read from a file only rank 0 does the /// read. Hence we need to broadcast the potential to all other ranks. void eamBcastPotential(EamPotential* pot) { assert(pot); struct { real_t cutoff, mass, lat; char latticeType[8]; char name[3]; int atomicNo; } buf; if (getMyRank() == 0) { buf.cutoff = pot->cutoff; buf.mass = pot->mass; buf.lat = pot->lat; buf.atomicNo = pot->atomicNo; strcpy(buf.latticeType, pot->latticeType); strcpy(buf.name, pot->name); } bcastParallel(&buf, sizeof(buf), 0); pot->cutoff = buf.cutoff; pot->mass = buf.mass; pot->lat = buf.lat; pot->atomicNo = buf.atomicNo; strcpy(pot->latticeType, buf.latticeType); strcpy(pot->name, buf.name); bcastInterpolationObject(&pot->phi); bcastInterpolationObject(&pot->rho); bcastInterpolationObject(&pot->f); }
/// Check that the user input meets certain criteria. void sanityChecks(Command cmd, double cutoff, double latticeConst, char latticeType[8]) { int failCode = 0; // Check that domain grid matches number of ranks. (fail code 1) int nProcs = cmd.xproc * cmd.yproc * cmd.zproc; if (nProcs != getNRanks()) { failCode |= 1; if (printRank() ) fprintf(screenOut, "\nNumber of MPI ranks must match xproc * yproc * zproc\n"); } // Check whether simuation is too small (fail code 2) double minx = 2*cutoff*cmd.xproc; double miny = 2*cutoff*cmd.yproc; double minz = 2*cutoff*cmd.zproc; double sizex = cmd.nx*latticeConst; double sizey = cmd.ny*latticeConst; double sizez = cmd.nz*latticeConst; if ( sizex < minx || sizey < miny || sizez < minz) { failCode |= 2; if (printRank()) fprintf(screenOut,"\nSimulation too small.\n" " Increase the number of unit cells to make the simulation\n" " at least (%3.2f, %3.2f. %3.2f) Ansgstroms in size\n", minx, miny, minz); } // Check for supported lattice structure (fail code 4) if (strcasecmp(latticeType, "FCC") != 0) { failCode |= 4; if ( printRank() ) fprintf(screenOut, "\nOnly FCC Lattice type supported, not %s. Fatal Error.\n", latticeType); } int checkCode = failCode; bcastParallel(&checkCode, sizeof(int), 0); // This assertion can only fail if different tasks failed different // sanity checks. That should not be possible. assert(checkCode == failCode); if (failCode != 0) exit(failCode); }