Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Actions/FillAction/SuspendInMoleculeAction.cpp

    raa55d0 r2440ce  
    129129  filler->CenterEdge();
    130130
     131  std::vector<molecule *> molecules = World::getInstance().getAllMolecules();
     132  if (molecules.size() < 2) {
     133    STATUS("There must be at least two molecules: filler and to be suspended.");
     134    return Action::failure;
     135  }
     136
    131137  /// first we need to calculate some volumes and masses
    132   std::vector<molecule *> molecules = World::getInstance().getAllMolecules();
    133138  double totalmass = 0.;
    134139  const bool IsAngstroem = true;
     
    139144      iter != molecules.end(); ++iter)
    140145  {
     146    // skip the filler
     147    if (*iter == filler)
     148      continue;
    141149    molecule & mol = **iter;
    142150    const double mass = calculateMass(mol);
     
    152160  LOG(1, "INFO: The average density is " << setprecision(10)
    153161      << totalmass / clustervolume << " atomicmassunit/"
    154       << (IsAngstroem ? "angstrom" : "atomiclength") << "^3.");
     162      << (IsAngstroem ? " angstrom" : " atomiclength") << "^3.");
     163  if ( ((totalmass / clustervolume < 1.) && (params.density.get() > 1.))
     164      || ((totalmass / clustervolume > 1.) && (params.density.get() < 1.))) {
     165    STATUS("Desired and present molecular densities must both be either in [0,1) or in (1, inf).");
     166    return Action::failure;
     167  }
    155168
    156169  // calculate maximum solvent density
    157170  std::vector<double> fillerdiameters(NDIM, 0.);
    158   const double solventdensity =
    159       calculateMass(*filler) / calculateEnvelopeVolume(*filler, fillerdiameters);
    160 
    161   std::vector<unsigned int> counts(3, 0);
    162   Vector offset(.5,.5,.5);
     171  const double fillervolume = calculateEnvelopeVolume(*filler, fillerdiameters);
     172  const double fillermass = calculateMass(*filler);
     173  LOG(1, "INFO: The filler's mass is " << setprecision(10)
     174      << fillermass << " atomicmassunit, and it's volume is "
     175      << fillervolume << (IsAngstroem ? " angstrom" : " atomiclength") << "^3.");
     176  const double solventdensity = fillermass / fillervolume;
    163177
    164178  /// solve cubic polynomial
    165179  double cellvolume = 0.;
    166180  LOG(1, "Solving equidistant suspension in water problem ...");
    167   cellvolume = (totalmass / solventdensity
    168       - (totalmass / clustervolume)) / (params.density.get() - 1.);
     181  // s = solvent, f = filler, 0 = initial molecules/cluster
     182  // v_s = v_0 + v_f, m_s = m_0 + rho_f * v_f --> rho_s = m_s/v_s ==> v_f = (m_0 - rho_s * v_o) / (rho_s - rho_f)
     183  cellvolume = (totalmass - params.density.get() * clustervolume) / (params.density.get() - 1.) + clustervolume;
    169184  LOG(1, "Cellvolume needed for a density of " << params.density.get()
    170185      << " g/cm^3 is " << cellvolume << " angstroem^3.");
     
    173188      (GreatestDiameter[0] * GreatestDiameter[1] * GreatestDiameter[2]);
    174189  LOG(1, "Minimum volume of the convex envelope contained in a rectangular box is "
    175       << minimumvolume << "angstrom^3.");
     190      << minimumvolume << " angstrom^3.");
    176191
    177192  if (minimumvolume > cellvolume) {
     
    187202        + GreatestDiameter[1] * GreatestDiameter[2];
    188203    BoxLengths[2] = minimumvolume - cellvolume;
    189     double x0 = 0.;
    190     double x1 = 0.;
    191     double x2 = 0.;
     204    std::vector<double> x(3, 0.);
    192205    // for cubic polynomial there are either 1 or 3 unique solutions
    193     if (gsl_poly_solve_cubic(BoxLengths[0], BoxLengths[1], BoxLengths[2], &x0, &x1, &x2) == 1)
    194       LOG(0, "RESULT: The resulting spacing is: " << x0 << " .");
    195     else {
    196       LOG(0, "RESULT: The resulting spacings are: " << x0 << " and " << x1 << " and " << x2 << " .");
    197       std::swap(x0, x2); // sorted in ascending order
    198     }
     206    if (gsl_poly_solve_cubic(BoxLengths[0], BoxLengths[1], BoxLengths[2], &x[0], &x[1], &x[2]) == 1) {
     207      x[1] = x[0];
     208      x[2] = x[0];
     209    } else {
     210      std::swap(x[0], x[2]); // sorted in ascending order
     211    }
     212    LOG(0, "RESULT: The resulting spacing is: " << x << " .");
    199213
    200214    cellvolume = 1.;
    201215    for (size_t i = 0; i < NDIM; ++i) {
    202       BoxLengths[i] = x0 + GreatestDiameter[i];
     216      BoxLengths[i] = x[i] + GreatestDiameter[i];
    203217      cellvolume *= BoxLengths[i];
    204218    }
    205 
    206     // set new box dimensions
    207     LOG(0, "Translating to box with these boundaries.");
    208     {
    209       RealSpaceMatrix domain;
    210       for(size_t i =0; i<NDIM;++i)
    211         domain.at(i,i) = BoxLengths[i];
    212       World::getInstance().setDomain(domain);
    213     }
    214 //    mol->CenterInBox();
     219  }
     220
     221  // TODO: Determine counts from resulting mass correctly (hard problem due to integers)
     222  std::vector<unsigned int> counts(3, 0);
     223  const unsigned int totalcounts = round(params.density.get() * cellvolume - totalmass) / fillermass;
     224  if (totalcounts > 0) {
     225    counts[0] = ceil(BoxLengths[0]/3.1);
     226    counts[1] = ceil(BoxLengths[1]/3.1);
     227    counts[2] = ceil(BoxLengths[2]/3.1);
    215228  }
    216229
     
    231244      params.RandMoleculeDisplacement.get(),
    232245      params.DoRotate.get());
     246  Vector offset(.5,.5,.5);
    233247  filler_preparator.addCubeMesh(
    234248      counts,
Note: See TracChangeset for help on using the changeset viewer.