55 Foam::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())),
105 surf_(reconstructionSchemes::
New(alpha1_, phi_, U_, dict_)),
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_)
170 <<
"Porosity field has values <= 0 or > 1" 177 <<
"Porosity enabled in constant/porosityProperties " 178 <<
"but no porosity field is found in object registry." 187 void Foam::isoAdvection::setProcessorPatches()
189 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
190 surfaceCellFacesOnProcPatches_.
clear();
191 surfaceCellFacesOnProcPatches_.resize(
patches.
size());
194 procPatchLabels_.clear();
199 isA<processorPolyPatch>(
patches[patchi])
203 procPatchLabels_.append(patchi);
209 void Foam::isoAdvection::extendMarkedCells
215 bitSet markedFace(mesh_.nFaces());
217 for (
const label celli : markedCell)
219 markedFace.set(mesh_.cells()[celli]);
225 for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
227 if (markedFace.test(facei))
229 markedCell.set(mesh_.faceOwner()[facei]);
230 markedCell.set(mesh_.faceNeighbour()[facei]);
233 for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); ++facei)
235 if (markedFace.test(facei))
237 markedCell.set(mesh_.faceOwner()[facei]);
243 void Foam::isoAdvection::timeIntegratedFlux()
247 const scalar dt = mesh_.time().deltaTValue();
250 interpolationCellPoint<vector> UInterp(U_);
253 label nSurfaceCells = 0;
261 const scalarField& magSfIn = mesh_.magSf().primitiveField();
265 const cellList& cellFaces = mesh_.cells();
266 const labelList& own = mesh_.faceOwner();
270 DynamicList<List<point>> isoFacePts;
271 const DynamicField<label>& interfaceLabels = surf_->interfaceLabels();
277 const label celli = interfaceLabels[i];
278 const point x0(surf_->centre()[celli]);
280 Un0[i] = UInterp.interpolate(x0, celli) & n0;
284 if (porosityEnabled_)
288 const label celli = interfaceLabels[i];
289 Un0[i] /= porosityPtr_->primitiveField()[celli];
294 forAll(interfaceLabels, i)
296 const label celli = interfaceLabels[i];
297 if (
mag(surf_->normal()[celli]) != 0)
302 surfCells_.append(celli);
303 const point x0(surf_->centre()[celli]);
307 <<
"\n------------ Cell " << celli <<
" with alpha1 = " 308 << alpha1In_[celli] <<
" and 1-alpha1 = " 309 << 1.0 - alpha1In_[celli] <<
" ------------" 315 const cell& celliFaces = cellFaces[celli];
316 for (
const label facei : celliFaces)
318 if (mesh_.isInternalFace(facei))
320 bool isDownwindFace =
false;
322 if (celli == own[facei])
324 if (phiIn[facei] >= 0)
326 isDownwindFace =
true;
331 if (phiIn[facei] < 0)
333 isDownwindFace =
true;
339 dVfIn[facei] = advectFace_.timeIntegratedFaceFlux
354 bsFaces_.append(facei);
357 bsUn0_.append(Un0[i]);
367 const polyBoundaryMesh& boundaryMesh = mesh_.boundaryMesh();
376 const label facei = bsFaces_[i];
377 const label patchi = boundaryMesh.patchID(facei);
379 if (!
phib[patchi].empty())
381 const label patchFacei = boundaryMesh[patchi].whichFace(facei);
383 const scalar phiP =
phib[patchi][patchFacei];
387 const scalar magSf = magSfb[patchi][patchFacei];
389 dVfb[patchi][patchFacei] = advectFace_.timeIntegratedFaceFlux
401 const polyPatch&
pp = boundaryMesh[patchi];
402 const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(
pp);
405 const label neiPatchID(cpp->neighbPolyPatchID());
406 dVfb[neiPatchID][patchFacei] = -dVfb[patchi][patchFacei];
411 checkIfOnProcPatch(facei);
417 syncProcPatches(dVf_, phi_);
419 writeIsoFaces(isoFacePts);
421 DebugInfo <<
"Number of isoAdvector surface cells = " 426 void Foam::isoAdvection::setDownwindFaces
429 DynamicLabelList& downwindFaces
435 const labelList& own = mesh_.faceOwner();
437 const cell&
c =
cells[celli];
439 downwindFaces.
clear();
442 for (
const label facei:
c)
445 const scalar
phi = faceValue(phi_, facei);
447 if (own[facei] == celli)
451 downwindFaces.append(facei);
456 downwindFaces.append(facei);
460 downwindFaces.shrink();
464 Foam::scalar Foam::isoAdvection::netFlux
473 const cell&
c = mesh_.cells()[celli];
476 const labelList& own = mesh_.faceOwner();
478 for (
const label facei :
c)
480 const scalar dVff = faceValue(dVf, facei);
482 if (own[facei] == celli)
500 bool returnSyncedFaces
503 DynamicLabelList syncedFaces(0);
504 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
508 DynamicList<label> neighProcs;
509 PstreamBuffers pBufs;
512 for (
const label patchi : procPatchLabels_)
514 const processorPolyPatch& procPatch =
515 refCast<const processorPolyPatch>(
patches[patchi]);
516 const label nbrProci = procPatch.neighbProcNo();
519 neighProcs.push_uniq(nbrProci);
521 const scalarField& pFlux = dVf.boundaryField()[patchi];
522 const List<label>& surfCellFacesOnProcPatch =
523 surfaceCellFacesOnProcPatches_[patchi];
525 const UIndirectList<scalar> dVfPatch
528 surfCellFacesOnProcPatch
531 UOPstream toNbr(nbrProci, pBufs);
532 toNbr << surfCellFacesOnProcPatch << dVfPatch;
536 pBufs.finishedNeighbourSends(neighProcs);
540 for (
const label patchi : procPatchLabels_)
542 const processorPolyPatch& procPatch =
543 refCast<const processorPolyPatch>(
patches[patchi]);
544 const label nbrProci = procPatch.neighbProcNo();
547 List<scalar> nbrdVfs;
550 UIPstream fromNbr(nbrProci, pBufs);
551 fromNbr >> faceIDs >> nbrdVfs;
554 if (returnSyncedFaces)
556 List<label> syncedFaceI(faceIDs);
557 for (label& faceI : syncedFaceI)
559 faceI += procPatch.start();
561 syncedFaces.append(syncedFaceI);
566 Pout<<
"Received at time = " << mesh_.time().value()
567 <<
": surfCellFacesOnProcPatch = " << faceIDs <<
nl 568 <<
"Received at time = " << mesh_.time().value()
569 <<
": dVfPatch = " << nbrdVfs <<
endl;
573 scalarField& localFlux = dVf.boundaryFieldRef()[patchi];
577 const label facei = faceIDs[i];
578 localFlux[facei] = - nbrdVfs[i];
579 if (
debug &&
mag(localFlux[facei] + nbrdVfs[i]) > ROOTVSMALL)
581 Pout<<
"localFlux[facei] = " << localFlux[facei]
582 <<
" and nbrdVfs[i] = " << nbrdVfs[i]
583 <<
" for facei = " << facei <<
endl;
591 forAll(procPatchLabels_, patchLabeli)
593 const label patchi = procPatchLabels_[patchLabeli];
594 const scalarField& localFlux = dVf.boundaryField()[patchi];
595 Pout<<
"time = " << mesh_.time().value() <<
": localFlux = " 596 << localFlux <<
endl;
601 forAll(surfaceCellFacesOnProcPatches_, patchi)
603 surfaceCellFacesOnProcPatches_[patchi].clear();
611 void Foam::isoAdvection::checkIfOnProcPatch(
const label facei)
613 if (!mesh_.isInternalFace(facei))
615 const polyBoundaryMesh&
pbm = mesh_.boundaryMesh();
618 if (isA<processorPolyPatch>(
pbm[patchi]) && !
pbm[patchi].empty())
620 const label patchFacei =
pbm[patchi].whichFace(facei);
621 surfaceCellFacesOnProcPatches_[patchi].
append(patchFacei);
627 void Foam::isoAdvection::applyBruteForceBounding()
630 bool alpha1Changed =
false;
632 const scalar snapAlphaTol = dict_.getOrDefault<scalar>(
"snapTol", 0);
633 if (snapAlphaTol > 0)
637 *
pos0(alpha1_ - snapAlphaTol)
638 *
neg0(alpha1_ - (1.0 - snapAlphaTol))
639 +
pos0(alpha1_ - (1.0 - snapAlphaTol));
641 alpha1Changed =
true;
644 if (dict_.getOrDefault(
"clip",
true))
646 alpha1_.clamp_range(zero_one{});
647 alpha1Changed =
true;
652 alpha1_.correctBoundaryConditions();
659 if (!mesh_.time().writeTime())
return;
661 if (dict_.getOrDefault(
"writeSurfCells",
false))
668 mesh_.time().timeName(),
674 cSet.insert(surfCells_);
683 const DynamicList<List<point>>& faces
686 if (!writeIsoFacesToFile_ || !mesh_.time().writeTime())
return;
689 const fileName outputFile
691 mesh_.time().globalPath()
693 /
word::printf(
"isoFaces_%012d.obj", mesh_.time().timeIndex())
705 mkDir(outputFile.path());
706 OBJstream
os(outputFile);
707 Info<<
nl <<
"isoAdvection: writing iso faces to file: " 712 const DynamicList<List<point>>& procFacePts
716 for (
const List<point>& facePts : procFacePts)
725 mkDir(outputFile.path());
726 OBJstream
os(outputFile);
727 Info<<
nl <<
"isoAdvection: writing iso faces to file: " 730 for (
const List<point>& facePts : faces)
Ostream & writeFace(const UList< point > &points, const bool lines=true)
Write face loop points with lines/filled-polygon.
const polyBoundaryMesh & pbm
Surface integrate surfaceField creating a volField. Surface sum a surfaceField creating a volField...
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
List< cell > cellList
List of cell.
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
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.
Type gMin(const FieldField< Field, Type > &f)
virtual const fileName & name() const override
Read/write access to the name of the stream.
constexpr char nl
The newline '\n' character (0x0a)
Ostream & endl(Ostream &os)
Add newline and flush stream.
static void gatherList(const UList< commsStruct > &comms, UList< T > &values, const int tag, const label comm)
Gather data, but keep individual values separate. Uses the specified communication schedule...
const labelList & patchID() const
Per boundary face label the patch index.
void writeIsoFaces(const DynamicList< List< point >> &isoFacePts) const
Write isoface points to .obj file.
static bool & parRun() noexcept
Test if this a parallel run.
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.
const dimensionSet dimVol(dimVolume)
Older spelling for dimVolume.
const cellList & cells() const
GeometricBoundaryField< scalar, fvsPatchField, surfaceMesh > Boundary
Type of boundary fields.
Ignore writing from objectRegistry::writeObject()
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
const Time & time() const
Return the top-level database.
GeometricField< vector, fvPatchField, volMesh > volVectorField
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
conserve primitiveFieldRef()+
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
void writeSurfaceCells() const
Return cellSet of surface cells.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
const dimensionedScalar e
Elementary charge.
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Calculate the gradient of the given field.
void clear()
Clear the list, i.e. set size to zero.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
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...
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
#define DebugInFunction
Report an information message using Foam::Info.
label size() const noexcept
The number of entries in the list.
dimensionedScalar neg0(const dimensionedScalar &ds)
Reading is optional [identical to LAZY_READ].
const vectorField & cellCentres() const
#define DebugInfo
Report an information message using Foam::Info.
static word printf(const char *fmt, const PrimitiveType &val)
Use a printf-style formatter for a primitive.
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
dimensionedScalar pos0(const dimensionedScalar &ds)
void clear()
Clear the patch list and all demand-driven data.
const word & constant() const noexcept
Return constant name.
int debug
Static debugging option.
Type gMax(const FieldField< Field, Type > &f)
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
IOdictionary porosityProperties(IOobject("porosityProperties", runTime.constant(), runTime, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE))
const vectorField & faceCentres() const
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
vector point
Point is a vector.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const vectorField & faceAreas() const
const dimensionedScalar c
Speed of light in a vacuum.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
const polyBoundaryMesh & patches
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
#define addProfilingInFunction(Name)
Define profiling trigger with specified name and description corresponding to the compiler-defined fu...
messageStream Info
Information stream (stdout output on master, null elsewhere)
List< label > labelList
A List of labels.
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
const labelListList & cellCells() const
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
const labelListList & cellPoints() const
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const scalarField & cellVolumes() const
static constexpr const zero Zero
Global zero (0)
const volScalarField & alpha1