55Foam::isoAdvection::isoAdvection
98 nAlphaBounds_(dict_.getOrDefault<label>(
"nAlphaBounds", 3)),
99 isoFaceTol_(dict_.getOrDefault<scalar>(
"isoFaceTol", 1
e-8)),
100 surfCellTol_(dict_.getOrDefault<scalar>(
"surfCellTol", 1
e-8)),
101 writeIsoFacesToFile_(dict_.getOrDefault(
"writeIsoFaces", false)),
104 surfCells_(label(0.2*mesh_.nCells())),
107 bsFaces_(label(0.2*mesh_.nBoundaryFaces())),
108 bsx0_(bsFaces_.size()),
109 bsn0_(bsFaces_.size()),
110 bsUn0_(bsFaces_.size()),
113 porosityEnabled_(dict_.getOrDefault<bool>(
"porosityEnabled", false)),
114 porosityPtr_(nullptr),
117 procPatchLabels_(mesh_.
boundary().size()),
118 surfaceCellFacesOnProcPatches_(0)
138 setProcessorPatches();
146 "porosityProperties",
157 if (porosityEnabled_)
168 <<
"Porosity field has values <= 0 or > 1"
175 <<
"Porosity enabled in constant/porosityProperties "
176 <<
"but no porosity field is found in object registry."
185void Foam::isoAdvection::setProcessorPatches()
188 surfaceCellFacesOnProcPatches_.
clear();
189 surfaceCellFacesOnProcPatches_.resize(
patches.
size());
192 procPatchLabels_.clear();
201 procPatchLabels_.append(patchi);
207void Foam::isoAdvection::extendMarkedCells
213 bitSet markedFace(mesh_.nFaces());
215 for (
const label celli : markedCell)
217 markedFace.set(mesh_.cells()[celli]);
223 for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
225 if (markedFace.test(facei))
227 markedCell.set(mesh_.faceOwner()[facei]);
228 markedCell.set(mesh_.faceNeighbour()[facei]);
231 for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); ++facei)
233 if (markedFace.test(facei))
235 markedCell.set(mesh_.faceOwner()[facei]);
241void Foam::isoAdvection::timeIntegratedFlux()
245 const scalar dt = mesh_.time().deltaTValue();
251 label nSurfaceCells = 0;
259 const scalarField& magSfIn = mesh_.magSf().primitiveField();
263 const cellList& cellFaces = mesh_.cells();
264 const labelList& own = mesh_.faceOwner();
269 const labelUList& interfaceLabels = surf_->interfaceLabels();
275 const label celli = interfaceLabels[i];
276 const point x0(surf_->centre()[celli]);
278 Un0[i] = UInterp.interpolate(x0, celli) & n0;
282 if (porosityEnabled_)
286 const label celli = interfaceLabels[i];
287 Un0[i] /= porosityPtr_->primitiveField()[celli];
292 forAll(interfaceLabels, i)
294 const label celli = interfaceLabels[i];
295 if (
mag(surf_->normal()[celli]) != 0)
300 surfCells_.append(celli);
301 const point x0(surf_->centre()[celli]);
305 <<
"\n------------ Cell " << celli <<
" with alpha1 = "
306 << alpha1In_[celli] <<
" and 1-alpha1 = "
307 << 1.0 - alpha1In_[celli] <<
" ------------"
313 const cell& celliFaces = cellFaces[celli];
314 for (
const label facei : celliFaces)
316 if (mesh_.isInternalFace(facei))
318 bool isDownwindFace =
false;
320 if (celli == own[facei])
322 if (phiIn[facei] >= 0)
324 isDownwindFace =
true;
329 if (phiIn[facei] < 0)
331 isDownwindFace =
true;
337 dVfIn[facei] = advectFace_.timeIntegratedFaceFlux
352 bsFaces_.append(facei);
355 bsUn0_.append(Un0[i]);
374 const label facei = bsFaces_[i];
377 if (!
phib[patchi].empty())
379 const label patchFacei =
boundaryMesh[patchi].whichFace(facei);
381 const scalar phiP =
phib[patchi][patchFacei];
385 const scalar magSf = magSfb[patchi][patchFacei];
387 dVfb[patchi][patchFacei] = advectFace_.timeIntegratedFaceFlux
403 const label neiPatchID(cpp->neighbPolyPatchID());
404 dVfb[neiPatchID][patchFacei] = -dVfb[patchi][patchFacei];
409 checkIfOnProcPatch(facei);
415 syncProcPatches(dVf_, phi_);
417 writeIsoFaces(isoFacePts);
419 DebugInfo <<
"Number of isoAdvector surface cells = "
424void Foam::isoAdvection::setDownwindFaces
427 DynamicLabelList& downwindFaces
433 const labelList& own = mesh_.faceOwner();
437 downwindFaces.
clear();
440 for (
const label facei: c)
443 const scalar
phi = faceValue(phi_, facei);
445 if (own[facei] == celli)
449 downwindFaces.append(facei);
454 downwindFaces.append(facei);
458 downwindFaces.shrink();
462Foam::scalar Foam::isoAdvection::netFlux
471 const cell&
c = mesh_.cells()[celli];
474 const labelList& own = mesh_.faceOwner();
476 for (
const label facei : c)
478 const scalar dVff = faceValue(dVf, facei);
480 if (own[facei] == celli)
494Foam::DynamicList<Foam::label> Foam::isoAdvection::syncProcPatches
498 bool returnSyncedFaces
501 DynamicLabelList syncedFaces(0);
510 for (
const label patchi : procPatchLabels_)
514 const label nbrProci = procPatch.neighbProcNo();
517 neighProcs.push_uniq(nbrProci);
519 const scalarField& pFlux = dVf.boundaryField()[patchi];
521 surfaceCellFacesOnProcPatches_[patchi];
526 surfCellFacesOnProcPatch
530 toNbr << surfCellFacesOnProcPatch << dVfPatch;
538 for (
const label patchi : procPatchLabels_)
542 const label nbrProci = procPatch.neighbProcNo();
549 fromNbr >> faceIDs >> nbrdVfs;
552 if (returnSyncedFaces)
555 for (label& faceI : syncedFaceI)
557 faceI += procPatch.start();
559 syncedFaces.append(syncedFaceI);
564 Pout<<
"Received at time = " << mesh_.time().value()
565 <<
": surfCellFacesOnProcPatch = " << faceIDs <<
nl
566 <<
"Received at time = " << mesh_.time().value()
567 <<
": dVfPatch = " << nbrdVfs <<
endl;
571 scalarField& localFlux = dVf.boundaryFieldRef()[patchi];
575 const label facei = faceIDs[i];
576 localFlux[facei] = - nbrdVfs[i];
577 if (
debug &&
mag(localFlux[facei] + nbrdVfs[i]) > ROOTVSMALL)
579 Pout<<
"localFlux[facei] = " << localFlux[facei]
580 <<
" and nbrdVfs[i] = " << nbrdVfs[i]
581 <<
" for facei = " << facei <<
endl;
589 forAll(procPatchLabels_, patchLabeli)
591 const label patchi = procPatchLabels_[patchLabeli];
592 const scalarField& localFlux = dVf.boundaryField()[patchi];
593 Pout<<
"time = " << mesh_.time().value() <<
": localFlux = "
594 << localFlux <<
endl;
599 forAll(surfaceCellFacesOnProcPatches_, patchi)
601 surfaceCellFacesOnProcPatches_[patchi].
clear();
609void Foam::isoAdvection::checkIfOnProcPatch(
const label facei)
611 if (!mesh_.isInternalFace(facei))
618 const label patchFacei =
pbm[patchi].whichFace(facei);
619 surfaceCellFacesOnProcPatches_[patchi].
append(patchFacei);
625void Foam::isoAdvection::applyBruteForceBounding()
628 bool alpha1Changed =
false;
630 const scalar snapAlphaTol = dict_.getOrDefault<scalar>(
"snapTol", 0);
631 if (snapAlphaTol > 0)
635 *
pos0(alpha1_ - snapAlphaTol)
636 *
neg0(alpha1_ - (1.0 - snapAlphaTol))
637 +
pos0(alpha1_ - (1.0 - snapAlphaTol));
639 alpha1Changed =
true;
642 if (dict_.getOrDefault(
"clip",
true))
645 alpha1Changed =
true;
650 alpha1_.correctBoundaryConditions();
657 if (!mesh_.time().writeTime())
return;
659 if (dict_.getOrDefault(
"writeSurfCells",
false))
666 mesh_.time().timeName(),
672 cSet.insert(surfCells_);
681 const UList<List<point>>& faces
684 if (!writeIsoFacesToFile_ || !mesh_.time().writeTime())
return;
687 const fileName outputFile
689 mesh_.time().globalPath()
691 /
word::printf(
"isoFaces_%012d.obj", mesh_.time().timeIndex())
703 mkDir(outputFile.path());
704 OBJstream
os(outputFile);
705 Info<<
nl <<
"isoAdvection: writing iso faces to file: "
708 for (
const auto& procFacePts : allProcFaces)
710 for (
const auto& facePts : procFacePts)
712 os.writeFace(facePts,
false);
719 mkDir(outputFile.path());
721 Info<<
nl <<
"isoAdvection: writing iso faces to file: "
724 for (
const auto& facePts : faces)
Macros for easy insertion into run-time selection tables.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const polyBoundaryMesh & pbm
const volScalarField & alpha1
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
GeometricBoundaryField< scalar, fvsPatchField, surfaceMesh > Boundary
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
@ NO_READ
Nothing to be read.
@ READ_IF_PRESENT
Reading is optional [identical to LAZY_READ].
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
void clear()
Clear the list, i.e. set size to zero.
An OFstream that keeps track of vertices and provides convenience output methods for OBJ files.
Ostream & writeFace(const UList< point > &points, const bool lines=true)
Write face loop points with lines/filled-polygon.
virtual const fileName & name() const override
Read/write access to the name of the stream.
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void finishedNeighbourSends(const labelUList &neighProcs, const bool wait=true)
Mark the send phase as being finished, with communication being limited to a known subset of send/rec...
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
const word & constant() const noexcept
Return constant name.
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
A List with indirect addressing. Like IndirectList but does not store addressing.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Output inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run.
@ gatherList
gatherList [manual algorithm]
static bool & parRun() noexcept
Test if this a parallel run.
label size() const noexcept
The number of entries in the list.
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
A collection of cell labels.
A cell is defined as a list of faces with extra functionality.
A class for handling file names.
static std::string path(const std::string &str)
Return directory path name (part before last /).
const Time & time() const
Return the top-level database.
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
Given cell centre values and point (vertex) values decompose into tetrahedra and linear interpolate w...
An implementation of the isoAdvector geometric Volume-of-Fluid method advancing the provided volume f...
void writeIsoFaces(const UList< List< point > > &isoFacePts) const
Write isoface points to .obj file.
void writeSurfaceCells() const
Return cellSet of surface cells.
Type * getObjectPtr(const word &name, const bool recursive=false) const
Return non-const pointer to the object of the given Type, using a const-cast to have it behave like a...
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
const labelList & patchID() const
Per boundary face label the patch index.
void clear()
Clear the patch list and all demand-driven data.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
A patch is a list of labels that address the faces in the global face list.
const vectorField & faceCentres() const
const scalarField & cellVolumes() const
const vectorField & cellCentres() const
const labelListList & cellCells() const
const labelListList & cellPoints() const
const vectorField & faceAreas() const
const cellList & cells() const
Neighbour processor patch.
Original code supplied by Henning Scheufler, DLR (2019).
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
static word printf(const char *fmt, const PrimitiveType &val)
Use a printf-style formatter for a primitive.
Represents 0/1 range or concept. Used for tagged dispatch or clamping.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
const polyBoundaryMesh & patches
IOdictionary porosityProperties(IOobject("porosityProperties", runTime.constant(), runTime, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
Calculate the gradient of the given field.
Surface integrate surfaceField creating a volField. Surface sum a surfaceField creating a volField.
#define DebugInfo
Report an information message using Foam::Info.
#define DebugInFunction
Report an information message using Foam::Info.
const dimensionedScalar c
Speed of light in a vacuum.
Namespace for handling debugging switches.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
GeometricField< vector, fvPatchField, volMesh > volVectorField
dimensionedScalar pos0(const dimensionedScalar &ds)
List< label > labelList
A List of labels.
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
GeometricField< scalar, fvPatchField, volMesh > volScalarField
messageStream Info
Information stream (stdout output on master, null elsewhere).
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Ostream & endl(Ostream &os)
Add newline and flush stream.
List< cell > cellList
List of cell.
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
vector point
Point is a vector.
MinMax< Type > gMinMax(const FieldField< Field, Type > &f)
static constexpr const zero Zero
Global zero (0).
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
dimensionedScalar neg0(const dimensionedScalar &ds)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
errorManipArg< error, int > exit(error &err, const int errNo=1)
UList< label > labelUList
A UList of labels.
const dimensionSet dimVol(dimVolume)
Older spelling for dimVolume.
constexpr char nl
The newline '\n' character (0x0a).
#define addProfilingInFunction(Name)
Define profiling trigger with specified name and description corresponding to the compiler-defined fu...
#define forAll(list, i)
Loop across all elements in list.
conserve primitiveFieldRef()+