moleculeI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "molecule.H"
27 
28 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
29 
31 :
32  siteReferencePositions_(Field<vector>(0)),
33  siteMasses_(List<scalar>(0)),
34  siteCharges_(List<scalar>(0)),
35  siteIds_(List<label>(0)),
36  pairPotentialSites_(List<bool>(false)),
37  electrostaticSites_(List<bool>(false)),
38  momentOfInertia_(diagTensor(0, 0, 0)),
39  mass_(0)
40 {}
41 
42 
44 (
45  const dictionary& dict
46 )
47 :
48  siteReferencePositions_(dict.lookup("siteReferencePositions")),
49  siteMasses_(dict.lookup("siteMasses")),
50  siteCharges_(dict.lookup("siteCharges")),
51  siteIds_(List<word>(dict.lookup("siteIds")).size(), -1),
52  pairPotentialSites_(),
53  electrostaticSites_(),
54  momentOfInertia_(),
55  mass_()
56 {
57  checkSiteListSizes();
58 
59  setInteractionSiteBools
60  (
61  List<word>(dict.lookup("siteIds")),
62  List<word>(dict.lookup("pairPotentialSiteIds"))
63  );
64 
65  mass_ = sum(siteMasses_);
66 
67  vector centreOfMass(Zero);
68 
69  // Calculate the centre of mass of the body and subtract it from each
70  // position
71 
72  forAll(siteReferencePositions_, i)
73  {
74  centreOfMass += siteReferencePositions_[i]*siteMasses_[i];
75  }
76 
77  centreOfMass /= mass_;
78 
79  siteReferencePositions_ -= centreOfMass;
80 
81  if (siteIds_.size() == 1)
82  {
83  // Single site molecule - no rotational motion.
84 
85  siteReferencePositions_[0] = Zero;
86 
87  momentOfInertia_ = diagTensor(-1, -1, -1);
88  }
89  else if (linearMoleculeTest())
90  {
91  // Linear molecule.
92 
93  Info<< nl << "Linear molecule." << endl;
94 
95  vector dir = siteReferencePositions_[1] - siteReferencePositions_[0];
96 
97  dir /= mag(dir);
98 
99  tensor Q = rotationTensor(dir, vector(1,0,0));
100 
101  siteReferencePositions_ = (Q & siteReferencePositions_);
102 
103  // The rotation was around the centre of mass but remove any
104  // components that have crept in due to floating point errors
105 
106  centreOfMass = Zero;
107 
108  forAll(siteReferencePositions_, i)
109  {
110  centreOfMass += siteReferencePositions_[i]*siteMasses_[i];
111  }
112 
113  centreOfMass /= mass_;
114 
115  siteReferencePositions_ -= centreOfMass;
116 
117  diagTensor momOfInertia = Zero;
118 
119  forAll(siteReferencePositions_, i)
120  {
121  const vector& p(siteReferencePositions_[i]);
122 
123  momOfInertia +=
124  siteMasses_[i]*diagTensor(0, p.x()*p.x(), p.x()*p.x());
125  }
126 
127  momentOfInertia_ = diagTensor
128  (
129  -1,
130  momOfInertia.yy(),
131  momOfInertia.zz()
132  );
133  }
134  else
135  {
136  // Fully 6DOF molecule
137 
138  // Calculate the inertia tensor in the current orientation
139 
140  tensor momOfInertia(Zero);
141 
142  forAll(siteReferencePositions_, i)
143  {
144  const vector& p(siteReferencePositions_[i]);
145 
146  momOfInertia += siteMasses_[i]*tensor
147  (
148  p.y()*p.y() + p.z()*p.z(), -p.x()*p.y(), -p.x()*p.z(),
149  -p.y()*p.x(), p.x()*p.x() + p.z()*p.z(), -p.y()*p.z(),
150  -p.z()*p.x(), -p.z()*p.y(), p.x()*p.x() + p.y()*p.y()
151  );
152  }
153 
154  if (eigenValues(momOfInertia).x() < vSmall)
155  {
157  << "An eigenvalue of the inertia tensor is zero, the molecule "
158  << dict.name() << " is not a valid 6DOF shape."
159  << nl << abort(FatalError);
160  }
161 
162  // Normalise the inertia tensor magnitude to avoid small numbers in the
163  // components causing problems
164 
165  momOfInertia /= eigenValues(momOfInertia).x();
166 
167  tensor e = eigenVectors(momOfInertia);
168 
169  // Calculate the transformation between the principle axes to the
170  // global axes
171 
172  tensor Q =
173  vector(1,0,0)*e.x() + vector(0,1,0)*e.y() + vector(0,0,1)*e.z();
174 
175  // Transform the site positions
176 
177  siteReferencePositions_ = (Q & siteReferencePositions_);
178 
179  // Recalculating the moment of inertia with the new site positions
180 
181  // The rotation was around the centre of mass but remove any
182  // components that have crept in due to floating point errors
183 
184  centreOfMass = Zero;
185 
186  forAll(siteReferencePositions_, i)
187  {
188  centreOfMass += siteReferencePositions_[i]*siteMasses_[i];
189  }
190 
191  centreOfMass /= mass_;
192 
193  siteReferencePositions_ -= centreOfMass;
194 
195  // Calculate the moment of inertia in the principle component
196  // reference frame
197 
198  momOfInertia = Zero;
199 
200  forAll(siteReferencePositions_, i)
201  {
202  const vector& p(siteReferencePositions_[i]);
203 
204  momOfInertia += siteMasses_[i]*tensor
205  (
206  p.y()*p.y() + p.z()*p.z(), -p.x()*p.y(), -p.x()*p.z(),
207  -p.y()*p.x(), p.x()*p.x() + p.z()*p.z(), -p.y()*p.z(),
208  -p.z()*p.x(), -p.z()*p.y(), p.x()*p.x() + p.y()*p.y()
209  );
210  }
211 
212  momentOfInertia_ = diagTensor
213  (
214  momOfInertia.xx(),
215  momOfInertia.yy(),
216  momOfInertia.zz()
217  );
218  }
219 }
220 
221 
223 (
224  const polyMesh& mesh,
225  const vector& position,
226  const label celli,
227  const tensor& Q,
228  const vector& v,
229  const vector& a,
230  const vector& pi,
231  const vector& tau,
232  const vector& specialPosition,
233  const constantProperties& constProps,
234  const label special,
235  const label id
236 
237 )
238 :
239  particle(mesh, position, celli),
240  Q_(Q),
241  v_(v),
242  a_(a),
243  pi_(pi),
244  tau_(tau),
245  specialPosition_(specialPosition),
246  potentialEnergy_(0.0),
247  rf_(Zero),
248  special_(special),
249  id_(id),
250  siteForces_(constProps.nSites(), Zero),
251  sitePositions_(constProps.nSites())
252 {
253  setSitePositions(mesh, constProps);
254 }
255 
256 
257 // * * * * * * * constantProperties Private Member Functions * * * * * * * * //
258 
259 inline void Foam::molecule::constantProperties::checkSiteListSizes() const
260 {
261  if
262  (
263  siteIds_.size() != siteReferencePositions_.size()
264  || siteIds_.size() != siteCharges_.size()
265  )
266  {
268  << "Sizes of site id, charge and "
269  << "referencePositions are not the same. "
270  << nl << abort(FatalError);
271  }
272 }
273 
274 
275 inline void Foam::molecule::constantProperties::setInteractionSiteBools
276 (
277  const List<word>& siteIds,
278  const List<word>& pairPotSiteIds
279 )
280 {
281  pairPotentialSites_.setSize(siteIds_.size());
282 
283  electrostaticSites_.setSize(siteIds_.size());
284 
285  forAll(siteIds_, i)
286  {
287  const word& id(siteIds[i]);
288 
289  pairPotentialSites_[i] = (findIndex(pairPotSiteIds, id) > -1);
290 
291  electrostaticSites_[i] = (mag(siteCharges_[i]) > vSmall);
292  }
293 }
294 
295 
296 inline bool Foam::molecule::constantProperties::linearMoleculeTest() const
297 {
298  if (siteIds_.size() == 2)
299  {
300  return true;
301  }
302 
303  vector refDir = siteReferencePositions_[1] - siteReferencePositions_[0];
304 
305  refDir /= mag(refDir);
306 
307  for
308  (
309  label i = 2;
310  i < siteReferencePositions_.size();
311  i++
312  )
313  {
314  vector dir = siteReferencePositions_[i] - siteReferencePositions_[i-1];
315 
316  dir /= mag(dir);
317 
318  if (mag(refDir & dir) < 1 - small)
319  {
320  return false;
321  }
322  }
323 
324  return true;
325 }
326 
327 
328 // * * * * * * * constantProperties Member Functions * * * * * * * * * * * * //
329 
330 inline const Foam::Field<Foam::vector>&
332 {
333  return siteReferencePositions_;
334 }
335 
336 
337 inline const Foam::List<Foam::scalar>&
339 {
340  return siteMasses_;
341 }
342 
343 
344 inline const Foam::List<Foam::scalar>&
346 {
347  return siteCharges_;
348 }
349 
350 
351 inline const Foam::List<Foam::label>&
353 {
354  return siteIds_;
355 }
356 
357 
360 {
361  return siteIds_;
362 }
363 
364 
365 inline const Foam::List<bool>&
367 {
368  return pairPotentialSites_;
369 }
370 
371 
373 (
374  label sId
375 ) const
376 {
377  label s = findIndex(siteIds_, sId);
378 
379  if (s == -1)
380  {
382  << sId << " site not found."
383  << nl << abort(FatalError);
384  }
385 
386  return pairPotentialSites_[s];
387 }
388 
389 
390 inline const Foam::List<bool>&
392 {
393  return electrostaticSites_;
394 }
395 
396 
398 (
399  label sId
400 ) const
401 {
402  label s = findIndex(siteIds_, sId);
403 
404  if (s == -1)
405  {
407  << sId << " site not found."
408  << nl << abort(FatalError);
409  }
410 
411  return electrostaticSites_[s];
412 }
413 
414 
415 inline const Foam::diagTensor&
417 {
418  return momentOfInertia_;
419 }
420 
421 
423 {
424  return ((momentOfInertia_.xx() < 0) && (momentOfInertia_.yy() > 0));
425 }
426 
427 
429 {
430  return (momentOfInertia_.zz() < 0);
431 }
432 
433 
435 {
436  if (linearMolecule())
437  {
438  return 5;
439  }
440  else if (pointMolecule())
441  {
442  return 3;
443  }
444  else
445  {
446  return 6;
447  }
448 }
449 
450 
451 inline Foam::scalar Foam::molecule::constantProperties::mass() const
452 {
453  return mass_;
454 }
455 
456 
458 {
459  return siteIds_.size();
460 
461 }
462 
463 
464 // * * * * * * * * * * * * molecule Member Functions * * * * * * * * * * * * //
465 
466 inline const Foam::tensor& Foam::molecule::Q() const
467 {
468  return Q_;
469 }
470 
471 
473 {
474  return Q_;
475 }
476 
477 
478 inline const Foam::vector& Foam::molecule::v() const
479 {
480  return v_;
481 }
482 
483 
485 {
486  return v_;
487 }
488 
489 
490 inline const Foam::vector& Foam::molecule::a() const
491 {
492  return a_;
493 }
494 
495 
497 {
498  return a_;
499 }
500 
501 
502 inline const Foam::vector& Foam::molecule::pi() const
503 {
504  return pi_;
505 }
506 
507 
509 {
510  return pi_;
511 }
512 
513 
514 inline const Foam::vector& Foam::molecule::tau() const
515 {
516  return tau_;
517 }
518 
519 
521 {
522  return tau_;
523 }
524 
525 
527 {
528  return siteForces_;
529 }
530 
531 
533 {
534  return siteForces_;
535 }
536 
537 
539 {
540  return sitePositions_;
541 }
542 
543 
545 {
546  return sitePositions_;
547 }
548 
549 
551 {
552  return specialPosition_;
553 }
554 
555 
557 {
558  return specialPosition_;
559 }
560 
561 
562 inline Foam::scalar Foam::molecule::potentialEnergy() const
563 {
564  return potentialEnergy_;
565 }
566 
567 
568 inline Foam::scalar& Foam::molecule::potentialEnergy()
569 {
570  return potentialEnergy_;
571 }
572 
573 
574 inline const Foam::tensor& Foam::molecule::rf() const
575 {
576  return rf_;
577 }
578 
579 
581 {
582  return rf_;
583 }
584 
585 
587 {
588  return special_;
589 }
590 
591 
592 inline bool Foam::molecule::tethered() const
593 {
594  return special_ == SPECIAL_TETHERED;
595 }
596 
597 
599 {
600  return id_;
601 }
602 
603 
604 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
const Cmpt & zz() const
Definition: DiagTensorI.H:97
const Cmpt & yy() const
Definition: DiagTensorI.H:91
Pre-declare SubField and related Field type.
Definition: Field.H:82
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
const Cmpt & xx() const
Definition: TensorI.H:163
const Cmpt & zz() const
Definition: TensorI.H:219
const Cmpt & yy() const
Definition: TensorI.H:191
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
Class to hold molecule constant properties.
Definition: molecule.H:91
const diagTensor & momentOfInertia() const
Definition: moleculeI.H:416
const Field< vector > & siteReferencePositions() const
Definition: moleculeI.H:331
const List< label > & siteIds() const
Definition: moleculeI.H:352
const List< bool > & pairPotentialSites() const
Definition: moleculeI.H:366
const List< scalar > & siteCharges() const
Definition: moleculeI.H:345
bool pairPotentialSite(label sId) const
Definition: moleculeI.H:373
bool electrostaticSite(label sId) const
Definition: moleculeI.H:398
const List< scalar > & siteMasses() const
Definition: moleculeI.H:338
const List< bool > & electrostaticSites() const
Definition: moleculeI.H:391
const tensor & Q() const
Definition: moleculeI.H:466
const vector & v() const
Definition: moleculeI.H:478
const List< vector > & sitePositions() const
Definition: moleculeI.H:538
const vector & a() const
Definition: moleculeI.H:490
const List< vector > & siteForces() const
Definition: moleculeI.H:526
const vector & specialPosition() const
Definition: moleculeI.H:550
void setSitePositions(const polyMesh &mesh, const constantProperties &constProps)
Definition: molecule.C:218
label special() const
Definition: moleculeI.H:586
const tensor & rf() const
Definition: moleculeI.H:574
const vector & tau() const
Definition: moleculeI.H:514
scalar potentialEnergy() const
Definition: moleculeI.H:562
const vector & pi() const
Definition: moleculeI.H:502
bool tethered() const
Definition: moleculeI.H:592
molecule(const polyMesh &mesh, const vector &position, const label celli, const tensor &Q, const vector &v, const vector &a, const vector &pi, const vector &tau, const vector &specialPosition, const constantProperties &constProps, const label special, const label id)
Construct from a position and a cell, searching for the rest of the.
Definition: moleculeI.H:223
label id() const
Definition: moleculeI.H:598
Base particle class.
Definition: particle.H:83
vector position(const polyMesh &mesh) const
Return current particle position.
Definition: particleI.H:255
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
static const zero Zero
Definition: zero.H:97
const doubleScalar e
Definition: doubleScalar.H:105
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from unit vector n1 to n2.
Definition: transform.H:47
dimensionedTensor eigenVectors(const dimensionedTensor &dt)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Tensor< scalar > tensor
Tensor of scalars.
Definition: tensor.H:51
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
errorManip< error > abort(error &err)
Definition: errorManip.H:131
messageStream Info
DiagTensor< scalar > diagTensor
A scalar version of the templated DiagTensor.
Definition: diagTensor.H:48
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
dimensioned< scalar > mag(const dimensioned< Type > &)
dimensionedVector eigenValues(const dimensionedTensor &dt)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
static const char nl
Definition: Ostream.H:260
dictionary dict
volScalarField & p