// Calculate the RDF normalisation for the Box bool Box::calculateRDFNormalisation(ProcessPool& procPool, Data2D& boxNorm, double rdfRange, double rdfBinWidth, int nPoints) const { // Setup array - we will use a nominal bin width of 0.1 Angstroms and then interpolate to the rdfBinWidth afterwards const double binWidth = 0.1; const double rBinWidth = 1.0/binWidth; int bin, nBins = rdfRange / binWidth; Data2D normData; normData.initialise(nBins); Array<double>& y = normData.arrayY(); for (int n=0; n<nBins; ++n) normData.arrayX()[n] = (n+0.5)*binWidth; Vec3<double> centre = axes_*Vec3<double>(0.5,0.5,0.5); // Divide points over processes const int nPointsPerProcess = nPoints / procPool.nProcesses(); Messenger::print("--> Number of insertion points (per process) is %i\n", nPointsPerProcess); y = 0.0; for (int n=0; n<nPointsPerProcess; ++n) { bin = (randomCoordinate() - centre).magnitude() * rBinWidth; if (bin < nBins) y[bin] += 1.0; } if (!procPool.allSum(y.array(), nBins)) return false; // Normalise histogram data, and scale by volume and binWidth ratio y /= double(nPointsPerProcess*procPool.nProcesses()); y *= volume_ * (rdfBinWidth / binWidth); normData.interpolate(); // Write histogram data for random distribution if (procPool.isMaster()) normData.save("duq.box.random"); // Now we have the interpolated data, create the proper interpolated data nBins = rdfRange/rdfBinWidth; boxNorm.clear(); // Rescale against expected volume for spherical shells double shellVolume, r = 0.0, maxHalf = inscribedSphereRadius(), x = 0.5*rdfBinWidth; for (int n=0; n<nBins; ++n) { // We know that up to the maximum (orthogonal) half-cell width the normalisation should be exactly 1.0... if (x < maxHalf) boxNorm.addPoint(x, 1.0); else { shellVolume = (4.0/3.0)*PI*(pow(r+rdfBinWidth,3.0) - pow(r,3.0)); boxNorm.addPoint(x, shellVolume / normData.interpolated(x)); // boxNorm[n] = normData.interpolated(r); } r += rdfBinWidth; x += rdfBinWidth; } // Interpolate normalisation array boxNorm.interpolate(); // Write final box normalisation file if (procPool.isMaster()) boxNorm.save("duq.box.norm"); return true; }
// Calculate total forces within the system void DUQ::totalForces(ProcessPool& procPool, Configuration* cfg, double* fx, double* fy, double* fz, double cutoffSq) { /* * Calculates the total forces within the system, arising from inter-Grain PairPotential interactions * and intramolecular contributions. * * This is a serial routine (subroutines called from within are parallel). */ // Create a Timer Timer timer; // Calculate Grain forces timer.start(); grainForces(procPool, cfg, fx, fy, fz, cutoffSq); timer.stop(); Messenger::printVerbose("Time to do Grain forces was %s.\n", timer.timeString()); // Calculate intramolecular forces timer.start(); intramolecularForces(procPool, cfg, fx, fy, fz); timer.stop(); Messenger::printVerbose("Time to do intramolecular forces was %s.\n", timer.timeString()); // Gather forces together if (!procPool.allSum(fx, cfg->nAtoms())) return; if (!procPool.allSum(fy, cfg->nAtoms())) return; if (!procPool.allSum(fz, cfg->nAtoms())) return; }
int main(int argc, const char * argv[]) { if(argc != 2){ printf("Usage: ./xxx port(port stands for the port wanna listen on.)\n"); exit(1); } signal(SIGCHLD, SIG_IGN); if(!is_free()){ // exit(0); } int port = atoi(argv[1]); struct sockaddr_in addr; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); int server_socket = socket(AF_INET, SOCK_STREAM, 0); bind(server_socket, (struct sockaddr *) &addr, sizeof(addr)); listen(server_socket, 0); ProcessPool* pool = new ProcessPool(server_socket, 1, 10); pool->init(); pool->addTask(print, NULL); pool->start(); if(pool) delete(pool); exit(0); }
windows_process::~windows_process() { ProcessPool *pp = ProcPool(); GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator()); pp->condvar()->lock(); winGen->removeProcess(this); pp->condvar()->unlock(); // Do NOT close the process handle; that's handled by ContinueDebugEvent. Closing the file is okay. ::CloseHandle(hfile); }
// Broadcast data from Master to all Slaves bool Parameters::broadcast(ProcessPool& procPool) { #ifdef PARALLEL if (!procPool.broadcast(name_)) return false; if (!procPool.broadcast(description_)) return false; if (!procPool.broadcast(&sigma_, 1)) return false; if (!procPool.broadcast(&epsilon_, 1)) return false; if (!procPool.broadcast(&charge_, 1)) return false; #endif return true; }
// Execute Method bool Export::process(DUQ& duq, ProcessPool& procPool) { /* * Export data from the target Configuration(s) */ // Loop over target Configurations for (RefListItem<Configuration,bool>* ri = targetConfigurations_.first(); ri != NULL; ri = ri->next) { // Grab Configuration pointer Configuration* cfg = ri->item; // Retrieve control parameters from Configuration const char* saveTrajectory = variableAsChar(cfg, "SaveTrajectory"); /* * Save XYZ Trajectory */ if (!DUQSys::isEmpty(saveTrajectory)) { Messenger::print("Export: Appending to trajectory output file '%s'...\n", cfg->outputCoordinatesFile()); // Only the pool master saves the data if (procPool.isMaster()) { // Open the file LineParser parser; if (!parser.appendOutput(saveTrajectory)) { parser.closeFiles(); procPool.stop(); return false; } else if (!writeConfigurationXYZ(parser, cfg, cfg->name())) { Messenger::print("Export: Failed to append to trajectory file.\n"); parser.closeFiles(); procPool.stop(); return false; } procPool.proceed(); } else if (!procPool.decision()) return false; Messenger::print("Export: Finished appending trajectory file.\n"); } } return true; }
// Broadcast data bool VariableValue::broadcast(ProcessPool& procPool) { #ifdef PARALLEL // Broadcast type first, then value int tempType = type_; if (!procPool.broadcast(&tempType, 1)) return false; type_ = (VariableValue::ValueType) tempType; switch (type_) { case (VariableValue::BooleanType): if (!procPool.broadcast(valueB_)) return false; break; case (VariableValue::IntegerType): if (!procPool.broadcast(&valueI_, 1)) return false; break; case (VariableValue::DoubleType): if (!procPool.broadcast(&valueD_, 1)) return false; break; case (VariableValue::CharType): if (!procPool.broadcast(valueC_)) return false; break; case (VariableValue::IntegerArrayType): if (!procPool.broadcast(arrayI_)) return false; break; case (VariableValue::DoubleArrayType): if (!procPool.broadcast(arrayD_)) return false; break; default: Messenger::error("Broadcast of VariableValue failed - type_ %s not accounted for.\n", VariableValue::valueType(type_)); return false; } #endif return true; }
// Broadcast data from Master to all Slaves bool AtomType::broadcast(ProcessPool& procPool) { #ifdef PARALLEL int index; // Send name procPool.broadcast(name_); // Send element procPool.broadcast(&element_, 1); // Get index of Parameters, if (procPool.isMaster()) index = PeriodicTable::element(element_).indexOfParameters(parameters_); procPool.broadcast(&index, 1); parameters_ = PeriodicTable::element(element_).parameters(index); #endif return true; }
bool GeneratorMT::processWait(bool block) { ProcessPool *pp = ProcPool(); pp->condvar()->lock(); pthrd_printf("Checking for live processes\n"); while (!hasLiveProc() && !isExitingState()) { pthrd_printf("Checked and found no live processes\n"); if (!block) { pthrd_printf("Returning from non-blocking processWait\n"); pp->condvar()->broadcast(); pp->condvar()->unlock(); return false; } pp->condvar()->wait(); } pp->condvar()->broadcast(); pp->condvar()->unlock(); pthrd_printf("processWait returning true\n"); return true; }
// Calculate total intramolecular forces void DUQ::intramolecularForces(ProcessPool& procPool, Configuration* cfg, double* fx, double* fy, double* fz) { /* * Calculate the total intramolecular forces within the system, arising from Bond, Angle, and Torsion * terms in all molecules. * * This is a parallel routine. */ double distance, angle, force, dp, magji, magjk; int index, start, stride; Atom* i, *j, *k; Vec3<double> vecji, vecjk, forcei, forcek; // Set start/skip for parallel loop start = procPool.interleavedLoopStart(ProcessPool::OverPoolProcesses); stride = procPool.interleavedLoopStride(ProcessPool::OverPoolProcesses); // Main loop over molecules for (Molecule* mol = cfg->molecules(); mol != NULL; mol = mol->next) { // Bonds for (SpeciesBond* b = mol->species()->bonds(); b != NULL; b = b->next) { // Grab pointers to atoms involved in bond i = mol->atom(b->indexI()); j = mol->atom(b->indexJ()); // Determine whether we need to apply minimum image to the vector calculation if (cfg->useMim(i->grain()->cell(), j->grain()->cell())) vecji = cfg->box()->minimumVector(i, j); else vecji = j->r() - i->r(); // Get distance and normalise vector ready for force calculation distance = vecji.magAndNormalise(); // Determine final forces vecji *= b->force(distance); // Calculate forces index = b->i()->index(); fx[index] -= vecji.x; fy[index] -= vecji.y; fz[index] -= vecji.z; index = b->j()->index(); fx[index] += vecji.x; fy[index] += vecji.y; fz[index] += vecji.z; } // Angles for (SpeciesAngle* a = mol->species()->angles(); a != NULL; a = a->next) { // Grab pointers to atoms involved in angle i = mol->atom(a->indexI()); j = mol->atom(a->indexJ()); k = mol->atom(a->indexK()); // Determine whether we need to apply minimum image between 'j-i' and 'j-k' if (cfg->useMim(j->grain()->cell(), i->grain()->cell())) vecji = cfg->box()->minimumVector(j, i); else vecji = i->r() - j->r(); if (cfg->useMim(j->grain()->cell(), k->grain()->cell())) vecjk = cfg->box()->minimumVector(j, k); else vecjk = k->r() - j->r(); // Calculate angle magji = vecji.magAndNormalise(); magjk = vecjk.magAndNormalise(); angle = Box::angle(vecji, vecjk, dp); // Determine Angle force vectors for atoms force = a->force(angle); forcei = vecjk - vecji * dp; forcei *= force / magji; forcek = vecji - vecjk * dp; forcek *= force / magjk; // Store forces index = a->i()->index(); fx[index] += forcei.x; fy[index] += forcei.y; fz[index] += forcei.z; index = a->j()->index(); fx[index] -= forcei.x + forcek.x; fy[index] -= forcei.y + forcek.y; fz[index] -= forcei.z + forcek.z; index = a->k()->index(); fx[index] += forcek.x; fy[index] += forcek.y; fz[index] += forcek.z; } } }
// Calculate Grain forces within the system void DUQ::grainForces(ProcessPool& procPool, Configuration* cfg, double* fx, double* fy, double* fz, double cutoffSq) { /* * Calculates the total Grain forces within the system, i.e. the energy contributions from PairPotential * interactions between Grains. Any connections between Grains (which in reality correspond to proper chemical bonds * between Atoms) are automatically excluded. * * This is a parallel routine. */ // Initialise the Cell distributor const bool willBeModified = false, allowRepeats = false; cfg->initialiseCellDistribution(); // Create a ForcesKernel ForceKernel kernel(procPool, cfg->box(), potentialMap_); int cellId, n, m, start, stride; Cell* cell; Grain* grainI, *grainJ; // Set start/skip for parallel loop start = procPool.interleavedLoopStart(ProcessPool::OverGroups); stride = procPool.interleavedLoopStride(ProcessPool::OverGroups); while (cellId = cfg->nextAvailableCell(procPool, willBeModified, allowRepeats), cellId != Cell::AllCellsComplete) { // Check for valid cell if (cellId == Cell::NoCellsAvailable) { Messenger::printVerbose("Nothing for this process to do.\n"); cfg->finishedWithCell(procPool, willBeModified, cellId); continue; } cell = cfg->cell(cellId); Messenger::printVerbose("Cell %i now the target, containing %i Grains interacting with %i neighbours.\n", cellId, cell->nGrains(), cell->nTotalCellNeighbours()); /* * Calculation Begins */ for (n=start; n<cell->nGrains(); n += stride) { grainI = cell->grain(n); // Inter-Grain interactions in this Cell... for (m=n+1; m<cell->nGrains(); ++m) { grainJ = cell->grain(m); kernel.forces(grainI, grainJ, false, false, fx, fy, fz); } // Inter-Grain interactions between this Grain and those in Cell neighbours kernel.forces(grainI, cell->nCellNeighbours(), cell->cellNeighbours(), false, true, fx, fy, fz, ProcessPool::Individual); kernel.forces(grainI, cell->nMimCellNeighbours(), cell->mimCellNeighbours(), true, true, fx, fy, fz, ProcessPool::Individual); } /* * Calculation End */ // Must unlock the Cell when we are done with it! cfg->finishedWithCell(procPool, willBeModified, cellId); } }