initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / lagrangian / molecularDynamics / molecule / moleculeCloud / moleculeCloudI.H
blob94c9f49286bda8afbdbd62eef7ca2dd8cb19327e
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2008-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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
31     molecule* molI,
32     molecule* molJ
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();
59     forAll(siteIdsI, sI)
60     {
61         label idsI(siteIdsI[sI]);
63         forAll(siteIdsJ, sJ)
64         {
65             label idsJ(siteIdsJ[sJ]);
67             if (pairPotentialSitesI[sI] && pairPotentialSitesJ[sJ])
68             {
69                 vector rsIsJ =
70                     molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
72                 scalar rsIsJMagSq = magSqr(rsIsJ);
74                 if(pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
75                 {
76                     scalar rsIsJMag = mag(rsIsJ);
78                     vector fsIsJ =
79                         (rsIsJ/rsIsJMag)
80                        *pairPot.force(idsI, idsJ, rsIsJMag);
82                     molI->siteForces()[sI] += fsIsJ;
84                     molJ->siteForces()[sJ] += -fsIsJ;
86                     scalar potentialEnergy
87                     (
88                         pairPot.energy(idsI, idsJ, rsIsJMag)
89                     );
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;
107                 }
108             }
110             if (electrostaticSitesI[sI] && electrostaticSitesJ[sJ])
111             {
112                 vector rsIsJ =
113                 molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
115                 scalar rsIsJMagSq = magSqr(rsIsJ);
117                 if(rsIsJMagSq <= electrostatic.rCutSqr())
118                 {
119                     scalar rsIsJMag = mag(rsIsJ);
121                     scalar chargeI = constPropI.siteCharges()[sI];
123                     scalar chargeJ = constPropJ.siteCharges()[sJ];
125                     vector fsIsJ =
126                         (rsIsJ/rsIsJMag)
127                        *chargeI*chargeJ*electrostatic.force(rsIsJMag);
129                     molI->siteForces()[sI] += fsIsJ;
131                     molJ->siteForces()[sJ] += -fsIsJ;
133                     scalar potentialEnergy =
134                         chargeI*chargeJ
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;
153                 }
154             }
155         }
156     }
160 inline void Foam::moleculeCloud::evaluatePair
162     molecule* molReal,
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)
191     {
192         label idsReal(siteIdsReal[sReal]);
194         forAll(siteIdsRef, sRef)
195         {
196             label idsRef(siteIdsRef[sRef]);
198             if (pairPotentialSitesReal[sReal] && pairPotentialSitesRef[sRef])
199             {
200                 vector rsRealsRef =
201                     molReal->sitePositions()[sReal]
202                   - molRef->sitePositions()[sRef];
204                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
206                 if (pairPot.rCutSqr(idsReal, idsRef, rsRealsRefMagSq))
207                 {
208                     scalar rsRealsRefMag = mag(rsRealsRef);
210                     vector fsRealsRef =
211                         (rsRealsRef/rsRealsRefMag)
212                        *pairPot.force(idsReal, idsRef, rsRealsRefMag);
214                     molReal->siteForces()[sReal] += fsRealsRef;
216                     scalar potentialEnergy
217                     (
218                         pairPot.energy(idsReal, idsRef, rsRealsRefMag)
219                     );
221                     molReal->potentialEnergy() += 0.5*potentialEnergy;
223                     vector rRealRef = molReal->position() - molRef->position();
225                     molReal->rf() +=
226                         (rsRealsRef*fsRealsRef)
227                        *(rsRealsRef & rRealRef)
228                        /rsRealsRefMagSq;
230                     // molReal->rf() += rsRealsRef * fsRealsRef;
232                 }
233             }
235             if (electrostaticSitesReal[sReal] && electrostaticSitesRef[sRef])
236             {
237                 vector rsRealsRef =
238                     molReal->sitePositions()[sReal]
239                   - molRef->sitePositions()[sRef];
241                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
243                 if (rsRealsRefMagSq <= electrostatic.rCutSqr())
244                 {
245                     scalar rsRealsRefMag = mag(rsRealsRef);
247                     scalar chargeReal = constPropReal.siteCharges()[sReal];
249                     scalar chargeRef = constPropRef.siteCharges()[sRef];
251                     vector fsRealsRef =
252                         (rsRealsRef/rsRealsRefMag)
253                        *chargeReal*chargeRef
254                        *electrostatic.force(rsRealsRefMag);
256                     molReal->siteForces()[sReal] += fsRealsRef;
258                     scalar potentialEnergy =
259                         chargeReal*chargeRef
260                        *electrostatic.energy(rsRealsRefMag);
262                     molReal->potentialEnergy() += 0.5*potentialEnergy;
264                     vector rRealRef = molReal->position() - molRef->position();
266                     molReal->rf() +=
267                         (rsRealsRef*fsRealsRef)
268                        *(rsRealsRef & rRealRef)
269                        /rsRealsRefMagSq;
271                     // molReal->rf() += rsRealsRef * fsRealsRef;
272                 }
273             }
274         }
275     }
279 inline bool Foam::moleculeCloud::evaluatePotentialLimit
281     molecule* molI,
282     molecule* molJ
283 ) const
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();
309     forAll(siteIdsI, sI)
310     {
311         label idsI(siteIdsI[sI]);
313         forAll(siteIdsJ, sJ)
314         {
315             label idsJ(siteIdsJ[sJ]);
317             if (pairPotentialSitesI[sI] && pairPotentialSitesJ[sJ])
318             {
319                 vector rsIsJ =
320                     molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
322                 scalar rsIsJMagSq = magSqr(rsIsJ);
324                 if (pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
325                 {
326                     scalar rsIsJMag = mag(rsIsJ);
328                     // Guard against pairPot.energy being evaluated
329                     // if rIJMag < SMALL. A floating point exception will
330                     // happen otherwise.
332                     if (rsIsJMag < SMALL)
333                     {
334                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
335                             << "Molecule site pair closer than "
336                             << SMALL
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."
342                             << endl;
344                         return true;
345                     }
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))
351                     {
352                         return true;
353                     }
355                     if
356                     (
357                         mag(pairPot.energy(idsI, idsJ, rsIsJMag))
358                       > pot_.potentialEnergyLimit()
359                     )
360                     {
361                         return true;
362                     };
363                 }
364             }
366             if (electrostaticSitesI[sI] && electrostaticSitesJ[sJ])
367             {
368                 vector rsIsJ =
369                     molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
371                 scalar rsIsJMagSq = magSqr(rsIsJ);
373                 if (pairPot.rCutMaxSqr(rsIsJMagSq))
374                 {
375                     scalar rsIsJMag = mag(rsIsJ);
377                     // Guard against pairPot.energy being evaluated
378                     // if rIJMag < SMALL. A floating point exception will
379                     // happen otherwise.
381                     if (rsIsJMag < SMALL)
382                     {
383                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
384                             << "Molecule site pair closer than "
385                             << SMALL
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."
391                             << endl;
393                         return true;
394                     }
396                     if (rsIsJMag < electrostatic.rMin())
397                     {
398                         return true;
399                     }
401                     scalar chargeI = constPropI.siteCharges()[sI];
403                     scalar chargeJ = constPropJ.siteCharges()[sJ];
405                     if
406                     (
407                         mag(chargeI*chargeJ*electrostatic.energy(rsIsJMag))
408                       > pot_.potentialEnergyLimit()
409                     )
410                     {
411                         return true;
412                     };
413                 }
414             }
415         }
416     }
418     return false;
422 inline bool Foam::moleculeCloud::evaluatePotentialLimit
424     molecule* molReal,
425     referredMolecule* molRef
426 ) const
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)
453     {
454         label idsReal(siteIdsReal[sReal]);
456         forAll(siteIdsRef, sRef)
457         {
458             label idsRef(siteIdsRef[sRef]);
460             if (pairPotentialSitesReal[sReal] && pairPotentialSitesRef[sRef])
461             {
462                 vector rsRealsRef =
463                     molReal->sitePositions()[sReal]
464                   - molRef->sitePositions()[sRef];
466                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
468                 if (pairPot.rCutSqr(idsReal, idsRef, rsRealsRefMagSq))
469                 {
470                     scalar rsRealsRefMag = mag(rsRealsRef);
472                     // Guard against pairPot.energy being evaluated
473                     // if rRealRefMag < SMALL. A floating point exception will
474                     // happen otherwise.
476                     if (rsRealsRefMag < SMALL)
477                     {
478                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
479                             << "Molecule site pair closer than "
480                             << SMALL
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."
486                             << endl;
488                         return true;
489                     }
491                     // Guard against pairPot.energy being evaluated if
492                     // rRealRefMag < rMin.  A tabulation lookup error will occur
493                     // otherwise.
495                     if (rsRealsRefMag < pairPot.rMin(idsReal, idsRef))
496                     {
497                         return true;
498                     }
500                     if
501                     (
502                         mag(pairPot.energy(idsReal, idsRef, rsRealsRefMag))
503                       > pot_.potentialEnergyLimit()
504                     )
505                     {
506                         return true;
507                     };
508                 }
509             }
511             if (electrostaticSitesReal[sReal] && electrostaticSitesRef[sRef])
512             {
513                 vector rsRealsRef =
514                     molReal->sitePositions()[sReal]
515                   - molRef->sitePositions()[sRef];
517                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
519                 if (pairPot.rCutMaxSqr(rsRealsRefMagSq))
520                 {
521                     scalar rsRealsRefMag = mag(rsRealsRef);
523                     // Guard against pairPot.energy being evaluated
524                     // if rRealRefMag < SMALL. A floating point exception will
525                     // happen otherwise.
527                     if (rsRealsRefMag < SMALL)
528                     {
529                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
530                             << "Molecule site pair closer than "
531                             << SMALL
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."
537                             << endl;
539                         return true;
540                     }
542                     if (rsRealsRefMag < electrostatic.rMin())
543                     {
544                         return true;
545                     }
547                     scalar chargeReal = constPropReal.siteCharges()[sReal];
549                     scalar chargeRef = constPropRef.siteCharges()[sRef];
551                     if
552                     (
553                         mag
554                         (
555                             chargeReal
556                            *chargeRef
557                            *electrostatic.energy(rsRealsRefMag)
558                         )
559                       > pot_.potentialEnergyLimit()
560                     )
561                     {
562                         return true;
563                     };
564                 }
565             }
566         }
567     }
569     return false;
573 inline Foam::vector Foam::moleculeCloud::equipartitionLinearVelocity
575     scalar temperature,
576     scalar mass
579     return sqrt(kb*temperature/mass)*vector
580     (
581         rndGen_.GaussNormal(),
582         rndGen_.GaussNormal(),
583         rndGen_.GaussNormal()
584     );
588 inline Foam::vector Foam::moleculeCloud::equipartitionAngularMomentum
590     scalar temperature,
591     const molecule::constantProperties& cP
594     scalar sqrtKbT = sqrt(kb*temperature);
596     if (cP.linearMolecule())
597     {
598         return sqrtKbT*vector
599         (
600             0.0,
601             sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
602             sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
603         );
604     }
605     else
606     {
607         return sqrtKbT*vector
608         (
609             sqrt(cP.momentOfInertia().xx())*rndGen_.GaussNormal(),
610             sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
611             sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
612         );
613     }
617 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
619 inline const Foam::polyMesh& Foam::moleculeCloud::mesh() const
621     return mesh_;
625 inline const Foam::potential& Foam::moleculeCloud::pot() const
627     return pot_;
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
641     return il_;
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()
661     return rndGen_;
665 // ************************************************************************* //