void Firehose::getParameters(){ Project::getParameters(); typedef Readparameters RP; RP::get("Firehose.Bx", this->Bx); RP::get("Firehose.By", this->By); RP::get("Firehose.Bz", this->Bz); RP::get("Firehose.lambda", this->lambda); RP::get("Firehose.amp", this->amp); // Per-population parameters for(uint i=0; i< getObjectWrapper().particleSpecies.size(); i++) { const std::string& pop = getObjectWrapper().particleSpecies[i].name; FirehoseSpeciesParameters sP; RP::get(pop + "_Firehose.rho1", sP.rho[1]); RP::get(pop + "_Firehose.rho2", sP.rho[2]); RP::get(pop + "_Firehose.Tx1", sP.Tx[1]); RP::get(pop + "_Firehose.Tx2", sP.Tx[2]); RP::get(pop + "_Firehose.Ty1", sP.Ty[1]); RP::get(pop + "_Firehose.Ty2", sP.Ty[2]); RP::get(pop + "_Firehose.Tz1", sP.Tz[1]); RP::get(pop + "_Firehose.Tz2", sP.Tz[2]); RP::get(pop + "_Firehose.Vx1", sP.Vx[1]); RP::get(pop + "_Firehose.Vx2", sP.Vx[2]); RP::get(pop + "_Firehose.Vy1", sP.Vy[1]); RP::get(pop + "_Firehose.Vy2", sP.Vy[2]); RP::get(pop + "_Firehose.Vz1", sP.Vz[1]); RP::get(pop + "_Firehose.Vz2", sP.Vz[2]); RP::get(pop + "_Firehose.nSpaceSamples", sP.nSpaceSamples); RP::get(pop + "_Firehose.nVelocitySamples", sP.nVelocitySamples); speciesParams.push_back(sP); } }
void MultiPeak::addParameters(){ typedef Readparameters RP; RP::add("MultiPeak.Bx", "Magnetic field x component (T)", 0.0); RP::add("MultiPeak.By", "Magnetic field y component (T)", 0.0); RP::add("MultiPeak.Bz", "Magnetic field z component (T)", 0.0); RP::add("MultiPeak.dBx", "Magnetic field x component cosine perturbation amplitude (T)", 0.0); RP::add("MultiPeak.dBy", "Magnetic field y component cosine perturbation amplitude (T)", 0.0); RP::add("MultiPeak.dBz", "Magnetic field z component cosine perturbation amplitude (T)", 0.0); RP::add("MultiPeak.magXPertAbsAmp", "Absolute amplitude of the random magnetic perturbation along x (T)", 1.0e-9); RP::add("MultiPeak.magYPertAbsAmp", "Absolute amplitude of the random magnetic perturbation along y (T)", 1.0e-9); RP::add("MultiPeak.magZPertAbsAmp", "Absolute amplitude of the random magnetic perturbation along z (T)", 1.0e-9); RP::add("MultiPeak.lambda", "B cosine perturbation wavelength (m)", 1.0); RP::add("MultiPeak.nVelocitySamples", "Number of sampling points per velocity dimension", 2); RP::add("MultiPeak.densityModel","Which spatial density model is used?",string("uniform")); // Per-population parameters for(uint i=0; i< getObjectWrapper().particleSpecies.size(); i++) { const std::string& pop = getObjectWrapper().particleSpecies[i].name; RP::add(pop+"_MultiPeak.n", "Number of peaks to create", 0); RP::addComposing(pop+"_MultiPeak.rho", "Number density (m^-3)"); RP::addComposing(pop+"_MultiPeak.Tx", "Temperature (K)"); RP::addComposing(pop+"_MultiPeak.Ty", "Temperature"); RP::addComposing(pop+"_MultiPeak.Tz", "Temperature"); RP::addComposing(pop+"_MultiPeak.Vx", "Bulk velocity x component (m/s)"); RP::addComposing(pop+"_MultiPeak.Vy", "Bulk velocity y component (m/s)"); RP::addComposing(pop+"_MultiPeak.Vz", "Bulk velocity z component (m/s)"); RP::addComposing(pop+"_MultiPeak.rhoPertAbsAmp", "Absolute amplitude of the density perturbation"); } }
void Firehose::addParameters(){ typedef Readparameters RP; RP::add("Firehose.Bx", "Magnetic field x component (T)", 0.0); RP::add("Firehose.By", "Magnetic field y component (T)", 0.0); RP::add("Firehose.Bz", "Magnetic field z component (T)", 0.0); RP::add("Firehose.lambda", "Initial perturbation wavelength (m)", 0.0); RP::add("Firehose.amp", "Initial perturbation amplitude (m)", 0.0); // Per-population parameters for(uint i=0; i< getObjectWrapper().particleSpecies.size(); i++) { const std::string& pop = getObjectWrapper().particleSpecies[i].name; RP::add(pop + "_Firehose.rho1", "Number density, first peak (m^-3)", 0.0); RP::add(pop + "_Firehose.rho2", "Number density, second peak (m^-3)", 0.0); RP::add(pop + "_Firehose.Tx1", "Temperature x, first peak (K)", 0.0); RP::add(pop + "_Firehose.Tx2", "Temperature x, second peak (K)", 0.0); RP::add(pop + "_Firehose.Ty1", "Temperature y, first peak (K)", 0.0); RP::add(pop + "_Firehose.Ty2", "Temperature y, second peak (K)", 0.0); RP::add(pop + "_Firehose.Tz1", "Temperature z, first peak (K)", 0.0); RP::add(pop + "_Firehose.Tz2", "Temperature z, second peak (K)", 0.0); RP::add(pop + "_Firehose.Vx1", "Bulk velocity x component, first peak (m/s)", 0.0); RP::add(pop + "_Firehose.Vx2", "Bulk velocity x component, second peak (m/s)", 0.0); RP::add(pop + "_Firehose.Vy1", "Bulk velocity y component, first peak (m/s)", 0.0); RP::add(pop + "_Firehose.Vy2", "Bulk velocity y component, second peak (m/s)", 0.0); RP::add(pop + "_Firehose.Vz1", "Bulk velocity z component, first peak (m/s)", 0.0); RP::add(pop + "_Firehose.Vz2", "Bulk velocity z component, second peak (m/s)", 0.0); RP::add(pop + "_Firehose.nSpaceSamples", "Number of sampling points per spatial dimension", 2); RP::add(pop + "_Firehose.nVelocitySamples", "Number of sampling points per velocity dimension", 5); } }
Real Larmor::getDistribValue(creal& x, creal& y, creal& z, creal& vx, creal& vy, creal& vz, const uint popID) const { creal kb = physicalconstants::K_B; creal mass = getObjectWrapper().particleSpecies[popID].mass; return exp(- mass * ((vx-this->VX0)*(vx-this->VX0) + (vy-this->VY0)*(vy-this->VY0)+ (vz-this->VZ0)*(vz-this->VZ0)) / (2.0 * kb * this->TEMPERATURE))* exp(-pow(x-Parameters::xmax/2.5, 2.0)/pow(this->SCA_X, 2.0))*exp(-pow(y-Parameters::ymax/2.0, 2.0)/pow(this->SCA_Y, 2.0)); }
void Harris::addParameters(){ typedef Readparameters RP; RP::add("Harris.Scale_size", "Harris sheet scale size (m)", 150000.0); RP::add("Harris.BX0", "Magnetic field at infinity (T)", 8.33061003094e-8); RP::add("Harris.BY0", "Magnetic field at infinity (T)", 8.33061003094e-8); RP::add("Harris.BZ0", "Magnetic field at infinity (T)", 8.33061003094e-8); // Per-population parameters for(uint i=0; i< getObjectWrapper().particleSpecies.size(); i++) { const std::string& pop = getObjectWrapper().particleSpecies[i].name; RP::add(pop + "_Harris.Temperature", "Temperature (K)", 2.0e6); RP::add(pop + "_Harris.rho", "Number density at infinity (m^-3)", 1.0e7); RP::add(pop + "_Harris.nSpaceSamples", "Number of sampling points per spatial dimension.", 2); RP::add(pop + "_Harris.nVelocitySamples", "Number of sampling points per velocity dimension.", 2); } }
void MultiPeak::getParameters(){ typedef Readparameters RP; Project::getParameters(); RP::get("MultiPeak.Bx", this->Bx); RP::get("MultiPeak.By", this->By); RP::get("MultiPeak.Bz", this->Bz); RP::get("MultiPeak.magXPertAbsAmp", this->magXPertAbsAmp); RP::get("MultiPeak.magYPertAbsAmp", this->magYPertAbsAmp); RP::get("MultiPeak.magZPertAbsAmp", this->magZPertAbsAmp); RP::get("MultiPeak.dBx", this->dBx); RP::get("MultiPeak.dBy", this->dBy); RP::get("MultiPeak.dBz", this->dBz); RP::get("MultiPeak.lambda", this->lambda); RP::get("MultiPeak.nVelocitySamples", this->nVelocitySamples); // Per-population parameters for(uint i=0; i< getObjectWrapper().particleSpecies.size(); i++) { const std::string& pop = getObjectWrapper().particleSpecies[i].name; MultiPeakSpeciesParameters sP; RP::get(pop + "_MultiPeak.n", sP.numberOfPeaks); RP::get(pop + "_MultiPeak.rho",sP.rho); RP::get(pop + "_MultiPeak.Tx", sP.Tx); RP::get(pop + "_MultiPeak.Ty", sP.Ty); RP::get(pop + "_MultiPeak.Tz", sP.Tz); RP::get(pop + "_MultiPeak.Vx", sP.Vx); RP::get(pop + "_MultiPeak.Vy", sP.Vy); RP::get(pop + "_MultiPeak.Vz", sP.Vz); RP::get(pop + "_MultiPeak.rhoPertAbsAmp", sP.rhoPertAbsAmp); if(!sP.isConsistent()) { cerr << "You should define all parameters (MultiPeak.rho, MultiPeak.Tx, MultiPeak.Ty, MultiPeak.Tz, MultiPeak.Vx, MultiPeak.Vy, MultiPeak.Vz, MultiPeak.rhoPertAbsAmp) for all " << sP.numberOfPeaks << " peaks of population " << pop << "." << endl; abort(); } speciesParams.push_back(sP); } string densModelString; RP::get("MultiPeak.densityModel",densModelString); if (densModelString == "uniform") densityModel = Uniform; else if (densModelString == "testcase") densityModel = TestCase; }
Real Larmor::calcPhaseSpaceDensity(creal& x, creal& y, creal& z, creal& dx, creal& dy, creal& dz, creal& vx, creal& vy, creal& vz, creal& dvx, creal& dvy, creal& dvz,const uint popID) const { const size_t meshID = getObjectWrapper().particleSpecies[popID].velocityMesh; vmesh::MeshParameters& meshParams = getObjectWrapper().velocityMeshes[meshID]; if (vx < meshParams.meshMinLimits[0] + 0.5*dvx || vy < meshParams.meshMinLimits[1] + 0.5*dvy || vz < meshParams.meshMinLimits[2] + 0.5*dvz || vx > meshParams.meshMaxLimits[0] - 1.5*dvx || vy > meshParams.meshMaxLimits[1] - 1.5*dvy || vz > meshParams.meshMaxLimits[2] - 1.5*dvz) { return 0.0; } creal mass = getObjectWrapper().particleSpecies[popID].mass; creal kb = physicalconstants::K_B; creal d_x = dx / (this->nSpaceSamples-1); creal d_y = dy / (this->nSpaceSamples-1); creal d_z = dz / (this->nSpaceSamples-1); creal d_vx = dvx / (this->nVelocitySamples-1); creal d_vy = dvy / (this->nVelocitySamples-1); creal d_vz = dvz / (this->nVelocitySamples-1); Real avg = 0.0; for (uint i=0; i<this->nSpaceSamples; ++i) for (uint j=0; j<this->nSpaceSamples; ++j) for (uint k=0; k<this->nSpaceSamples; ++k) for (uint vi=0; vi<this->nVelocitySamples; ++vi) for (uint vj=0; vj<this->nVelocitySamples; ++vj) for (uint vk=0; vk<this->nVelocitySamples; ++vk) { avg += getDistribValue(x+i*d_x, y+j*d_y, z+k*d_z, vx+vi*d_vx, vy+vj*d_vy, vz+vk*d_vz, popID); } creal result = avg *this->DENSITY * pow(mass / (2.0 * M_PI * kb * this->TEMPERATURE), 1.5) / (this->nSpaceSamples*this->nSpaceSamples*this->nSpaceSamples) / (this->nVelocitySamples*this->nVelocitySamples*this->nVelocitySamples); if(result < this->maxwCutoff) { return 0.0; } else { return result; } }
void Harris::getParameters(){ Project::getParameters(); typedef Readparameters RP; RP::get("Harris.Scale_size", this->SCA_LAMBDA); RP::get("Harris.BX0", this->BX0); RP::get("Harris.BY0", this->BY0); RP::get("Harris.BZ0", this->BZ0); // Per-population parameters for(uint i=0; i< getObjectWrapper().particleSpecies.size(); i++) { const std::string& pop = getObjectWrapper().particleSpecies[i].name; HarrisSpeciesParameters sP; RP::get(pop + "_Harris.Temperature", sP.TEMPERATURE); RP::get(pop + "_Harris.rho", sP.DENSITY); RP::get(pop + "_Harris.nSpaceSamples", sP.nSpaceSamples); RP::get(pop + "_Harris.nVelocitySamples", sP.nVelocitySamples); speciesParams.push_back(sP); } }
std::vector<string> RepositoryXL::callerKey(const std::vector<string> &objectList) { std::vector<string> ret; for (std::vector<string>::const_iterator i = objectList.begin(); i != objectList.end(); ++i) { string idStrip = CallingRange::getStub(*i); const shared_ptr<ObjectWrapperXL>& objectWrapperXL = boost::static_pointer_cast<ObjectWrapperXL>( getObjectWrapper(idStrip)); ret.push_back(objectWrapperXL->callerKey()); } return ret; }
Real Harris::getDistribValue( creal& x,creal& y, creal& z, creal& vx, creal& vy, creal& vz, creal& dvx, creal& dvy, creal& dvz, const uint popID ) const { const HarrisSpeciesParameters& sP = speciesParams[popID]; Real mass = getObjectWrapper().particleSpecies[popID].mass; return sP.DENSITY * pow(mass / (2.0 * M_PI * physicalconstants::K_B * sP.TEMPERATURE), 1.5) * ( 5.0 / pow(cosh(x / (this->SCA_LAMBDA)), 2.0) * exp(- mass * (pow(vx, 2.0) + pow(vy, 2.0) + pow(vz, 2.0)) / (2.0 * physicalconstants::K_B * sP.TEMPERATURE)) + exp(- mass * (pow(vx, 2.0) + pow(vy, 2.0) + pow(vz, 2.0)) / (2.0 * physicalconstants::K_B * sP.TEMPERATURE))); }
Real MultiPeak::getDistribValue(creal& vx, creal& vy, creal& vz, creal& dvx, creal& dvy, creal& dvz,const uint popID) const { const MultiPeakSpeciesParameters& sP = speciesParams[popID]; creal mass = getObjectWrapper().particleSpecies[popID].mass; creal kb = physicalconstants::K_B; Real value = 0.0; for (uint i=0; i<sP.numberOfPeaks; ++i) { value += (sP.rho[i] + sP.rhoPertAbsAmp[i] * rhoRnd) * pow(mass / (2.0 * M_PI * kb ), 1.5) * 1.0 / sqrt(sP.Tx[i]*sP.Ty[i]*sP.Tz[i]) * exp(- mass * (pow(vx - sP.Vx[i], 2.0) / (2.0 * kb * sP.Tx[i]) + pow(vy - sP.Vy[i], 2.0) / (2.0 * kb * sP.Ty[i]) + pow(vz - sP.Vz[i], 2.0) / (2.0 * kb * sP.Tz[i]))); } return value; }
Real Firehose::getDistribValue( creal& x, creal& y, creal& vx, creal& vy, creal& vz, creal& dvx, creal& dvy, creal& dvz, const uint popID) const { const FirehoseSpeciesParameters& sP = speciesParams[popID]; creal mass = getObjectWrapper().particleSpecies[popID].mass; creal kb = physicalconstants::K_B; Real Vx = profile(sP.Vx[1],sP.Vx[1], x); return sP.rho[1] * pow(mass / (2.0 * M_PI * kb * sP.Tx[1]), 1.5) * exp(- mass * (pow(vx - Vx, 2.0) / (2.0 * kb * sP.Tx[1]) + pow(vy - sP.Vy[1], 2.0) / (2.0 * kb * sP.Ty[1]) + pow(vz - sP.Vz[1], 2.0) / (2.0 * kb * sP.Tz[1]))); // this->rho[2] * pow(mass / (2.0 * M_PI * kb * this->Tx[2]), 1.5) * // exp(- mass * (pow(vx - this->Vx[2], 2.0) / (2.0 * kb * this->Tx[2]) + // pow(vy - this->Vy[2], 2.0) / (2.0 * kb * this->Ty[2]) + // pow(vz - this->Vz[2], 2.0) / (2.0 * kb * this->Tz[2]))); }
void Larmor::getParameters() { Project::getParameters(); typedef Readparameters RP; if(getObjectWrapper().particleSpecies.size() > 1) { std::cerr << "The selected project does not support multiple particle populations! Aborting in " << __FILE__ << " line " << __LINE__ << std::endl; abort(); } RP::get("Larmor.BX0", this->BX0); RP::get("Larmor.BY0", this->BY0); RP::get("Larmor.BZ0", this->BZ0); RP::get("Larmor.VX0", this->VX0); RP::get("Larmor.VY0", this->VY0); RP::get("Larmor.VZ0", this->VZ0); RP::get("Larmor.rho", this->DENSITY); RP::get("Larmor.Temperature", this->TEMPERATURE); RP::get("Larmor.nSpaceSamples", this->nSpaceSamples); RP::get("Larmor.nVelocitySamples", this->nVelocitySamples); RP::get("Larmor.maxwCutoff", this->maxwCutoff); RP::get("Larmor.Scale_x", this->SCA_X); RP::get("Larmor.Scale_y", this->SCA_Y); }
/*! * WARNING This assumes that the velocity space is isotropic (same resolution in vx, vy, vz). */ std::vector<vmesh::GlobalID> TriAxisSearch::findBlocksToInitialize(SpatialCell* cell,const uint popID) const { set<vmesh::GlobalID> blocksToInitialize; bool search; unsigned int counter; creal x = cell->parameters[CellParams::XCRD]; creal y = cell->parameters[CellParams::YCRD]; creal z = cell->parameters[CellParams::ZCRD]; creal dx = cell->parameters[CellParams::DX]; creal dy = cell->parameters[CellParams::DY]; creal dz = cell->parameters[CellParams::DZ]; const uint8_t refLevel = 0; creal dvxCell = cell->get_velocity_grid_cell_size(popID,refLevel)[0]; creal dvyCell = cell->get_velocity_grid_cell_size(popID,refLevel)[1]; creal dvzCell = cell->get_velocity_grid_cell_size(popID,refLevel)[2]; creal dvxBlock = cell->get_velocity_grid_block_size(popID,refLevel)[0]; creal dvyBlock = cell->get_velocity_grid_block_size(popID,refLevel)[1]; creal dvzBlock = cell->get_velocity_grid_block_size(popID,refLevel)[2]; const size_t vxblocks_ini = cell->get_velocity_grid_length(popID,refLevel)[0]; const size_t vyblocks_ini = cell->get_velocity_grid_length(popID,refLevel)[1]; const size_t vzblocks_ini = cell->get_velocity_grid_length(popID,refLevel)[2]; const vector<std::array<Real, 3>> V0 = this->getV0(x+0.5*dx, y+0.5*dy, z+0.5*dz, popID); for (vector<std::array<Real, 3>>::const_iterator it = V0.begin(); it != V0.end(); it++) { // VX search search = true; counter = 0; #warning TODO: add SpatialCell::getVelocityBlockMinValue() in place of sparseMinValue while (search) { if (0.1 * getObjectWrapper().particleSpecies[popID].sparseMinValue > calcPhaseSpaceDensity(x, y, z, dx, dy, dz, it->at(0) + counter*dvxBlock, it->at(1), it->at(2), dvxCell, dvyCell, dvzCell, popID ) ) { search = false; } ++counter; if (counter >= cell->get_velocity_grid_length(popID,refLevel)[0]) search = false; } counter+=2; Real vRadiusSquared = (Real)counter*(Real)counter*dvxBlock*dvxBlock; // VY search search = true; counter = 0; while(search) { if (0.1 * getObjectWrapper().particleSpecies[popID].sparseMinValue > calcPhaseSpaceDensity( x, y, z, dx, dy, dz, it->at(0), it->at(1) + counter*dvyBlock, it->at(2), dvxCell, dvyCell, dvzCell, popID ) || counter > vxblocks_ini ) { search = false; } ++counter; if (counter >= cell->get_velocity_grid_length(popID,refLevel)[1]) search = false; } counter+=2; vRadiusSquared = max(vRadiusSquared, (Real)counter*(Real)counter*dvyBlock*dvyBlock); // VZ search search = true; counter = 0; while(search) { if (0.1 * getObjectWrapper().particleSpecies[popID].sparseMinValue > calcPhaseSpaceDensity( x, y, z, dx, dy, dz, it->at(0), it->at(1), it->at(2) + counter*dvzBlock, dvxCell, dvyCell, dvzCell, popID ) || counter > vxblocks_ini ) { search = false; } ++counter; if (counter >= cell->get_velocity_grid_length(popID,refLevel)[2]) search = false; } counter+=2; vRadiusSquared = max(vRadiusSquared, (Real)counter*(Real)counter*dvzBlock*dvzBlock); // Block listing for (uint kv=0; kv<vzblocks_ini; ++kv) for (uint jv=0; jv<vyblocks_ini; ++jv) for (uint iv=0; iv<vxblocks_ini; ++iv) { vmesh::GlobalID blockIndices[3]; blockIndices[0] = iv; blockIndices[1] = jv; blockIndices[2] = kv; const vmesh::GlobalID blockGID = cell->get_velocity_block(popID,blockIndices,refLevel); Real V_crds[3]; cell->get_velocity_block_coordinates(popID,blockGID,V_crds); Real dV[3]; cell->get_velocity_block_size(popID,blockGID,dV); V_crds[0] += 0.5*dV[0]; V_crds[1] += 0.5*dV[1]; V_crds[2] += 0.5*dV[2]; Real R2 = ((V_crds[0]-it->at(0))*(V_crds[0]-it->at(0)) + (V_crds[1]-it->at(1))*(V_crds[1]-it->at(1)) + (V_crds[2]-it->at(2))*(V_crds[2]-it->at(2))); if (R2 < vRadiusSquared) { cell->add_velocity_block(blockGID,popID); blocksToInitialize.insert(blockGID); } } } vector<vmesh::GlobalID> returnVector; for (set<vmesh::GlobalID>::const_iterator it=blocksToInitialize.begin(); it!=blocksToInitialize.end(); ++it) { returnVector.push_back(*it); } return returnVector; }
Real MultiPeak::calcPhaseSpaceDensity(creal& x, creal& y, creal& z, creal& dx, creal& dy, creal& dz, creal& vx, creal& vy, creal& vz, creal& dvx, creal& dvy, creal& dvz, const uint popID) const { // Iterative sampling of the distribution function. Keep track of the // accumulated volume average over the iterations. When the next // iteration improves the average by less than 1%, return the value. Real avgTotal = 0.0; bool ok = false; uint N = nVelocitySamples; // Start by using nVelocitySamples int N3_sum = 0; // Sum of sampling points used so far const MultiPeakSpeciesParameters& sP = speciesParams[popID]; #warning TODO: Replace getObjectWrapper().particleSpecies[popID].sparseMinValue with SpatialCell::getVelocityBlockMinValue(popID) const Real avgLimit = 0.01*getObjectWrapper().particleSpecies[popID].sparseMinValue; do { Real avg = 0.0; // Volume average obtained during this sampling creal DVX = dvx / N; creal DVY = dvy / N; creal DVZ = dvz / N; Real rhoFactor = 1.0; switch (densityModel) { case Uniform: rhoFactor = 1.0; break; case TestCase: rhoFactor = 1.0; if ((x >= 3.9e5 && x <= 6.1e5) && (y >= 3.9e5 && y <= 6.1e5)) { rhoFactor = 1.5; } break; default: rhoFactor = 1.0; break; } // Sample the distribution using N*N*N points for (uint vi=0; vi<N; ++vi) { for (uint vj=0; vj<N; ++vj) { for (uint vk=0; vk<N; ++vk) { creal VX = vx + 0.5*DVX + vi*DVX; creal VY = vy + 0.5*DVY + vj*DVY; creal VZ = vz + 0.5*DVZ + vk*DVZ; avg += getDistribValue(VX,VY,VZ,DVX,DVY,DVZ,popID); } } } avg *= rhoFactor; // Compare the current and accumulated volume averages: Real eps = max(numeric_limits<creal>::min(),avg * static_cast<Real>(1e-6)); Real avgAccum = avgTotal / (avg + N3_sum); Real avgCurrent = avg / (N*N*N); if (fabs(avgCurrent-avgAccum)/(avgAccum+eps) < 0.01) ok = true; else if (avg < avgLimit) ok = true; else if (N > 10) { ok = true; } avgTotal += avg; N3_sum += N*N*N; ++N; } while (ok == false); return avgTotal / N3_sum; }