41 void Foam::moleculeCloud::buildConstProps()
43 Info<< nl <<
"Reading moleculeProperties dictionary." <<
endl;
45 const List<word>& idList(pot_.idList());
47 constPropList_.setSize(idList.size());
49 const List<word>& siteIdList(pot_.siteIdList());
51 IOdictionary moleculePropertiesDict
56 mesh_.time().constant(),
66 const word&
id = idList[i];
67 const dictionary& molDict = moleculePropertiesDict.subDict(
id);
69 List<word> siteIdNames = molDict.lookup(
"siteIds");
71 List<label> siteIds(siteIdNames.size());
75 const word& siteId = siteIdNames[sI];
77 siteIds[sI] =
findIndex(siteIdList, siteId);
79 if (siteIds[sI] == -1)
82 << siteId <<
" site not found." 87 molecule::constantProperties&
constProp = constPropList_[i];
89 constProp = molecule::constantProperties(molDict);
91 constProp.siteIds() = siteIds;
96 void Foam::moleculeCloud::setSiteSizesAndPositions()
100 const molecule::constantProperties& cP = constProps(mol().
id());
102 mol().setSiteSizes(cP.nSites());
104 mol().setSitePositions(cP);
109 void Foam::moleculeCloud::buildCellOccupancy()
111 forAll(cellOccupancy_, cO)
113 cellOccupancy_[cO].clear();
118 cellOccupancy_[mol().cell()].append(&mol());
121 forAll(cellOccupancy_, cO)
123 cellOccupancy_[cO].shrink();
128 void Foam::moleculeCloud::calculatePairForce()
136 molecule* molI = NULL;
137 molecule* molJ = NULL;
146 forAll(cellOccupancy_[d],cellIMols)
148 molI = cellOccupancy_[d][cellIMols];
150 forAll(dil[d], interactingCells)
152 List<molecule*> cellJ =
153 cellOccupancy_[dil[d][interactingCells]];
157 molJ = cellJ[cellJMols];
159 evaluatePair(*molI, *molJ);
163 forAll(cellOccupancy_[d], cellIOtherMols)
165 molJ = cellOccupancy_[d][cellIOtherMols];
169 evaluatePair(*molI, *molJ);
177 il_.receiveReferredData(pBufs, startOfRequests);
184 List<IDLList<molecule>>& referredMols = il_.referredParticles();
188 const List<label>& realCells = ril[r];
190 IDLList<molecule>& refMols = referredMols[r];
201 List<molecule*> celli = cellOccupancy_[realCells[rC]];
205 molI = celli[cellIMols];
207 evaluatePair(*molI, refMol());
216 void Foam::moleculeCloud::calculateTetherForce()
218 const tetherPotentialList& tetherPot(pot_.tetherPotentials());
222 if (mol().tethered())
224 vector rIT = mol().position() - mol().specialPosition();
226 label idI = mol().id();
228 scalar massI = constProps(idI).mass();
230 vector fIT = tetherPot.force(idI, rIT);
232 mol().a() += fIT/massI;
234 mol().potentialEnergy() += tetherPot.energy(idI, rIT);
243 void Foam::moleculeCloud::calculateExternalForce()
247 mol().a() += pot_.gravity();
252 void Foam::moleculeCloud::removeHighEnergyOverlaps()
254 Info<< nl <<
"Removing high energy overlaps, limit = " 255 << pot_.potentialEnergyLimit()
256 << nl <<
"Removal order:";
258 forAll(pot_.removalOrder(), rO)
260 Info<<
' ' << pot_.idList()[pot_.removalOrder()[rO]];
265 label initialSize = this->size();
267 buildCellOccupancy();
271 molecule* molI = NULL;
272 molecule* molJ = NULL;
275 DynamicList<molecule*> molsToDelete;
281 forAll(cellOccupancy_[d],cellIMols)
283 molI = cellOccupancy_[d][cellIMols];
285 forAll(dil[d], interactingCells)
287 List<molecule*> cellJ =
288 cellOccupancy_[dil[d][interactingCells]];
292 molJ = cellJ[cellJMols];
294 if (evaluatePotentialLimit(*molI, *molJ))
296 label idI = molI->id();
298 label idJ = molJ->id();
309 molsToDelete.append(molJ);
312 else if (
findIndex(molsToDelete, molI) == -1)
314 molsToDelete.append(molI);
321 forAll(cellOccupancy_[d], cellIOtherMols)
323 molJ = cellOccupancy_[d][cellIOtherMols];
327 if (evaluatePotentialLimit(*molI, *molJ))
329 label idI = molI->id();
331 label idJ = molJ->id();
342 molsToDelete.append(molJ);
345 else if (
findIndex(molsToDelete, molI) == -1)
347 molsToDelete.append(molI);
356 deleteParticle(*(molsToDelete[mTD]));
360 buildCellOccupancy();
370 il_.receiveReferredData(pBufs, startOfRequests);
375 DynamicList<molecule*> molsToDelete;
379 List<IDLList<molecule>>& referredMols = il_.referredParticles();
383 IDLList<molecule>& refMols = referredMols[r];
394 const List<label>& realCells = ril[r];
398 label celli = realCells[rC];
400 List<molecule*> cellIMols = cellOccupancy_[celli];
404 molI = cellIMols[cIM];
406 if (evaluatePotentialLimit(*molI, *molJ))
408 label idI = molI->id();
410 label idJ = molJ->id();
420 molsToDelete.append(molI);
434 if (molI->origId() > molJ->origId())
438 molsToDelete.append(molI);
450 deleteParticle(*(molsToDelete[mTD]));
454 buildCellOccupancy();
462 il_.receiveReferredData(pBufs, startOfRequests);
464 label molsRemoved = initialSize - this->size();
468 reduce(molsRemoved, sumOp<label>());
471 Info<<
tab << molsRemoved <<
" molecules removed" <<
endl;
475 void Foam::moleculeCloud::initialiseMolecules
477 const IOdictionary& mdInitialiseDict
481 <<
"Initialising molecules in each zone specified in mdInitialiseDict." 486 if (!cellZones.size())
489 <<
"No cellZones found in the mesh." 495 const cellZone& zone(cellZones[z]);
499 if (!mdInitialiseDict.found(zone.name()))
501 Info<<
"No specification subDictionary for zone " 502 << zone.name() <<
" found, skipping." <<
endl;
506 const dictionary& zoneDict =
507 mdInitialiseDict.subDict(zone.name());
509 const scalar temperature
514 const vector bulkVelocity(zoneDict.lookup(
"bulkVelocity"));
516 List<word> latticeIds
518 zoneDict.lookup(
"latticeIds")
521 List<vector> latticePositions
523 zoneDict.lookup(
"latticePositions")
526 if (latticeIds.size() != latticePositions.size())
529 <<
"latticeIds and latticePositions must be the same " 536 zoneDict.lookup(
"latticeCellShape")
539 scalar latticeCellScale = 0.0;
541 if (zoneDict.found(
"numberDensity"))
545 zoneDict.lookup(
"numberDensity")
548 if (numberDensity < VSMALL)
551 <<
"numberDensity too small, not filling zone " 552 << zone.name() <<
endl;
557 latticeCellScale =
pow 559 latticeIds.size()/(
det(latticeCellShape)*numberDensity),
563 else if (zoneDict.found(
"massDensity"))
565 scalar unitCellMass = 0.0;
571 const molecule::constantProperties& cP(constProps(
id));
573 unitCellMass += cP.mass();
578 zoneDict.lookup(
"massDensity")
581 if (massDensity < VSMALL)
584 <<
"massDensity too small, not filling zone " 585 << zone.name() <<
endl;
591 latticeCellScale =
pow 593 unitCellMass/(
det(latticeCellShape)*massDensity),
600 <<
"massDensity or numberDensity not specified " << nl
604 latticeCellShape *= latticeCellScale;
606 vector anchor(zoneDict.lookup(
"anchor"));
608 bool tethered =
false;
610 if (zoneDict.found(
"tetherSiteIds"))
614 List<word>(zoneDict.lookup(
"tetherSiteIds")).size()
618 const vector orientationAngles
620 zoneDict.lookup(
"orientationAngles")
623 scalar
phi(orientationAngles.x()*pi/180.0);
625 scalar theta(orientationAngles.y()*pi/180.0);
627 scalar
psi(orientationAngles.z()*pi/180.0);
652 const point cellCentre = mesh_.cellCentres()[zone[cell]];
654 if (cellCentre.x() > zoneMax.x())
656 zoneMax.
x() = cellCentre.x();
658 if (cellCentre.x() < zoneMin.x())
660 zoneMin.x() = cellCentre.x();
662 if (cellCentre.y() > zoneMax.y())
664 zoneMax.y() = cellCentre.y();
666 if (cellCentre.y() < zoneMin.y())
668 zoneMin.y() = cellCentre.y();
670 if (cellCentre.z() > zoneMax.z())
672 zoneMax.z() = cellCentre.z();
674 if (cellCentre.z() < zoneMin.z())
676 zoneMin.z() = cellCentre.z();
680 point zoneMid = 0.5*(zoneMin + zoneMax);
682 point latticeMid =
inv(latticeCellShape) & (
R.T()
683 & (zoneMid - anchor));
687 label(latticeMid.x() + 0.5*
sign(latticeMid.x())),
688 label(latticeMid.y() + 0.5*
sign(latticeMid.y())),
689 label(latticeMid.z() + 0.5*
sign(latticeMid.z()))
692 anchor += (
R & (latticeCellShape & latticeAnchor));
702 label totalZoneMols = 0;
704 label molsPlacedThisIteration = 0;
708 molsPlacedThisIteration != 0
709 || totalZoneMols == 0
712 label sizeBeforeIteration = this->size();
714 bool partOfLayerInBounds =
false;
731 const vector& latticePosition =
734 unitCellLatticePosition.x(),
735 unitCellLatticePosition.y(),
736 unitCellLatticePosition.z()
738 + latticePositions[
p];
740 point globalPosition =
742 + (
R & (latticeCellShape & latticePosition));
744 partOfLayerInBounds = mesh_.bounds().contains
785 unitCellLatticePosition.z() = -
n;
786 unitCellLatticePosition.z() <=
n;
787 unitCellLatticePosition.z() += 2*
n 792 unitCellLatticePosition.y() = -
n;
793 unitCellLatticePosition.y() <=
n;
794 unitCellLatticePosition.y()++
799 unitCellLatticePosition.x() = -
n;
800 unitCellLatticePosition.x() <=
n;
801 unitCellLatticePosition.x()++
812 const vector& latticePosition =
815 unitCellLatticePosition.x(),
816 unitCellLatticePosition.y(),
817 unitCellLatticePosition.z()
819 + latticePositions[
p];
821 point globalPosition =
831 partOfLayerInBounds =
832 mesh_.bounds().contains
870 unitCellLatticePosition.z() = -(n-1);
871 unitCellLatticePosition.z() <= (n-1);
872 unitCellLatticePosition.z()++
875 for (
label iR = 0; iR <= 2*n -1; iR++)
877 unitCellLatticePosition.x() =
n;
879 unitCellLatticePosition.y() = -n + (iR + 1);
881 for (
label iK = 0; iK < 4; iK++)
891 const vector& latticePosition =
894 unitCellLatticePosition.x(),
895 unitCellLatticePosition.y(),
896 unitCellLatticePosition.z()
898 + latticePositions[
p];
900 point globalPosition =
910 partOfLayerInBounds =
911 mesh_.bounds().contains
944 unitCellLatticePosition =
947 - unitCellLatticePosition.y(),
948 unitCellLatticePosition.x(),
949 unitCellLatticePosition.z()
963 && !partOfLayerInBounds
967 <<
"A whole layer of unit cells was placed " 968 <<
"outside the bounds of the mesh, but no " 969 <<
"molecules have been placed in zone '" 971 <<
"'. This is likely to be because the zone " 974 <<
" in this case) and no lattice position " 975 <<
"fell inside them. " 976 <<
"Aborting filling this zone." 982 molsPlacedThisIteration =
983 this->size() - sizeBeforeIteration;
985 totalZoneMols += molsPlacedThisIteration;
995 void Foam::moleculeCloud::createMolecule
997 const point& position,
1004 const vector& bulkVelocity
1009 mesh_.findCellFacePt(position, cell, tetFace, tetPt);
1015 <<
"Position specified does not correspond to a mesh cell." << nl
1025 specialPosition = position;
1030 const molecule::constantProperties& cP(constProps(
id));
1032 vector v = equipartitionLinearVelocity(temperature, cP.mass());
1040 if (!cP.pointMolecule())
1042 pi = equipartitionAngularMomentum(temperature, cP);
1044 scalar
phi(rndGen_.scalar01()*
twoPi);
1046 scalar theta(rndGen_.scalar01()*
twoPi);
1048 scalar
psi(rndGen_.scalar01()*
twoPi);
1093 n += constProps(mol().
id()).nSites();
1102 Foam::moleculeCloud::moleculeCloud
1112 cellOccupancy_(mesh_.nCells()),
1113 il_(mesh_, pot_.pairPotentials().rCutMax(),
false),
1124 setSiteSizesAndPositions();
1126 removeHighEnergyOverlaps();
1132 Foam::moleculeCloud::moleculeCloud
1143 il_(mesh_, 0.0,
false),
1156 initialiseMolecules(mdInitialiseDict);
1182 buildCellOccupancy();
1187 mol().siteForces() =
Zero;
1189 mol().potentialEnergy() = 0.0;
1194 calculatePairForce();
1196 calculateTetherForce();
1198 calculateExternalForce();
1204 const scalar targetTemperature,
1205 const scalar measuredTemperature
1208 scalar temperatureCorrectionFactor =
1209 sqrt(targetTemperature/
max(VSMALL, measuredTemperature));
1211 Info<<
"----------------------------------------" << nl
1212 <<
"Temperature equilibration" << nl
1213 <<
"Target temperature = " 1214 << targetTemperature << nl
1215 <<
"Measured temperature = " 1216 << measuredTemperature << nl
1217 <<
"Temperature correction factor = " 1218 << temperatureCorrectionFactor << nl
1219 <<
"----------------------------------------" 1224 mol().v() *= temperatureCorrectionFactor;
1226 mol().pi() *= temperatureCorrectionFactor;
1235 os << nSites() << nl <<
"moleculeCloud site positions in angstroms" <<
nl;
1241 forAll(mol().sitePositions(), i)
1243 const point& sP = mol().sitePositions()[i];
1245 os << pot_.siteIdList()[cP.
siteIds()[i]]
1246 <<
' ' << sP.
x()*1e10
1247 <<
' ' << sP.
y()*1e10
1248 <<
' ' << sP.
z()*1e10
const Time & time() const
Return time.
dimensionedScalar sign(const dimensionedScalar &ds)
List< labelList > labelListList
A List of labelList.
#define forAll(list, i)
Loop across all elements in list.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
DiagTensor< scalar > diagTensor
A scalar version of the templated DiagTensor.
A class for handling file names.
Class to hold molecule constant properties.
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
void writeXYZ(const fileName &fName) const
Write molecule sites in XYZ format.
void evolve()
Evolve the molecules (move, calculate forces, control state etc)
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
static time_t getTime()
Get the current clock time in seconds.
static label nRequests()
Get number of outstanding requests.
static const Vector< scalar > one
Vector< scalar > vector
A scalar version of the templated Vector.
dimensionedScalar det(const dimensionedSphericalTensor &dt)
const List< label > & siteIds() const
static void readFields(Cloud< molecule > &mC)
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
dimensionedScalar cos(const dimensionedScalar &ds)
static const Identity< scalar > I
word constProp(initialConditions.lookup("constantProperty"))
void applyConstraintsAndThermostats(const scalar targetTemperature, const scalar measuredTemperature)
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
errorManip< error > abort(error &err)
defineTemplateTypeNameAndDebug(IOPtrList< ensightPart >, 0)
const scalar twoPi(2 *pi)
void move(TrackData &td, const scalar trackTime)
Move the particles.
dimensionedScalar sin(const dimensionedScalar &ds)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
static bool & parRun()
Is this a parallel run?
const List< DynamicList< molecule * > > & cellOccupancy
vector point
Point is a vector.
#define R(A, B, C, D, E, F, K, M)
#define WarningInFunction
Report a warning using Foam::Warning.
Class used to pass tracking data to the trackToFace function.
const volScalarField & psi
Vector< label > labelVector
Vector of labels.
Mesh consisting of general polyhedral cells.
Tensor< scalar > tensor
Tensor of scalars.
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.