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_)
168 <<
"Porosity field has values <= 0 or > 1" 175 <<
"Porosity enabled in constant/porosityProperties " 176 <<
"but no porosity field is found in object registry." 185 void Foam::isoAdvection::setProcessorPatches()
187 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
188 surfaceCellFacesOnProcPatches_.
clear();
189 surfaceCellFacesOnProcPatches_.resize(
patches.
size());
192 procPatchLabels_.clear();
197 isA<processorPolyPatch>(
patches[patchi])
201 procPatchLabels_.append(patchi);
207 void 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]);
241 void Foam::isoAdvection::timeIntegratedFlux()
245 const scalar dt = mesh_.time().deltaTValue();
248 interpolationCellPoint<vector> UInterp(U_);
251 label nSurfaceCells = 0;
259 const scalarField& magSfIn = mesh_.magSf().primitiveField();
263 const cellList& cellFaces = mesh_.cells();
264 const labelList& own = mesh_.faceOwner();
268 DynamicList<List<point>> isoFacePts;
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]);
365 const polyBoundaryMesh& boundaryMesh = mesh_.boundaryMesh();
374 const label facei = bsFaces_[i];
375 const label patchi = boundaryMesh.patchID(facei);
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
399 const polyPatch&
pp = boundaryMesh[patchi];
400 const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(
pp);
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 = " 424 void Foam::isoAdvection::setDownwindFaces
427 DynamicLabelList& downwindFaces
433 const labelList& own = mesh_.faceOwner();
435 const cell&
c =
cells[celli];
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();
462 Foam::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)
498 bool returnSyncedFaces
501 DynamicLabelList syncedFaces(0);
502 const polyBoundaryMesh&
patches = mesh_.boundaryMesh();
506 DynamicList<label> neighProcs;
507 PstreamBuffers pBufs;
510 for (
const label patchi : procPatchLabels_)
512 const processorPolyPatch& procPatch =
513 refCast<const processorPolyPatch>(
patches[patchi]);
514 const label nbrProci = procPatch.neighbProcNo();
517 neighProcs.push_uniq(nbrProci);
519 const scalarField& pFlux = dVf.boundaryField()[patchi];
520 const List<label>& surfCellFacesOnProcPatch =
521 surfaceCellFacesOnProcPatches_[patchi];
523 const UIndirectList<scalar> dVfPatch
526 surfCellFacesOnProcPatch
529 UOPstream toNbr(nbrProci, pBufs);
530 toNbr << surfCellFacesOnProcPatch << dVfPatch;
534 pBufs.finishedNeighbourSends(neighProcs);
538 for (
const label patchi : procPatchLabels_)
540 const processorPolyPatch& procPatch =
541 refCast<const processorPolyPatch>(
patches[patchi]);
542 const label nbrProci = procPatch.neighbProcNo();
545 List<scalar> nbrdVfs;
548 UIPstream fromNbr(nbrProci, pBufs);
549 fromNbr >> faceIDs >> nbrdVfs;
552 if (returnSyncedFaces)
554 List<label> syncedFaceI(faceIDs);
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();
609 void Foam::isoAdvection::checkIfOnProcPatch(
const label facei)
611 if (!mesh_.isInternalFace(facei))
613 const polyBoundaryMesh&
pbm = mesh_.boundaryMesh();
616 if (isA<processorPolyPatch>(
pbm[patchi]) && !
pbm[patchi].empty())
618 const label patchFacei =
pbm[patchi].whichFace(facei);
619 surfaceCellFacesOnProcPatches_[patchi].
append(patchFacei);
625 void 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))
644 alpha1_.clamp_range(zero_one{});
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: " 706 << os.name() <<
nl <<
endl;
708 for (
const auto& procFacePts : allProcFaces)
710 for (
const auto& facePts : procFacePts)
712 os.writeFace(facePts,
false);
719 mkDir(outputFile.path());
720 OBJstream os(outputFile);
721 Info<<
nl <<
"isoAdvection: writing iso faces to file: " 722 << os.name() <<
nl <<
endl;
724 for (
const auto& facePts : faces)
726 os.writeFace(facePts,
false);
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.
constexpr char nl
The newline '\n' character (0x0a)
Ostream & endl(Ostream &os)
Add newline and flush stream.
const labelList & patchID() const
Per boundary face label the patch index.
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.
static int myProcNo(label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
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.
const Time & time() const
Return the top-level database.
GeometricField< vector, fvPatchField, volMesh > volVectorField
conserve primitiveFieldRef()+
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
A UList of labels.
static void gatherList(UList< T > &values, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Gather data, but keep individual values separate.
#define forAll(list, i)
Loop across all elements in list.
void writeSurfaceCells() const
Return cellSet of surface cells.
void writeIsoFaces(const UList< List< point >> &isoFacePts) const
Write isoface points to .obj file.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
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.
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].
MinMax< Type > gMinMax(const FieldField< Field, Type > &f)
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.
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.
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.
static label nProcs(label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
decomposeUsingBbs false
Use bounding boxes (default) or unique decomposition of triangles (i.e. do not duplicate triangles) ...
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.
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)
static bool master(label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
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