// 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; }
// 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 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; }