FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

moleculeCloudI.H

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 2008-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00027 
00028 inline void Foam::moleculeCloud::evaluatePair
00029 (
00030     molecule* molI,
00031     molecule* molJ
00032 )
00033 {
00034     const pairPotentialList& pairPot = pot_.pairPotentials();
00035 
00036     const pairPotential& electrostatic = pairPot.electrostatic();
00037 
00038     label idI = molI->id();
00039 
00040     label idJ = molJ->id();
00041 
00042     const molecule::constantProperties& constPropI(constProps(idI));
00043 
00044     const molecule::constantProperties& constPropJ(constProps(idJ));
00045 
00046     List<label> siteIdsI = constPropI.siteIds();
00047 
00048     List<label> siteIdsJ = constPropJ.siteIds();
00049 
00050     List<bool> pairPotentialSitesI = constPropI.pairPotentialSites();
00051 
00052     List<bool> electrostaticSitesI = constPropI.electrostaticSites();
00053 
00054     List<bool> pairPotentialSitesJ = constPropJ.pairPotentialSites();
00055 
00056     List<bool> electrostaticSitesJ = constPropJ.electrostaticSites();
00057 
00058     forAll(siteIdsI, sI)
00059     {
00060         label idsI(siteIdsI[sI]);
00061 
00062         forAll(siteIdsJ, sJ)
00063         {
00064             label idsJ(siteIdsJ[sJ]);
00065 
00066             if (pairPotentialSitesI[sI] && pairPotentialSitesJ[sJ])
00067             {
00068                 vector rsIsJ =
00069                     molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
00070 
00071                 scalar rsIsJMagSq = magSqr(rsIsJ);
00072 
00073                 if(pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
00074                 {
00075                     scalar rsIsJMag = mag(rsIsJ);
00076 
00077                     vector fsIsJ =
00078                         (rsIsJ/rsIsJMag)
00079                        *pairPot.force(idsI, idsJ, rsIsJMag);
00080 
00081                     molI->siteForces()[sI] += fsIsJ;
00082 
00083                     molJ->siteForces()[sJ] += -fsIsJ;
00084 
00085                     scalar potentialEnergy
00086                     (
00087                         pairPot.energy(idsI, idsJ, rsIsJMag)
00088                     );
00089 
00090                     molI->potentialEnergy() += 0.5*potentialEnergy;
00091 
00092                     molJ->potentialEnergy() += 0.5*potentialEnergy;
00093 
00094                     vector rIJ = molI->position() - molJ->position();
00095 
00096                     tensor virialContribution =
00097                         (rsIsJ*fsIsJ)*(rsIsJ & rIJ)/rsIsJMagSq;
00098 
00099                     molI->rf() += virialContribution;
00100 
00101                     molJ->rf() += virialContribution;
00102 
00103                     // molI->rf() += rsIsJ * fsIsJ;
00104 
00105                     // molJ->rf() += rsIsJ * fsIsJ;
00106                 }
00107             }
00108 
00109             if (electrostaticSitesI[sI] && electrostaticSitesJ[sJ])
00110             {
00111                 vector rsIsJ =
00112                 molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
00113 
00114                 scalar rsIsJMagSq = magSqr(rsIsJ);
00115 
00116                 if(rsIsJMagSq <= electrostatic.rCutSqr())
00117                 {
00118                     scalar rsIsJMag = mag(rsIsJ);
00119 
00120                     scalar chargeI = constPropI.siteCharges()[sI];
00121 
00122                     scalar chargeJ = constPropJ.siteCharges()[sJ];
00123 
00124                     vector fsIsJ =
00125                         (rsIsJ/rsIsJMag)
00126                        *chargeI*chargeJ*electrostatic.force(rsIsJMag);
00127 
00128                     molI->siteForces()[sI] += fsIsJ;
00129 
00130                     molJ->siteForces()[sJ] += -fsIsJ;
00131 
00132                     scalar potentialEnergy =
00133                         chargeI*chargeJ
00134                        *electrostatic.energy(rsIsJMag);
00135 
00136                     molI->potentialEnergy() += 0.5*potentialEnergy;
00137 
00138                     molJ->potentialEnergy() += 0.5*potentialEnergy;
00139 
00140                     vector rIJ = molI->position() - molJ->position();
00141 
00142                     tensor virialContribution =
00143                         (rsIsJ*fsIsJ)*(rsIsJ & rIJ)/rsIsJMagSq;
00144 
00145                     molI->rf() += virialContribution;
00146 
00147                     molJ->rf() += virialContribution;
00148 
00149                     // molI->rf() += rsIsJ * fsIsJ;
00150 
00151                     // molJ->rf() += rsIsJ * fsIsJ;
00152                 }
00153             }
00154         }
00155     }
00156 }
00157 
00158 
00159 inline void Foam::moleculeCloud::evaluatePair
00160 (
00161     molecule* molReal,
00162     referredMolecule* molRef
00163 )
00164 {
00165     const pairPotentialList& pairPot = pot_.pairPotentials();
00166 
00167     const pairPotential& electrostatic = pairPot.electrostatic();
00168 
00169     label idReal = molReal->id();
00170 
00171     label idRef = molRef->id();
00172 
00173     const molecule::constantProperties& constPropReal(constProps(idReal));
00174 
00175     const molecule::constantProperties& constPropRef(constProps(idRef));
00176 
00177     List<label> siteIdsReal = constPropReal.siteIds();
00178 
00179     List<label> siteIdsRef = constPropRef.siteIds();
00180 
00181     List<bool> pairPotentialSitesReal = constPropReal.pairPotentialSites();
00182 
00183     List<bool> electrostaticSitesReal = constPropReal.electrostaticSites();
00184 
00185     List<bool> pairPotentialSitesRef = constPropRef.pairPotentialSites();
00186 
00187     List<bool> electrostaticSitesRef = constPropRef.electrostaticSites();
00188 
00189     forAll(siteIdsReal, sReal)
00190     {
00191         label idsReal(siteIdsReal[sReal]);
00192 
00193         forAll(siteIdsRef, sRef)
00194         {
00195             label idsRef(siteIdsRef[sRef]);
00196 
00197             if (pairPotentialSitesReal[sReal] && pairPotentialSitesRef[sRef])
00198             {
00199                 vector rsRealsRef =
00200                     molReal->sitePositions()[sReal]
00201                   - molRef->sitePositions()[sRef];
00202 
00203                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
00204 
00205                 if (pairPot.rCutSqr(idsReal, idsRef, rsRealsRefMagSq))
00206                 {
00207                     scalar rsRealsRefMag = mag(rsRealsRef);
00208 
00209                     vector fsRealsRef =
00210                         (rsRealsRef/rsRealsRefMag)
00211                        *pairPot.force(idsReal, idsRef, rsRealsRefMag);
00212 
00213                     molReal->siteForces()[sReal] += fsRealsRef;
00214 
00215                     scalar potentialEnergy
00216                     (
00217                         pairPot.energy(idsReal, idsRef, rsRealsRefMag)
00218                     );
00219 
00220                     molReal->potentialEnergy() += 0.5*potentialEnergy;
00221 
00222                     vector rRealRef = molReal->position() - molRef->position();
00223 
00224                     molReal->rf() +=
00225                         (rsRealsRef*fsRealsRef)
00226                        *(rsRealsRef & rRealRef)
00227                        /rsRealsRefMagSq;
00228 
00229                     // molReal->rf() += rsRealsRef * fsRealsRef;
00230 
00231                 }
00232             }
00233 
00234             if (electrostaticSitesReal[sReal] && electrostaticSitesRef[sRef])
00235             {
00236                 vector rsRealsRef =
00237                     molReal->sitePositions()[sReal]
00238                   - molRef->sitePositions()[sRef];
00239 
00240                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
00241 
00242                 if (rsRealsRefMagSq <= electrostatic.rCutSqr())
00243                 {
00244                     scalar rsRealsRefMag = mag(rsRealsRef);
00245 
00246                     scalar chargeReal = constPropReal.siteCharges()[sReal];
00247 
00248                     scalar chargeRef = constPropRef.siteCharges()[sRef];
00249 
00250                     vector fsRealsRef =
00251                         (rsRealsRef/rsRealsRefMag)
00252                        *chargeReal*chargeRef
00253                        *electrostatic.force(rsRealsRefMag);
00254 
00255                     molReal->siteForces()[sReal] += fsRealsRef;
00256 
00257                     scalar potentialEnergy =
00258                         chargeReal*chargeRef
00259                        *electrostatic.energy(rsRealsRefMag);
00260 
00261                     molReal->potentialEnergy() += 0.5*potentialEnergy;
00262 
00263                     vector rRealRef = molReal->position() - molRef->position();
00264 
00265                     molReal->rf() +=
00266                         (rsRealsRef*fsRealsRef)
00267                        *(rsRealsRef & rRealRef)
00268                        /rsRealsRefMagSq;
00269 
00270                     // molReal->rf() += rsRealsRef * fsRealsRef;
00271                 }
00272             }
00273         }
00274     }
00275 }
00276 
00277 
00278 inline bool Foam::moleculeCloud::evaluatePotentialLimit
00279 (
00280     molecule* molI,
00281     molecule* molJ
00282 ) const
00283 {
00284     const pairPotentialList& pairPot = pot_.pairPotentials();
00285 
00286     const pairPotential& electrostatic = pairPot.electrostatic();
00287 
00288     label idI = molI->id();
00289 
00290     label idJ = molJ->id();
00291 
00292     const molecule::constantProperties& constPropI(constProps(idI));
00293 
00294     const molecule::constantProperties& constPropJ(constProps(idJ));
00295 
00296     List<label> siteIdsI = constPropI.siteIds();
00297 
00298     List<label> siteIdsJ = constPropJ.siteIds();
00299 
00300     List<bool> pairPotentialSitesI = constPropI.pairPotentialSites();
00301 
00302     List<bool> electrostaticSitesI = constPropI.electrostaticSites();
00303 
00304     List<bool> pairPotentialSitesJ = constPropJ.pairPotentialSites();
00305 
00306     List<bool> electrostaticSitesJ = constPropJ.electrostaticSites();
00307 
00308     forAll(siteIdsI, sI)
00309     {
00310         label idsI(siteIdsI[sI]);
00311 
00312         forAll(siteIdsJ, sJ)
00313         {
00314             label idsJ(siteIdsJ[sJ]);
00315 
00316             if (pairPotentialSitesI[sI] && pairPotentialSitesJ[sJ])
00317             {
00318                 vector rsIsJ =
00319                     molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
00320 
00321                 scalar rsIsJMagSq = magSqr(rsIsJ);
00322 
00323                 if (pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
00324                 {
00325                     scalar rsIsJMag = mag(rsIsJ);
00326 
00327                     // Guard against pairPot.energy being evaluated
00328                     // if rIJMag < SMALL. A floating point exception will
00329                     // happen otherwise.
00330 
00331                     if (rsIsJMag < SMALL)
00332                     {
00333                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
00334                             << "Molecule site pair closer than "
00335                             << SMALL
00336                             << ": mag separation = " << rsIsJMag
00337                             << ". These may have been placed on top of each"
00338                             << " other by a rounding error in mdInitialise in"
00339                             << " parallel or a block filled with molecules"
00340                             << " twice. Removing one of the molecules."
00341                             << endl;
00342 
00343                         return true;
00344                     }
00345 
00346                     // Guard against pairPot.energy being evaluated if rIJMag <
00347                     // rMin.  A tabulation lookup error will occur otherwise.
00348 
00349                     if (rsIsJMag < pairPot.rMin(idsI, idsJ))
00350                     {
00351                         return true;
00352                     }
00353 
00354                     if
00355                     (
00356                         mag(pairPot.energy(idsI, idsJ, rsIsJMag))
00357                       > pot_.potentialEnergyLimit()
00358                     )
00359                     {
00360                         return true;
00361                     };
00362                 }
00363             }
00364 
00365             if (electrostaticSitesI[sI] && electrostaticSitesJ[sJ])
00366             {
00367                 vector rsIsJ =
00368                     molI->sitePositions()[sI] - molJ->sitePositions()[sJ];
00369 
00370                 scalar rsIsJMagSq = magSqr(rsIsJ);
00371 
00372                 if (pairPot.rCutMaxSqr(rsIsJMagSq))
00373                 {
00374                     scalar rsIsJMag = mag(rsIsJ);
00375 
00376                     // Guard against pairPot.energy being evaluated
00377                     // if rIJMag < SMALL. A floating point exception will
00378                     // happen otherwise.
00379 
00380                     if (rsIsJMag < SMALL)
00381                     {
00382                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
00383                             << "Molecule site pair closer than "
00384                             << SMALL
00385                             << ": mag separation = " << rsIsJMag
00386                             << ". These may have been placed on top of each"
00387                             << " other by a rounding error in mdInitialise in"
00388                             << " parallel or a block filled with molecules"
00389                             << " twice. Removing one of the molecules."
00390                             << endl;
00391 
00392                         return true;
00393                     }
00394 
00395                     if (rsIsJMag < electrostatic.rMin())
00396                     {
00397                         return true;
00398                     }
00399 
00400                     scalar chargeI = constPropI.siteCharges()[sI];
00401 
00402                     scalar chargeJ = constPropJ.siteCharges()[sJ];
00403 
00404                     if
00405                     (
00406                         mag(chargeI*chargeJ*electrostatic.energy(rsIsJMag))
00407                       > pot_.potentialEnergyLimit()
00408                     )
00409                     {
00410                         return true;
00411                     };
00412                 }
00413             }
00414         }
00415     }
00416 
00417     return false;
00418 }
00419 
00420 
00421 inline bool Foam::moleculeCloud::evaluatePotentialLimit
00422 (
00423     molecule* molReal,
00424     referredMolecule* molRef
00425 ) const
00426 {
00427     const pairPotentialList& pairPot = pot_.pairPotentials();
00428 
00429     const pairPotential& electrostatic = pairPot.electrostatic();
00430 
00431     label idReal = molReal->id();
00432 
00433     label idRef = molRef->id();
00434 
00435     const molecule::constantProperties& constPropReal(constProps(idReal));
00436 
00437     const molecule::constantProperties& constPropRef(constProps(idRef));
00438 
00439     List<label> siteIdsReal = constPropReal.siteIds();
00440 
00441     List<label> siteIdsRef = constPropRef.siteIds();
00442 
00443     List<bool> pairPotentialSitesReal = constPropReal.pairPotentialSites();
00444 
00445     List<bool> electrostaticSitesReal = constPropReal.electrostaticSites();
00446 
00447     List<bool> pairPotentialSitesRef = constPropRef.pairPotentialSites();
00448 
00449     List<bool> electrostaticSitesRef = constPropRef.electrostaticSites();
00450 
00451     forAll(siteIdsReal, sReal)
00452     {
00453         label idsReal(siteIdsReal[sReal]);
00454 
00455         forAll(siteIdsRef, sRef)
00456         {
00457             label idsRef(siteIdsRef[sRef]);
00458 
00459             if (pairPotentialSitesReal[sReal] && pairPotentialSitesRef[sRef])
00460             {
00461                 vector rsRealsRef =
00462                     molReal->sitePositions()[sReal]
00463                   - molRef->sitePositions()[sRef];
00464 
00465                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
00466 
00467                 if (pairPot.rCutSqr(idsReal, idsRef, rsRealsRefMagSq))
00468                 {
00469                     scalar rsRealsRefMag = mag(rsRealsRef);
00470 
00471                     // Guard against pairPot.energy being evaluated
00472                     // if rRealRefMag < SMALL. A floating point exception will
00473                     // happen otherwise.
00474 
00475                     if (rsRealsRefMag < SMALL)
00476                     {
00477                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
00478                             << "Molecule site pair closer than "
00479                             << SMALL
00480                             << ": mag separation = " << rsRealsRefMag
00481                             << ". These may have been placed on top of each"
00482                             << " other by a rounding error in mdInitialise in"
00483                             << " parallel or a block filled with molecules"
00484                             << " twice. Removing one of the molecules."
00485                             << endl;
00486 
00487                         return true;
00488                     }
00489 
00490                     // Guard against pairPot.energy being evaluated if
00491                     // rRealRefMag < rMin.  A tabulation lookup error will occur
00492                     // otherwise.
00493 
00494                     if (rsRealsRefMag < pairPot.rMin(idsReal, idsRef))
00495                     {
00496                         return true;
00497                     }
00498 
00499                     if
00500                     (
00501                         mag(pairPot.energy(idsReal, idsRef, rsRealsRefMag))
00502                       > pot_.potentialEnergyLimit()
00503                     )
00504                     {
00505                         return true;
00506                     };
00507                 }
00508             }
00509 
00510             if (electrostaticSitesReal[sReal] && electrostaticSitesRef[sRef])
00511             {
00512                 vector rsRealsRef =
00513                     molReal->sitePositions()[sReal]
00514                   - molRef->sitePositions()[sRef];
00515 
00516                 scalar rsRealsRefMagSq = magSqr(rsRealsRef);
00517 
00518                 if (pairPot.rCutMaxSqr(rsRealsRefMagSq))
00519                 {
00520                     scalar rsRealsRefMag = mag(rsRealsRef);
00521 
00522                     // Guard against pairPot.energy being evaluated
00523                     // if rRealRefMag < SMALL. A floating point exception will
00524                     // happen otherwise.
00525 
00526                     if (rsRealsRefMag < SMALL)
00527                     {
00528                         WarningIn("moleculeCloud::removeHighEnergyOverlaps()")
00529                             << "Molecule site pair closer than "
00530                             << SMALL
00531                             << ": mag separation = " << rsRealsRefMag
00532                             << ". These may have been placed on top of each"
00533                             << " other by a rounding error in mdInitialise in"
00534                             << " parallel or a block filled with molecules"
00535                             << " twice. Removing one of the molecules."
00536                             << endl;
00537 
00538                         return true;
00539                     }
00540 
00541                     if (rsRealsRefMag < electrostatic.rMin())
00542                     {
00543                         return true;
00544                     }
00545 
00546                     scalar chargeReal = constPropReal.siteCharges()[sReal];
00547 
00548                     scalar chargeRef = constPropRef.siteCharges()[sRef];
00549 
00550                     if
00551                     (
00552                         mag
00553                         (
00554                             chargeReal
00555                            *chargeRef
00556                            *electrostatic.energy(rsRealsRefMag)
00557                         )
00558                       > pot_.potentialEnergyLimit()
00559                     )
00560                     {
00561                         return true;
00562                     };
00563                 }
00564             }
00565         }
00566     }
00567 
00568     return false;
00569 }
00570 
00571 
00572 inline Foam::vector Foam::moleculeCloud::equipartitionLinearVelocity
00573 (
00574     scalar temperature,
00575     scalar mass
00576 )
00577 {
00578     return sqrt(kb*temperature/mass)*vector
00579     (
00580         rndGen_.GaussNormal(),
00581         rndGen_.GaussNormal(),
00582         rndGen_.GaussNormal()
00583     );
00584 }
00585 
00586 
00587 inline Foam::vector Foam::moleculeCloud::equipartitionAngularMomentum
00588 (
00589     scalar temperature,
00590     const molecule::constantProperties& cP
00591 )
00592 {
00593     scalar sqrtKbT = sqrt(kb*temperature);
00594 
00595     if (cP.linearMolecule())
00596     {
00597         return sqrtKbT*vector
00598         (
00599             0.0,
00600             sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
00601             sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
00602         );
00603     }
00604     else
00605     {
00606         return sqrtKbT*vector
00607         (
00608             sqrt(cP.momentOfInertia().xx())*rndGen_.GaussNormal(),
00609             sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
00610             sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
00611         );
00612     }
00613 }
00614 
00615 
00616 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00617 
00618 inline const Foam::polyMesh& Foam::moleculeCloud::mesh() const
00619 {
00620     return mesh_;
00621 }
00622 
00623 
00624 inline const Foam::potential& Foam::moleculeCloud::pot() const
00625 {
00626     return pot_;
00627 }
00628 
00629 
00630 inline const Foam::List<Foam::DynamicList<Foam::molecule*> >&
00631     Foam::moleculeCloud::cellOccupancy() const
00632 {
00633     return cellOccupancy_;
00634 }
00635 
00636 
00637 inline const Foam::interactionLists&
00638     Foam::moleculeCloud::il() const
00639 {
00640     return il_;
00641 }
00642 
00643 
00644 inline const Foam::List<Foam::molecule::constantProperties>
00645     Foam::moleculeCloud::constProps() const
00646 {
00647     return constPropList_;
00648 }
00649 
00650 
00651 inline const Foam::molecule::constantProperties&
00652     Foam::moleculeCloud::constProps(label id) const
00653 {
00654     return constPropList_[id];
00655 }
00656 
00657 
00658 inline Foam::Random& Foam::moleculeCloud::rndGen()
00659 {
00660     return rndGen_;
00661 }
00662 
00663 
00664 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines