molecule.C
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-2025 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 "moleculeCloud.H"
27 #include "molecule.H"
28 #include "meshSearch.H"
29 #include "randomGenerator.H"
30 #include "Time.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 Foam::tensor Foam::molecule::rotationTensorX(scalar phi) const
35 {
36  return tensor
37  (
38  1, 0, 0,
39  0, Foam::cos(phi), -Foam::sin(phi),
40  0, Foam::sin(phi), Foam::cos(phi)
41  );
42 }
43 
44 
45 Foam::tensor Foam::molecule::rotationTensorY(scalar phi) const
46 {
47  return tensor
48  (
49  Foam::cos(phi), 0, Foam::sin(phi),
50  0, 1, 0,
51  -Foam::sin(phi), 0, Foam::cos(phi)
52  );
53 }
54 
55 
56 Foam::tensor Foam::molecule::rotationTensorZ(scalar phi) const
57 {
58  return tensor
59  (
60  Foam::cos(phi), -Foam::sin(phi), 0,
61  Foam::sin(phi), Foam::cos(phi), 0,
62  0, 0, 1
63  );
64 }
65 
66 
67 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
68 
70 (
72  trackingData& td
73 )
74 {
75  td.keepParticle = true;
76  td.sendToProc = -1;
77 
78  const constantProperties& constProps(cloud.constProps(id_));
79 
80  const scalar trackTime = td.mesh.time().deltaTValue();
81 
82  if (td.part() == trackingData::tpVelocityHalfStep0)
83  {
84  // First leapfrog velocity adjust part, required before tracking+force
85  // part
86 
87  v_ += 0.5*trackTime*a_;
88 
89  pi_ += 0.5*trackTime*tau_;
90  }
91  else if (td.part() == trackingData::tpLinearTrack)
92  {
93  // Leapfrog tracking part
94 
95  while (td.keepParticle && td.sendToProc == -1 && stepFraction() < 1)
96  {
97  const scalar f = 1 - stepFraction();
98  trackToAndHitFace(f*trackTime*v_, f, cloud, td);
99  }
100  }
101  else if (td.part() == trackingData::tpRotationalTrack)
102  {
103  // Leapfrog orientation adjustment, carried out before force calculation
104  // but after tracking stage, i.e. rotation carried once linear motion
105  // complete.
106 
107  if (!constProps.pointMolecule())
108  {
109  const diagTensor& momentOfInertia(constProps.momentOfInertia());
110 
111  tensor R;
112 
113  if (!constProps.linearMolecule())
114  {
115  R = rotationTensorX(0.5*trackTime*pi_.x()/momentOfInertia.xx());
116  pi_ = pi_ & R;
117  Q_ = Q_ & R;
118  }
119 
120  R = rotationTensorY(0.5*trackTime*pi_.y()/momentOfInertia.yy());
121  pi_ = pi_ & R;
122  Q_ = Q_ & R;
123 
124  R = rotationTensorZ(trackTime*pi_.z()/momentOfInertia.zz());
125  pi_ = pi_ & R;
126  Q_ = Q_ & R;
127 
128  R = rotationTensorY(0.5*trackTime*pi_.y()/momentOfInertia.yy());
129  pi_ = pi_ & R;
130  Q_ = Q_ & R;
131 
132  if (!constProps.linearMolecule())
133  {
134  R = rotationTensorX(0.5*trackTime*pi_.x()/momentOfInertia.xx());
135  pi_ = pi_ & R;
136  Q_ = Q_ & R;
137  }
138  }
139 
140  setSitePositions(td.mesh, constProps);
141  }
142  else if (td.part() == trackingData::tpVelocityHalfStep1)
143  {
144  // Second leapfrog velocity adjust part, required after tracking+force
145  // part
146 
147  scalar m = constProps.mass();
148 
149  a_ = Zero;
150 
151  tau_ = Zero;
152 
153  forAll(siteForces_, s)
154  {
155  const vector& f = siteForces_[s];
156 
157  a_ += f/m;
158 
159  tau_ += (constProps.siteReferencePositions()[s] ^ (Q_.T() & f));
160  }
161 
162  v_ += 0.5*trackTime*a_;
163 
164  pi_ += 0.5*trackTime*tau_;
165 
166  if (constProps.pointMolecule())
167  {
168  tau_ = Zero;
169 
170  pi_ = Zero;
171  }
172 
173  if (constProps.linearMolecule())
174  {
175  tau_.x() = 0.0;
176 
177  pi_.x() = 0.0;
178  }
179  }
180  else
181  {
183  << td.part() << " is an invalid part of the integration method."
184  << abort(FatalError);
185  }
186 
187  return td.keepParticle;
188 }
189 
190 
192 {
194 
195  Q_ = transform.T() & Q_;
196 
197  v_ = transform.transform(v_);
198 
199  a_ = transform.transform(a_);
200 
201  pi_ = Q_.T() & transform.transform(Q_ & pi_);
202 
203  tau_ = Q_.T() & transform.transform(Q_ & tau_);
204 
205  rf_ = transform.transform(rf_);
206 
207  transform.transformList(siteForces_);
208 
209  sitePositions_ = transform.transformPosition(vectorField(sitePositions_));
210 
211  if (special_ == SPECIAL_TETHERED)
212  {
213  specialPosition_ = transform.transformPosition(specialPosition_);
214  }
215 }
216 
217 
219 (
220  const polyMesh& mesh,
221  const constantProperties& constProps
222 )
223 {
224  sitePositions_ =
225  position(mesh)
226  + (Q_ & constProps.siteReferencePositions());
227 }
228 
229 
231 {
232  sitePositions_.setSize(size);
233 
234  siteForces_.setSize(size);
235 }
236 
237 
239 {
240  const vector nw = normal(td.mesh);
241  const scalar vn = v_ & nw;
242 
243  // Specular reflection
244  if (vn > 0)
245  {
246  v_ -= 2*vn*nw;
247  }
248 }
249 
250 
251 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
scalar deltaTValue() const
Return time step value.
Definition: TimeStateI.H:34
Base class for clouds. Provides a basic evolution algorithm, models, and a database for caching deriv...
Definition: cloud.H:61
Class to hold molecule constant properties.
Definition: molecule.H:91
const diagTensor & momentOfInertia() const
Definition: moleculeI.H:417
const Field< vector > & siteReferencePositions() const
Definition: moleculeI.H:332
Class used to pass tracking data to the trackToFace function.
Definition: molecule.H:169
trackPart part() const
Return the part of the tracking operation taking place.
Definition: molecule.H:203
void setSiteSizes(label size)
Definition: molecule.C:230
void setSitePositions(const polyMesh &mesh, const constantProperties &constProps)
Definition: molecule.C:219
bool move(moleculeCloud &, trackingData &)
Definition: molecule.C:70
virtual void transformProperties(const transformer &)
Transform the physical properties of the particle.
Definition: molecule.C:191
void hitWallPatch(moleculeCloud &cloud, trackingData &td)
Overridable function to handle the particle hitting a wallPatch.
Definition: molecule.C:238
Calculates the inertia tensor and principal axes and moments of a polyhedra/cells/triSurfaces....
const Time & time() const
Return time.
label sendToProc
Processor to send the particle to. -1 indicates that this.
Definition: particle.H:111
bool keepParticle
Flag to indicate whether to keep particle (false = delete)
Definition: particle.H:107
const polyMesh & mesh
Reference to the mesh.
Definition: particle.H:104
virtual void transformProperties(const transformer &)
Transform the physical properties of the particle.
Definition: particle.C:244
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
Vector-tensor class used to perform translations, rotations and scaling operations in 3D space.
Definition: transformer.H:84
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
point position(const polyMesh &mesh, const barycentric &coordinates, const label celli, const label facei, const label faceTrii, const scalar stepFraction)
Return the position given the coordinates and tet topology.
Definition: trackingI.H:224
static const zero Zero
Definition: zero.H:97
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
void transform(GeometricField< Type, GeoMesh > &rtf, const GeometricField< tensor, GeoMesh > &trf, const GeometricField< Type, GeoMesh > &tf)
errorManip< error > abort(error &err)
Definition: errorManip.H:131
dimensionedScalar sin(const dimensionedScalar &ds)
Field< vector > vectorField
Specialisation of Field<T> for vector.
static scalar R(const scalar a, const scalar x)
Definition: invIncGamma.C:102
error FatalError
dimensionedScalar cos(const dimensionedScalar &ds)
labelList f(nPoints)