77 const wordRes& filters
80 if (!filters.empty() && !filters.match(
name))
88 writePropertyName<Type>(
os,
name, delim);
102 const Field<Type>&
values,
105 const wordRes& filters
108 if (!filters.empty() && !filters.match(
name))
123 writePropertyName<Type>(
os, tag, delim);
139 template<
class TrackCloudType>
142 const bool readOnProc =
c.size();
146 const bool haveFile = procIO.typeHeaderOk<IOField<label>>(
true);
148 IOField<label> origProcId(procIO, readOnProc && haveFile);
149 c.checkFieldIOobject(
c, origProcId);
151 IOField<label> origId
154 readOnProc && haveFile
156 c.checkFieldIOobject(
c, origId);
159 for (particle&
p :
c)
161 p.origProc_ = origProcId[i];
162 p.origId_ = origId[i];
169 template<
class TrackCloudType>
172 const label np =
c.size();
173 const bool writeOnProc =
c.size();
175 if (writeLagrangianCoordinates)
177 IOPosition<TrackCloudType> ioP(
c);
178 ioP.write(writeOnProc);
180 else if (!writeLagrangianPositions)
183 <<
"Must select coordinates and/or positions" <<
nl 188 if (writeLagrangianPositions)
190 IOPosition<TrackCloudType> ioP
195 ioP.write(writeOnProc);
198 IOField<label> origProc
203 IOField<label> origId
210 for (
const particle&
p :
c)
212 origProc[i] =
p.origProc_;
213 origId[i] =
p.origId_;
218 origProc.
write(writeOnProc);
219 origId.write(writeOnProc);
223 template<
class CloudType>
230 const label np =
c.size();
231 const label newNp = (positionPtr ? positionPtr->size() : 0);
234 for (label i = newNp; i < np; ++i)
236 parcelType*
p =
c.last();
238 c.deleteParticle(*
p);
243 const auto& position = *positionPtr;
245 const auto& origProcId = cloud::lookupIOField<label>(
"origProc", obr);
246 const auto& origId = cloud::lookupIOField<label>(
"origId", obr);
249 for (label i = np; i < newNp; ++i)
251 c.addParticle(
new parcelType(
c.pMesh(), position[i], -1));
255 for (particle&
p :
c)
257 p.origProc_ = origProcId[i];
258 p.origId_ = origId[i];
263 p.relocate(position[i]);
272 template<
class CloudType>
275 const label np =
c.size();
277 auto& origProc = cloud::createIOField<label>(
"origProc", np, obr);
278 auto& origId = cloud::createIOField<label>(
"origId", np, obr);
279 auto& position = cloud::createIOField<point>(
"position", np, obr);
282 for (
const particle&
p :
c)
284 origProc[i] =
p.origProc_;
285 origId[i] =
p.origId_;
286 position[i] =
p.position();
293 template<
class TrackCloudType>
296 const vector& displacement,
297 TrackCloudType& cloud,
301 typename TrackCloudType::particleType&
p =
302 static_cast<typename TrackCloudType::particleType&
>(*this);
303 typename TrackCloudType::particleType::trackingData& ttd =
304 static_cast<typename TrackCloudType::particleType::trackingData&
>(
td);
306 if (!
p.hitPatch(cloud, ttd))
308 const polyPatch&
patch = mesh_.boundaryMesh()[
p.patch()];
310 if (isA<wedgePolyPatch>(
patch))
312 p.hitWedgePatch(cloud, ttd);
314 else if (isA<symmetryPlanePolyPatch>(
patch))
316 p.hitSymmetryPlanePatch(cloud, ttd);
318 else if (isA<symmetryPolyPatch>(
patch))
320 p.hitSymmetryPatch(cloud, ttd);
322 else if (isA<cyclicPolyPatch>(
patch))
324 p.hitCyclicPatch(cloud, ttd);
326 else if (isA<cyclicACMIPolyPatch>(
patch))
328 p.hitCyclicACMIPatch(cloud, ttd, displacement);
330 else if (isA<cyclicAMIPolyPatch>(
patch))
332 p.hitCyclicAMIPatch(cloud, ttd, displacement);
334 else if (isA<processorPolyPatch>(
patch))
336 p.hitProcessorPatch(cloud, ttd);
338 else if (isA<wallPolyPatch>(
patch))
340 p.hitWallPatch(cloud, ttd);
344 td.keepParticle =
false;
350 template<
class TrackCloudType>
353 const vector& displacement,
354 TrackCloudType& cloud,
362 else if (onInternalFace())
366 else if (onBoundaryFace())
370 changeToMasterPatch();
377 template<
class TrackCloudType>
381 const scalar fraction,
382 TrackCloudType& cloud,
392 template<
class TrackCloudType>
399 template<
class TrackCloudType>
403 <<
"Hitting a wedge patch should not be possible." 410 template<
class TrackCloudType>
413 TrackCloudType&
cloud,
421 template<
class TrackCloudType>
426 transformProperties(
I - 2.0*nf*nf);
430 template<
class TrackCloudType>
436 const label receiveFacei = receiveCpp.
whichFace(facei_);
440 celli_ = mesh_.faceOwner()[facei_];
442 tetPti_ = mesh_.faces()[tetFacei_].size() - 1 - tetPti_;
454 : receiveCpp.
forwardT()[receiveFacei]
456 transformProperties(
T);
466 transformProperties(-
s);
471 template<
class TrackCloudType>
476 const vector& displacement
481 const cyclicAMIPolyPatch& cpp =
482 static_cast<const cyclicAMIPolyPatch&
>(mesh_.boundaryMesh()[
patch()]);
483 const cyclicAMIPolyPatch& receiveCpp = cpp.
neighbPatch();
484 const label sendFacei = cpp.
whichFace(facei_);
485 const label receiveFacei = cpp.pointFace(sendFacei, displacement,
pos);
487 if (receiveFacei < 0)
491 td.keepParticle =
false;
493 <<
"Particle lost across " << cyclicAMIPolyPatch::typeName
494 <<
" patches " << cpp.name() <<
" and " << receiveCpp.name()
495 <<
" at position " <<
pos <<
endl;
499 facei_ = tetFacei_ = receiveFacei + receiveCpp.start();
502 vector displacementT = displacement;
503 cpp.reverseTransformDirection(displacementT, sendFacei);
509 const vector dispDir = cpp.fraction()*displacementT;
510 stepFraction_ += cpp.fraction();
515 mesh_.faceOwner()[facei_],
517 "Particle crossed between " + cyclicAMIPolyPatch::typeName +
518 " patches " + cpp.
name() +
" and " + receiveCpp.name() +
519 " to a location outside of the mesh." 527 if (!receiveCpp.parallel())
531 receiveCpp.forwardT().size() == 1
532 ? receiveCpp.forwardT()[0]
533 : receiveCpp.forwardT()[receiveFacei]
535 transformProperties(
T);
537 else if (receiveCpp.separated())
541 (receiveCpp.separation().size() == 1)
542 ? receiveCpp.separation()[0]
543 : receiveCpp.separation()[receiveFacei]
545 transformProperties(-
s);
570 template<
class TrackCloudType>
573 TrackCloudType& cloud,
575 const vector& displacement
578 const cyclicACMIPolyPatch& cpp =
579 static_cast<const cyclicACMIPolyPatch&
>(mesh_.boundaryMesh()[
patch()]);
581 const label localFacei = cpp.whichFace(facei_);
585 const scalar mask = cpp.mask()[localFacei];
586 bool couple = mask >= 1 - cpp.tolerance();
587 bool nonOverlap = mask <= cpp.tolerance();
592 if (!couple && !nonOverlap)
595 couple = cpp.pointFace(localFacei, displacement,
pos) >= 0;
596 nonOverlap = !couple;
601 hitCyclicAMIPatch(cloud,
td, displacement);
607 tetFacei_ = facei_ = cpp.nonOverlapPatch().start() + localFacei;
610 hitBoundaryFace(displacement,
cloud,
td);
615 template<
class TrackCloudType>
620 template<
class TrackCloudType>
static const IOField< point > * findIOPosition(const objectRegistry &obr)
Locate the "position" IOField within object registry.
void hitCyclicACMIPatch(TrackCloudType &, trackingData &, const vector &)
Overridable function to handle the particle hitting a.
void size(const label n)
Older name for setAddressableSize.
label whichFace(const label facei) const noexcept
Return label of face in patch from global face label.
DSMCCloud< dsmcParcel > CloudType
virtual bool separated() const
Are the planes separated.
errorManipArg< error, int > exit(error &err, const int errNo=1)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
wallPoints::trackData td(isBlockedFace, regionToBlockSize)
static void writeProperty(Ostream &os, const word &name, const Type &value, const bool nameOnly, const word &delim, const wordRes &filters=wordRes::null())
Write a named particle property to stream, optionally filtered based on its name. ...
constexpr char nl
The newline '\n' character (0x0a)
Ostream & endl(Ostream &os)
Add newline and flush stream.
A traits class, which is primarily used for primitives and vector-space.
void hitWallPatch(TrackCloudType &, trackingData &)
Overridable function to handle the particle hitting a wallPatch.
void hitSymmetryPlanePatch(TrackCloudType &, trackingData &)
Overridable function to handle the particle hitting a.
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
static void writePropertyName(Ostream &os, const word &name, const word &delim)
Write the name representation to stream.
void hitSymmetryPatch(TrackCloudType &, trackingData &)
Overridable function to handle the particle hitting a symmetryPatch.
virtual const vectorField & separation() const
If the planes are separated the separation vector.
virtual const tensorField & forwardT() const
Return face transformation tensor.
#define forAll(list, i)
Loop across all elements in list.
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
virtual bool parallel() const
Are the cyclic planes parallel.
dimensionedScalar pos(const dimensionedScalar &ds)
void hitBoundaryFace(const vector &direction, TrackCloudType &cloud, trackingData &td)
Dispatch function for boundary face interaction. Calls one of.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
void hitFace(const vector &direction, TrackCloudType &cloud, trackingData &td)
Hit the current face. If the current face is internal than this.
static const Identity< scalar > I
void hitProcessorPatch(TrackCloudType &, trackingData &)
Overridable function to handle the particle hitting a processorPatch.
A class for handling words, derived from Foam::string.
A cloud is a registry collection of lagrangian particles.
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
void hitCyclicPatch(TrackCloudType &, trackingData &)
Overridable function to handle the particle hitting a cyclicPatch.
errorManip< error > abort(error &err)
void hitCyclicAMIPatch(TrackCloudType &, trackingData &, const vector &)
Overridable function to handle the particle hitting a cyclicAMIPatch.
ParcelType parcelType
Type of parcel the cloud was instantiated for.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
OBJstream os(runTime.globalPath()/outputName)
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
const word & name() const noexcept
Return const reference to name.
void hitWedgePatch(TrackCloudType &, trackingData &)
Overridable function to handle the particle hitting a wedgePatch.
#define WarningInFunction
Report a warning using Foam::Warning.
static void readFields(TrackCloudType &c)
Read the fields associated with the owner cloud.
static void readObjects(CloudType &c, const objectRegistry &obr)
Read particle fields as objects from the obr registry.
const dimensionedScalar c
Speed of light in a vacuum.
static void writeFields(const TrackCloudType &c)
Write the fields associated with the owner cloud.
const std::string patch
OpenFOAM patch number as a std::string.
bool hitPatch(TrackCloudType &, trackingData &)
Overridable function to handle the particle hitting a patch.
label transformGlobalFace(const label facei) const
void trackToAndHitFace(const vector &direction, const scalar fraction, TrackCloudType &cloud, trackingData &td)
Convenience function. Combines trackToFace and hitFace.
Registry of regIOobjects.
const cyclicPolyPatch & neighbPatch() const
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
static void writeObjects(const CloudType &c, objectRegistry &obr)
Write particle fields as objects into the obr registry.
Tensor of scalars, i.e. Tensor<scalar>.
Templated base class for dsmc cloud.