1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
29 inline void Foam::moleculeCloud::evaluatePair
35 const pairPotentialList& pairPot = pot_.pairPotentials();
37 const pairPotential& electrostatic = pairPot.electrostatic();
39 label idI = molI->id();
41 label idJ = molJ->id();
43 const molecule::constantProperties& constPropI(constProps(idI));
45 const molecule::constantProperties& constPropJ(constProps(idJ));
47 List<label> siteIdsI = constPropI.siteIds();
49 List<label> siteIdsJ = constPropJ.siteIds();
51 List<bool> pairPotentialSitesI = constPropI.pairPotentialSites();
53 List<bool> electrostaticSitesI = constPropI.electrostaticSites();
55 List<bool> pairPotentialSitesJ = constPropJ.pairPotentialSites();
57 List<bool> electrostaticSitesJ = constPropJ.electrostaticSites();
61 label idsI(siteIdsI[sI]);
65 label idsJ(siteIdsJ[sJ]);
67 if (pairPotentialSitesI[sI] && pairPotentialSitesJ[sJ])
70 molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
72 scalar rsIsJMagSq = magSqr(rsIsJ);
74 if(pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
76 scalar rsIsJMag = mag(rsIsJ);
80 *pairPot.force(idsI, idsJ, rsIsJMag);
82 molI->siteForces()[sI] += fsIsJ;
84 molJ->siteForces()[sJ] += -fsIsJ;
86 scalar potentialEnergy
88 pairPot.energy(idsI, idsJ, rsIsJMag)
91 molI->potentialEnergy() += 0.5*potentialEnergy;
93 molJ->potentialEnergy() += 0.5*potentialEnergy;
95 vector rIJ = molI->position() - molJ->position();
97 tensor virialContribution =
98 (rsIsJ*fsIsJ)*(rsIsJ & rIJ)/rsIsJMagSq;
100 molI->rf() += virialContribution;
102 molJ->rf() += virialContribution;
104 // molI->rf() += rsIsJ * fsIsJ;
106 // molJ->rf() += rsIsJ * fsIsJ;
110 if (electrostaticSitesI[sI] && electrostaticSitesJ[sJ])
113 molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
115 scalar rsIsJMagSq = magSqr(rsIsJ);
117 if(rsIsJMagSq <= electrostatic.rCutSqr())
119 scalar rsIsJMag = mag(rsIsJ);
121 scalar chargeI = constPropI.siteCharges()[sI];
123 scalar chargeJ = constPropJ.siteCharges()[sJ];
127 *chargeI*chargeJ*electrostatic.force(rsIsJMag);
129 molI->siteForces()[sI] += fsIsJ;
131 molJ->siteForces()[sJ] += -fsIsJ;
133 scalar potentialEnergy =
135 *electrostatic.energy(rsIsJMag);
137 molI->potentialEnergy() += 0.5*potentialEnergy;
139 molJ->potentialEnergy() += 0.5*potentialEnergy;
141 vector rIJ = molI->position() - molJ->position();
143 tensor virialContribution =
144 (rsIsJ*fsIsJ)*(rsIsJ & rIJ)/rsIsJMagSq;
146 molI->rf() += virialContribution;
148 molJ->rf() += virialContribution;
150 // molI->rf() += rsIsJ * fsIsJ;
152 // molJ->rf() += rsIsJ * fsIsJ;
160 inline void Foam::moleculeCloud::evaluatePair
163 referredMolecule* molRef
166 const pairPotentialList& pairPot = pot_.pairPotentials();
168 const pairPotential& electrostatic = pairPot.electrostatic();
170 label idReal = molReal->id();
172 label idRef = molRef->id();
174 const molecule::constantProperties& constPropReal(constProps(idReal));
176 const molecule::constantProperties& constPropRef(constProps(idRef));
178 List<label> siteIdsReal = constPropReal.siteIds();
180 List<label> siteIdsRef = constPropRef.siteIds();
182 List<bool> pairPotentialSitesReal = constPropReal.pairPotentialSites();
184 List<bool> electrostaticSitesReal = constPropReal.electrostaticSites();
186 List<bool> pairPotentialSitesRef = constPropRef.pairPotentialSites();
188 List<bool> electrostaticSitesRef = constPropRef.electrostaticSites();
190 forAll(siteIdsReal, sReal)
192 label idsReal(siteIdsReal[sReal]);
194 forAll(siteIdsRef, sRef)
196 label idsRef(siteIdsRef[sRef]);
198 if (pairPotentialSitesReal[sReal] && pairPotentialSitesRef[sRef])
201 molReal->sitePositions()[sReal]
202 - molRef->sitePositions()[sRef];
204 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
206 if (pairPot.rCutSqr(idsReal, idsRef, rsRealsRefMagSq))
208 scalar rsRealsRefMag = mag(rsRealsRef);
211 (rsRealsRef/rsRealsRefMag)
212 *pairPot.force(idsReal, idsRef, rsRealsRefMag);
214 molReal->siteForces()[sReal] += fsRealsRef;
216 scalar potentialEnergy
218 pairPot.energy(idsReal, idsRef, rsRealsRefMag)
221 molReal->potentialEnergy() += 0.5*potentialEnergy;
223 vector rRealRef = molReal->position() - molRef->position();
226 (rsRealsRef*fsRealsRef)
227 *(rsRealsRef & rRealRef)
230 // molReal->rf() += rsRealsRef * fsRealsRef;
235 if (electrostaticSitesReal[sReal] && electrostaticSitesRef[sRef])
238 molReal->sitePositions()[sReal]
239 - molRef->sitePositions()[sRef];
241 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
243 if (rsRealsRefMagSq <= electrostatic.rCutSqr())
245 scalar rsRealsRefMag = mag(rsRealsRef);
247 scalar chargeReal = constPropReal.siteCharges()[sReal];
249 scalar chargeRef = constPropRef.siteCharges()[sRef];
252 (rsRealsRef/rsRealsRefMag)
253 *chargeReal*chargeRef
254 *electrostatic.force(rsRealsRefMag);
256 molReal->siteForces()[sReal] += fsRealsRef;
258 scalar potentialEnergy =
260 *electrostatic.energy(rsRealsRefMag);
262 molReal->potentialEnergy() += 0.5*potentialEnergy;
264 vector rRealRef = molReal->position() - molRef->position();
267 (rsRealsRef*fsRealsRef)
268 *(rsRealsRef & rRealRef)
271 // molReal->rf() += rsRealsRef * fsRealsRef;
279 inline bool Foam::moleculeCloud::evaluatePotentialLimit
285 const pairPotentialList& pairPot = pot_.pairPotentials();
287 const pairPotential& electrostatic = pairPot.electrostatic();
289 label idI = molI->id();
291 label idJ = molJ->id();
293 const molecule::constantProperties& constPropI(constProps(idI));
295 const molecule::constantProperties& constPropJ(constProps(idJ));
297 List<label> siteIdsI = constPropI.siteIds();
299 List<label> siteIdsJ = constPropJ.siteIds();
301 List<bool> pairPotentialSitesI = constPropI.pairPotentialSites();
303 List<bool> electrostaticSitesI = constPropI.electrostaticSites();
305 List<bool> pairPotentialSitesJ = constPropJ.pairPotentialSites();
307 List<bool> electrostaticSitesJ = constPropJ.electrostaticSites();
311 label idsI(siteIdsI[sI]);
315 label idsJ(siteIdsJ[sJ]);
317 if (pairPotentialSitesI[sI] && pairPotentialSitesJ[sJ])
320 molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
322 scalar rsIsJMagSq = magSqr(rsIsJ);
324 if (pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
326 scalar rsIsJMag = mag(rsIsJ);
328 // Guard against pairPot.energy being evaluated
329 // if rIJMag < SMALL. A floating point exception will
332 if (rsIsJMag < SMALL)
334 WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
335 << "Molecule site pair closer than "
337 << ": mag separation = " << rsIsJMag
338 << ". These may have been placed on top of each"
339 << " other by a rounding error in mdInitialise in"
340 << " parallel or a block filled with molecules"
341 << " twice. Removing one of the molecules."
347 // Guard against pairPot.energy being evaluated if rIJMag <
348 // rMin. A tabulation lookup error will occur otherwise.
350 if (rsIsJMag < pairPot.rMin(idsI, idsJ))
357 mag(pairPot.energy(idsI, idsJ, rsIsJMag))
358 > pot_.potentialEnergyLimit()
366 if (electrostaticSitesI[sI] && electrostaticSitesJ[sJ])
369 molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
371 scalar rsIsJMagSq = magSqr(rsIsJ);
373 if (pairPot.rCutMaxSqr(rsIsJMagSq))
375 scalar rsIsJMag = mag(rsIsJ);
377 // Guard against pairPot.energy being evaluated
378 // if rIJMag < SMALL. A floating point exception will
381 if (rsIsJMag < SMALL)
383 WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
384 << "Molecule site pair closer than "
386 << ": mag separation = " << rsIsJMag
387 << ". These may have been placed on top of each"
388 << " other by a rounding error in mdInitialise in"
389 << " parallel or a block filled with molecules"
390 << " twice. Removing one of the molecules."
396 if (rsIsJMag < electrostatic.rMin())
401 scalar chargeI = constPropI.siteCharges()[sI];
403 scalar chargeJ = constPropJ.siteCharges()[sJ];
407 mag(chargeI*chargeJ*electrostatic.energy(rsIsJMag))
408 > pot_.potentialEnergyLimit()
422 inline bool Foam::moleculeCloud::evaluatePotentialLimit
425 referredMolecule* molRef
428 const pairPotentialList& pairPot = pot_.pairPotentials();
430 const pairPotential& electrostatic = pairPot.electrostatic();
432 label idReal = molReal->id();
434 label idRef = molRef->id();
436 const molecule::constantProperties& constPropReal(constProps(idReal));
438 const molecule::constantProperties& constPropRef(constProps(idRef));
440 List<label> siteIdsReal = constPropReal.siteIds();
442 List<label> siteIdsRef = constPropRef.siteIds();
444 List<bool> pairPotentialSitesReal = constPropReal.pairPotentialSites();
446 List<bool> electrostaticSitesReal = constPropReal.electrostaticSites();
448 List<bool> pairPotentialSitesRef = constPropRef.pairPotentialSites();
450 List<bool> electrostaticSitesRef = constPropRef.electrostaticSites();
452 forAll(siteIdsReal, sReal)
454 label idsReal(siteIdsReal[sReal]);
456 forAll(siteIdsRef, sRef)
458 label idsRef(siteIdsRef[sRef]);
460 if (pairPotentialSitesReal[sReal] && pairPotentialSitesRef[sRef])
463 molReal->sitePositions()[sReal]
464 - molRef->sitePositions()[sRef];
466 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
468 if (pairPot.rCutSqr(idsReal, idsRef, rsRealsRefMagSq))
470 scalar rsRealsRefMag = mag(rsRealsRef);
472 // Guard against pairPot.energy being evaluated
473 // if rRealRefMag < SMALL. A floating point exception will
476 if (rsRealsRefMag < SMALL)
478 WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
479 << "Molecule site pair closer than "
481 << ": mag separation = " << rsRealsRefMag
482 << ". These may have been placed on top of each"
483 << " other by a rounding error in mdInitialise in"
484 << " parallel or a block filled with molecules"
485 << " twice. Removing one of the molecules."
491 // Guard against pairPot.energy being evaluated if
492 // rRealRefMag < rMin. A tabulation lookup error will occur
495 if (rsRealsRefMag < pairPot.rMin(idsReal, idsRef))
502 mag(pairPot.energy(idsReal, idsRef, rsRealsRefMag))
503 > pot_.potentialEnergyLimit()
511 if (electrostaticSitesReal[sReal] && electrostaticSitesRef[sRef])
514 molReal->sitePositions()[sReal]
515 - molRef->sitePositions()[sRef];
517 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
519 if (pairPot.rCutMaxSqr(rsRealsRefMagSq))
521 scalar rsRealsRefMag = mag(rsRealsRef);
523 // Guard against pairPot.energy being evaluated
524 // if rRealRefMag < SMALL. A floating point exception will
527 if (rsRealsRefMag < SMALL)
529 WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
530 << "Molecule site pair closer than "
532 << ": mag separation = " << rsRealsRefMag
533 << ". These may have been placed on top of each"
534 << " other by a rounding error in mdInitialise in"
535 << " parallel or a block filled with molecules"
536 << " twice. Removing one of the molecules."
542 if (rsRealsRefMag < electrostatic.rMin())
547 scalar chargeReal = constPropReal.siteCharges()[sReal];
549 scalar chargeRef = constPropRef.siteCharges()[sRef];
557 *electrostatic.energy(rsRealsRefMag)
559 > pot_.potentialEnergyLimit()
573 inline Foam::vector Foam::moleculeCloud::equipartitionLinearVelocity
579 return sqrt(kb*temperature/mass)*vector
581 rndGen_.GaussNormal(),
582 rndGen_.GaussNormal(),
583 rndGen_.GaussNormal()
588 inline Foam::vector Foam::moleculeCloud::equipartitionAngularMomentum
591 const molecule::constantProperties& cP
594 scalar sqrtKbT = sqrt(kb*temperature);
596 if (cP.linearMolecule())
598 return sqrtKbT*vector
601 sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
602 sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
607 return sqrtKbT*vector
609 sqrt(cP.momentOfInertia().xx())*rndGen_.GaussNormal(),
610 sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
611 sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
617 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
619 inline const Foam::polyMesh& Foam::moleculeCloud::mesh() const
625 inline const Foam::potential& Foam::moleculeCloud::pot() const
631 inline const Foam::List<Foam::DynamicList<Foam::molecule*> >&
632 Foam::moleculeCloud::cellOccupancy() const
634 return cellOccupancy_;
638 inline const Foam::interactionLists&
639 Foam::moleculeCloud::il() const
645 inline const Foam::List<Foam::molecule::constantProperties>
646 Foam::moleculeCloud::constProps() const
648 return constPropList_;
652 inline const Foam::molecule::constantProperties&
653 Foam::moleculeCloud::constProps(label id) const
655 return constPropList_[id];
659 inline Foam::Random& Foam::moleculeCloud::rndGen()
665 // ************************************************************************* //