Compare commits
18 Commits
ami-cache-
...
multi-fini
| Author | SHA1 | Date | |
|---|---|---|---|
| 7207e9e3a9 | |||
| 6d2deda470 | |||
| c172b588c0 | |||
| c075af4f7b | |||
| a1e5dcee43 | |||
| f2922f1ae9 | |||
| 1ae48880d2 | |||
| 9fc52d42eb | |||
| c669f7b736 | |||
| 27878797e2 | |||
| e9fcd75ec4 | |||
| ac34d9fd29 | |||
| 14bece937b | |||
| 2396828a60 | |||
| 9223d238bd | |||
| 4b92bb6533 | |||
| 55c81bce1b | |||
| 1cb0b7b6c9 |
@ -200,7 +200,7 @@ void printTypeName()
|
||||
|
||||
|
||||
template<class Type, bool UseTypeName = true>
|
||||
void printPstreamTraits(const std::string_view name = std::string_view())
|
||||
void printPstreamTraits(std::string_view name = std::string_view())
|
||||
{
|
||||
Info<< "========" << nl;
|
||||
Info<< "type: ";
|
||||
@ -299,6 +299,9 @@ void printPstreamTraits(const std::string_view name = std::string_view())
|
||||
// Use element or component type (or byte-wise) for data type
|
||||
using base = typename UPstream_dataType<Type>::base;
|
||||
|
||||
// The sizing factor is constexpr
|
||||
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
|
||||
|
||||
Info<< " : ";
|
||||
if constexpr (UseTypeName)
|
||||
{
|
||||
@ -311,8 +314,7 @@ void printPstreamTraits(const std::string_view name = std::string_view())
|
||||
|
||||
Info<< " cmpt-type=";
|
||||
printDataTypeId(UPstream_dataType<Type>::datatype_id);
|
||||
Info<< " count=" << UPstream_dataType<Type>::size(1);
|
||||
Info<< nl;
|
||||
Info<< " count=" << count << nl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,6 +364,24 @@ void print_data_opType(BinaryOp bop, std::string_view name)
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class Type>
|
||||
int check_simple(std::string_view name = std::string_view())
|
||||
{
|
||||
// The sizing factor is constexpr
|
||||
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
|
||||
|
||||
static_assert
|
||||
(
|
||||
(count == 1),
|
||||
"Code does not (yet) work with aggregate types"
|
||||
);
|
||||
|
||||
Info<< "check_simple: " << name << ": " << count << nl;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
@ -389,6 +409,8 @@ int main()
|
||||
printPstreamTraits<const float>();
|
||||
printPstreamTraits<floatVector>();
|
||||
|
||||
check_simple<floatVector>("vector<float>");
|
||||
|
||||
printPstreamTraits<scalar>();
|
||||
printPstreamTraits<double>();
|
||||
printPstreamTraits<doubleVector>();
|
||||
|
||||
@ -49,8 +49,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
Info<< "mesh 0: " << mesh.sortedNames() << nl;
|
||||
|
||||
faMeshesRegistry& reg =
|
||||
const_cast<faMeshesRegistry&>(faMeshesRegistry::New(mesh));
|
||||
auto& reg = const_cast<faMeshesRegistry&>(faMeshesRegistry::New(mesh));
|
||||
|
||||
// faMeshesRegistry faReg = faMeshesRegistry(mesh);
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
foamToEnsight-check.C
|
||||
foamToEnsight-check.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/foamToEnsight-check
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2022-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -203,6 +203,7 @@ int main(int argc, char *argv[])
|
||||
argList::addVerboseOption();
|
||||
|
||||
#include "addAllRegionOptions.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
argList::addBoolOption
|
||||
(
|
||||
@ -251,6 +252,14 @@ int main(int argc, char *argv[])
|
||||
// Handle -allRegions, -regions, -region
|
||||
#include "getAllRegionOptions.H"
|
||||
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
areaRegionNames.clear(); // For consistency
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
#include "createNamedMeshes.H"
|
||||
@ -259,8 +268,8 @@ int main(int argc, char *argv[])
|
||||
/// #include "createMeshAccounting.H"
|
||||
|
||||
PtrList<ensightMesh> ensightMeshes(regionNames.size());
|
||||
PtrList<faMesh> meshesFa(regionNames.size());
|
||||
PtrList<ensightFaMesh> ensightMeshesFa(regionNames.size());
|
||||
List<PtrList<faMesh>> meshesFa(regionNames.size());
|
||||
List<PtrList<ensightFaMesh>> ensightMeshesFa(regionNames.size());
|
||||
|
||||
forAll(regionNames, regioni)
|
||||
{
|
||||
@ -273,21 +282,32 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
ensightMeshes[regioni].verbose(optVerbose);
|
||||
|
||||
|
||||
if (doFiniteArea)
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
autoPtr<faMesh> faMeshPtr(faMesh::TryNew(mesh));
|
||||
continue;
|
||||
}
|
||||
|
||||
meshesFa[regioni].resize_null(areaRegionNames.size());
|
||||
ensightMeshesFa[regioni].resize_null(areaRegionNames.size());
|
||||
|
||||
autoPtr<faMesh> faMeshPtr(faMesh::TryNew(mesh));
|
||||
|
||||
forAll(areaRegionNames, areai)
|
||||
{
|
||||
const word& areaName = areaRegionNames[areai];
|
||||
|
||||
autoPtr<faMesh> faMeshPtr(faMesh::TryNew(areaName, mesh));
|
||||
|
||||
if (faMeshPtr)
|
||||
{
|
||||
meshesFa.set(regioni, std::move(faMeshPtr));
|
||||
meshesFa[regioni].set(areai, std::move(faMeshPtr));
|
||||
|
||||
ensightMeshesFa.set
|
||||
ensightMeshesFa[regioni].set
|
||||
(
|
||||
regioni,
|
||||
new ensightFaMesh(meshesFa[regioni])
|
||||
areai,
|
||||
new ensightFaMesh(meshesFa[regioni][areai])
|
||||
);
|
||||
ensightMeshesFa[regioni].verbose(optVerbose);
|
||||
ensightMeshesFa[regioni][areai].verbose(optVerbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -295,7 +315,7 @@ int main(int argc, char *argv[])
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
if (Pstream::master())
|
||||
if (UPstream::master())
|
||||
{
|
||||
Info<< "Checking " << timeDirs.size() << " time steps" << nl;
|
||||
}
|
||||
@ -317,17 +337,20 @@ int main(int argc, char *argv[])
|
||||
auto& ensMesh = ensightMeshes[regioni];
|
||||
|
||||
// Finite-area (can be missing)
|
||||
auto* ensFaMeshPtr = ensightMeshesFa.get(regioni);
|
||||
auto& ensFaMeshes = ensightMeshesFa[regioni];
|
||||
|
||||
if (moving)
|
||||
{
|
||||
ensMesh.expire();
|
||||
ensMesh.correct();
|
||||
|
||||
if (ensFaMeshPtr)
|
||||
forAll(areaRegionNames, areai)
|
||||
{
|
||||
ensFaMeshPtr->expire();
|
||||
ensFaMeshPtr->correct();
|
||||
if (auto* ensFaMeshPtr = ensFaMeshes.get(areai))
|
||||
{
|
||||
ensFaMeshPtr->expire();
|
||||
ensFaMeshPtr->correct();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,9 +363,15 @@ int main(int argc, char *argv[])
|
||||
|
||||
printInfo(ensMesh, optVerbose);
|
||||
|
||||
if (ensFaMeshPtr)
|
||||
// finite-area
|
||||
forAll(areaRegionNames, areai)
|
||||
{
|
||||
printInfo(*ensFaMeshPtr, optVerbose);
|
||||
auto* ensFaMeshPtr = ensFaMeshes.get(areai);
|
||||
|
||||
if (ensFaMeshPtr)
|
||||
{
|
||||
printInfo(*ensFaMeshPtr, optVerbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -296,7 +296,7 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
strings,
|
||||
order,
|
||||
stringOps::natural_sort::less<string>(strings)
|
||||
stringOps::natural_sort::list_less(strings)
|
||||
);
|
||||
Info<< "natural sortedOrder: " << flatOutput(order) << endl;
|
||||
}
|
||||
@ -321,7 +321,7 @@ int main(int argc, char *argv[])
|
||||
/// sortable = hashed.toc();
|
||||
/// sortable.sort
|
||||
/// (
|
||||
/// stringOps::natural_sort::less<string>(sortable)
|
||||
/// stringOps::natural_sort::list_less(sortable)
|
||||
/// );
|
||||
/// Info<< nl << "natural:" << sortable << endl;
|
||||
|
||||
@ -329,7 +329,7 @@ int main(int argc, char *argv[])
|
||||
/// sortable = hashed.toc();
|
||||
/// sortable.sort
|
||||
/// (
|
||||
/// stringOps::natural_sort::greater<string>(sortable)
|
||||
/// stringOps::natural_sort::list_greater(sortable)
|
||||
/// );
|
||||
/// Info<< nl << "natural:" << sortable << endl;
|
||||
}
|
||||
|
||||
@ -59,11 +59,6 @@ int main(int argc, char *argv[])
|
||||
<< " type: " << typeid(cstr).name() << " len:" << len << nl;
|
||||
|
||||
Info<< " view: " << std::string_view(cstr) << nl;
|
||||
|
||||
Info<< " span: "
|
||||
<< stdFoam::span<const char>(cstr, len) << nl;
|
||||
Info<< " span: "
|
||||
<< stdFoam::span<char>(const_cast<char*>(cstr), len) << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
mydebugSurfaceWriter.C
|
||||
Test-surface-sampling.C
|
||||
mydebugSurfaceWriter.cxx
|
||||
Test-surface-sampling.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-surface-sampling
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2022-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -83,12 +83,10 @@ template<> struct narrowType<SymmTensor<double>>
|
||||
typedef SymmTensor<float> type;
|
||||
};
|
||||
|
||||
// FIXME: Not sure why this one seems to be broken...
|
||||
//
|
||||
// template<> struct narrowType<Tensor<double>>
|
||||
// {
|
||||
// typedef Tensor<float> type;
|
||||
// };
|
||||
template<> struct narrowType<Tensor<double>>
|
||||
{
|
||||
typedef Tensor<float> type;
|
||||
};
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -104,12 +102,18 @@ Foam::surfaceWriters::mydebugWriter::mergeField
|
||||
{
|
||||
addProfiling(merge, "debugWriter::merge-field");
|
||||
|
||||
// This is largely identical to surfaceWriter::mergeField()
|
||||
// Identical to surfaceWriter::mergeField()
|
||||
// but with narrowing for communication
|
||||
if (narrowTransfer_ && parallel_ && UPstream::parRun())
|
||||
|
||||
if constexpr (std::is_same_v<Tensor<double>, Type>)
|
||||
{
|
||||
// Cannot narrow tensor. Does not compile since MatrixSpace
|
||||
// does not (yet) allow assigments from different Cmpt types.
|
||||
}
|
||||
else if (narrowTransfer_ && parallel_ && UPstream::parRun())
|
||||
{
|
||||
// The narrowed type
|
||||
typedef typename narrowType<Type>::type narrowedType;
|
||||
using narrowedType = typename narrowType<Type>::type;
|
||||
|
||||
// Ensure geometry is also merged
|
||||
merge();
|
||||
@ -130,14 +134,29 @@ Foam::surfaceWriters::mydebugWriter::mergeField
|
||||
ConstPrecisionAdaptor<narrowedType, Type> input(fld);
|
||||
PrecisionAdaptor<narrowedType, Type> output(allFld);
|
||||
|
||||
globIndex.gather
|
||||
(
|
||||
input.cref(), // fld,
|
||||
output.ref(), // allFld,
|
||||
UPstream::msgType(),
|
||||
commType_,
|
||||
UPstream::worldComm
|
||||
);
|
||||
if (gatherv_)
|
||||
{
|
||||
globIndex.mpiGather
|
||||
(
|
||||
input.cref(), // fld
|
||||
output.ref(), // allFld
|
||||
UPstream::worldComm,
|
||||
// For fallback:
|
||||
commType_,
|
||||
UPstream::msgType()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
globIndex.gather
|
||||
(
|
||||
input.cref(), // fld
|
||||
output.ref(), // allFld
|
||||
UPstream::msgType(),
|
||||
commType_,
|
||||
UPstream::worldComm
|
||||
);
|
||||
}
|
||||
|
||||
// Commit adapted content changes
|
||||
input.commit();
|
||||
@ -193,8 +212,19 @@ Foam::surfaceWriters::mydebugWriter::mydebugWriter
|
||||
{
|
||||
Info<< "Using debug surface writer ("
|
||||
<< (this->isPointData() ? "point" : "face") << " data):"
|
||||
<< " commsType=" << UPstream::commsTypeNames[commType_]
|
||||
<< " merge=" << Switch::name(enableMerge_)
|
||||
<< " commsType=";
|
||||
|
||||
if (UPstream::parRun())
|
||||
{
|
||||
if (gatherv_) Info<< "gatherv+";
|
||||
Info<< UPstream::commsTypeNames[commType_];
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "serial";
|
||||
}
|
||||
|
||||
Info<< " merge=" << Switch::name(enableMerge_)
|
||||
<< " write=" << Switch::name(enableWrite_)
|
||||
<< " narrow=" << Switch::name(narrowTransfer_)
|
||||
<< endl;
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2017 Wikki Ltd
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,7 +28,7 @@ Application
|
||||
makeFaMesh
|
||||
|
||||
Description
|
||||
Check a finiteArea mesh
|
||||
Check a finite-area mesh
|
||||
|
||||
Original Authors
|
||||
Zeljko Tukovic, FAMENA
|
||||
@ -39,6 +39,7 @@ Original Authors
|
||||
#include "Time.H"
|
||||
#include "argList.H"
|
||||
#include "faMesh.H"
|
||||
#include "faMeshTools.H"
|
||||
#include "polyMesh.H"
|
||||
#include "areaFaMesh.H"
|
||||
#include "edgeFaMesh.H"
|
||||
@ -47,7 +48,7 @@ Original Authors
|
||||
#include "processorFaPatch.H"
|
||||
#include "foamVtkIndPatchWriter.H"
|
||||
#include "foamVtkLineWriter.H"
|
||||
#include "faMeshTools.H"
|
||||
#include "regionProperties.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -59,7 +60,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
argList::addNote
|
||||
(
|
||||
"Check a finiteArea mesh"
|
||||
"Check a finite-area mesh"
|
||||
);
|
||||
|
||||
argList::addBoolOption
|
||||
@ -77,9 +78,15 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
#include "addRegionOption.H"
|
||||
#include "addFaRegionOption.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
#include "createNamedPolyMesh.H"
|
||||
|
||||
int geometryOrder(1);
|
||||
@ -91,16 +98,41 @@ int main(int argc, char *argv[])
|
||||
faMesh::geometryOrder(geometryOrder);
|
||||
}
|
||||
|
||||
#include "createNamedFaMesh.H"
|
||||
|
||||
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||
|
||||
// Mesh information (verbose)
|
||||
faMeshTools::printMeshChecks(aMesh);
|
||||
|
||||
if (args.found("write-vtk"))
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
#include "faMeshWriteVTK.H"
|
||||
Info<< "Create faMesh";
|
||||
if (!polyMesh::regionName(areaName).empty())
|
||||
{
|
||||
Info<< " [" << areaName << "]";
|
||||
}
|
||||
Info<< " for time = " << runTime.timeName() << nl;
|
||||
|
||||
autoPtr<faMesh> faMeshPtr(faMesh::TryNew(areaName, mesh));
|
||||
|
||||
if (!faMeshPtr)
|
||||
{
|
||||
Info<< " ...failed to create area-mesh";
|
||||
if (!polyMesh::regionName(areaName).empty())
|
||||
{
|
||||
Info<< " [" << areaName << "]";
|
||||
}
|
||||
Info<< endl;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
const auto& aMesh = faMeshPtr();
|
||||
|
||||
// Mesh information (verbose)
|
||||
faMeshTools::printMeshChecks(aMesh);
|
||||
|
||||
if (args.found("write-vtk"))
|
||||
{
|
||||
#include "faMeshWriteVTK.H"
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "\nEnd\n" << endl;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
@ -15,6 +15,16 @@ Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// The base name for output files
|
||||
word vtkBaseFileName(aMesh.regionName());
|
||||
if (polyMesh::regionName(vtkBaseFileName).empty())
|
||||
{
|
||||
vtkBaseFileName = "finiteArea";
|
||||
}
|
||||
|
||||
Info<< nl;
|
||||
Info<< "Write faMesh in vtk format:" << nl;
|
||||
|
||||
{
|
||||
// finiteArea - faces
|
||||
vtk::uindirectPatchWriter writer
|
||||
@ -23,7 +33,7 @@ Description
|
||||
// vtk::formatType::INLINE_ASCII,
|
||||
fileName
|
||||
(
|
||||
aMesh.time().globalPath() / "finiteArea"
|
||||
aMesh.time().globalPath() / vtkBaseFileName
|
||||
)
|
||||
);
|
||||
|
||||
@ -32,7 +42,7 @@ Description
|
||||
globalIndex procAddr(aMesh.nFaces());
|
||||
labelList cellIDs;
|
||||
|
||||
if (Pstream::master())
|
||||
if (UPstream::master())
|
||||
{
|
||||
cellIDs.resize(procAddr.totalSize());
|
||||
for (const labelRange& range : procAddr.ranges())
|
||||
@ -53,8 +63,7 @@ Description
|
||||
writer.beginPointData(1);
|
||||
writer.write("normal", aMesh.pointAreaNormals());
|
||||
|
||||
Info<< nl
|
||||
<< "Wrote faMesh in vtk format: " << writer.output().name() << nl;
|
||||
Info<< " " << writer.output().name() << nl;
|
||||
}
|
||||
|
||||
{
|
||||
@ -66,7 +75,7 @@ Description
|
||||
// vtk::formatType::INLINE_ASCII,
|
||||
fileName
|
||||
(
|
||||
aMesh.time().globalPath() / "finiteArea-edges"
|
||||
aMesh.time().globalPath() / (vtkBaseFileName + "-edges")
|
||||
)
|
||||
);
|
||||
|
||||
@ -88,8 +97,7 @@ Description
|
||||
writer.beginPointData(1);
|
||||
writer.write("normal", aMesh.pointAreaNormals());
|
||||
|
||||
Info<< nl
|
||||
<< "Wrote faMesh in vtk format: " << writer.output().name() << nl;
|
||||
Info<< " " << writer.output().name() << nl;
|
||||
}
|
||||
|
||||
{
|
||||
@ -108,7 +116,7 @@ Description
|
||||
// vtk::formatType::INLINE_ASCII,
|
||||
fileName
|
||||
(
|
||||
aMesh.time().globalPath() / "finiteArea-edgesCentres"
|
||||
aMesh.time().globalPath() / (vtkBaseFileName + "-edgesCentres")
|
||||
)
|
||||
);
|
||||
|
||||
@ -134,8 +142,7 @@ Description
|
||||
writer.write("normal", fld);
|
||||
}
|
||||
|
||||
Info<< nl
|
||||
<< "Wrote faMesh in vtk format: " << writer.output().name() << nl;
|
||||
Info<< " " << writer.output().name() << nl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 OpenCFD Ltd.
|
||||
Copyright (C) 2023-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
@ -15,7 +15,7 @@ Description
|
||||
|
||||
Input
|
||||
mesh (polyMesh)
|
||||
meshDefDict (system/faMeshDefintion)
|
||||
meshDefDict (system/finite-area/faMeshDefinition)
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -25,13 +25,16 @@ Input
|
||||
|
||||
const polyBoundaryMesh& pbm = mesh.boundaryMesh();
|
||||
|
||||
wordRes polyPatchNames;
|
||||
meshDefDict.readIfPresent("polyMeshPatches", polyPatchNames);
|
||||
labelList patchIDs;
|
||||
|
||||
const labelList patchIDs
|
||||
if
|
||||
(
|
||||
pbm.indices(polyPatchNames, true) // useGroups
|
||||
);
|
||||
wordRes select;
|
||||
meshDefDict.readIfPresent("polyMeshPatches", select)
|
||||
)
|
||||
{
|
||||
patchIDs = pbm.indices(select, true); // useGroups
|
||||
}
|
||||
|
||||
label nFaceLabels = 0;
|
||||
for (const label patchi : patchIDs)
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
@ -13,6 +13,18 @@ License
|
||||
Description
|
||||
Search for the appropriate faMeshDefinition dictionary...
|
||||
|
||||
Expects to find a faMeshDefinition file in a location specified
|
||||
by the command-line option, or one of the standard locations.
|
||||
|
||||
For default area region (region0):
|
||||
(1) system/finite-area/faMeshDefinition
|
||||
(2) system/faMeshDefinition [legacy location - v2312 and earlier]
|
||||
|
||||
For a named area region:
|
||||
(1) system/finite-area/<area-name>/faMeshDefinition
|
||||
(2) system/finite-area/faMeshDefinition.<area-name>
|
||||
[symmetric with faOptions]
|
||||
|
||||
Required Classes
|
||||
- Foam::polyMesh
|
||||
- Foam::IOdictionary
|
||||
@ -24,81 +36,185 @@ Required Variables
|
||||
- runTime [Time]
|
||||
|
||||
Provided Variables
|
||||
- meshDefDict [IOdictionary]
|
||||
- meshDictPtr [autoPtr<IOdictionary>]
|
||||
- faMeshDefinitionPtr [autoPtr<IOdictionary>]
|
||||
|
||||
If the dictionary cannot be found, exits with an error message or
|
||||
reports a warning (dry-run mode)
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
const word dictName("faMeshDefinition");
|
||||
|
||||
autoPtr<IOdictionary> meshDictPtr;
|
||||
autoPtr<IOdictionary> faMeshDefinitionPtr;
|
||||
|
||||
{
|
||||
fileName dictPath;
|
||||
const word& regionDir = Foam::polyMesh::regionName(regionName);
|
||||
const word& areaRegionDir = Foam::polyMesh::regionName(areaRegionName);
|
||||
// Exit unless dry-run?
|
||||
const bool exitOnFailure = (!args.dryRun());
|
||||
|
||||
if (args.readIfPresent("dict", dictPath))
|
||||
const word& regionDir = polyMesh::regionName(regionName);
|
||||
const word& areaRegionDir = polyMesh::regionName(areaRegionName);
|
||||
|
||||
// Canonical location
|
||||
fileName dictPath
|
||||
(
|
||||
runTime.system()/regionDir
|
||||
/ faMesh::prefix()/areaRegionDir/dictName
|
||||
);
|
||||
|
||||
|
||||
// Dictionary specified on the command-line ...
|
||||
const bool specified = args.readIfPresent("dict", dictPath);
|
||||
|
||||
if (specified)
|
||||
{
|
||||
// Dictionary specified on the command-line ...
|
||||
|
||||
if (isDir(dictPath))
|
||||
{
|
||||
dictPath /= dictName;
|
||||
}
|
||||
}
|
||||
else if
|
||||
(
|
||||
// Dictionary under system/faMeshDefinition ?
|
||||
// (v2312 and earlier)
|
||||
|
||||
areaRegionDir.empty()
|
||||
&& exists
|
||||
(
|
||||
runTime.path()/runTime.caseSystem()
|
||||
/ regionDir/faMesh::meshSubDir/dictName
|
||||
)
|
||||
)
|
||||
{
|
||||
// Dictionary present directly in system/ (v2312 and earlier)
|
||||
|
||||
dictPath = runTime.system()/regionDir/dictName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use system/finite-area/ directory, with region qualifications
|
||||
|
||||
dictPath =
|
||||
(
|
||||
runTime.system()/regionDir
|
||||
/ faMesh::prefix()/areaRegionDir/dictName
|
||||
);
|
||||
}
|
||||
|
||||
IOobject meshDictIO
|
||||
(
|
||||
dictPath,
|
||||
runTime,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER,
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER,
|
||||
true // is globalObject
|
||||
);
|
||||
|
||||
if (!meshDictIO.typeHeaderOk<IOdictionary>(true))
|
||||
refPtr<IOobject> meshDictIOPtr;
|
||||
|
||||
bool foundIOobject = meshDictIO.typeHeaderOk<IOdictionary>(true);
|
||||
|
||||
// For reporting any alternative locations
|
||||
dictPath.clear();
|
||||
|
||||
if (!foundIOobject && !specified)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< meshDictIO.objectPath() << nl
|
||||
<< exit(FatalError);
|
||||
if (!areaRegionDir.empty())
|
||||
{
|
||||
// Alternative location
|
||||
// - system/finite-area/faMeshDefinition.<area-name>
|
||||
|
||||
dictPath =
|
||||
(
|
||||
runTime.system()/regionDir
|
||||
/ faMesh::prefix()/IOobject::groupName(dictName, areaRegionDir)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// legacy location (v2312 and earlier)
|
||||
// - system/faMeshDefinition
|
||||
|
||||
dictPath = runTime.system()/regionDir/dictName;
|
||||
}
|
||||
|
||||
if (!dictPath.empty())
|
||||
{
|
||||
auto ioptr = autoPtr<IOobject>::New
|
||||
(
|
||||
dictPath,
|
||||
runTime,
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER,
|
||||
true // is globalObject
|
||||
);
|
||||
|
||||
foundIOobject =
|
||||
(
|
||||
ioptr && ioptr->typeHeaderOk<IOdictionary>(true)
|
||||
);
|
||||
|
||||
if (foundIOobject)
|
||||
{
|
||||
// Use if found
|
||||
meshDictIOPtr = std::move(ioptr);
|
||||
}
|
||||
|
||||
// Generally retain dictPath for error messages,
|
||||
// but don't mention the really old legacy location
|
||||
if (areaRegionDir.empty())
|
||||
{
|
||||
dictPath.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Creating faMesh from definition: "
|
||||
<< meshDictIO.objectRelPath() << endl;
|
||||
// Alternative location or regular location?
|
||||
if (!meshDictIOPtr)
|
||||
{
|
||||
meshDictIOPtr.cref(meshDictIO);
|
||||
}
|
||||
const auto& io = meshDictIOPtr();
|
||||
|
||||
meshDictPtr = autoPtr<IOdictionary>::New(meshDictIO);
|
||||
|
||||
// Handle final success or failure
|
||||
if (foundIOobject)
|
||||
{
|
||||
Info<< "----------------" << nl
|
||||
<< "Using area-mesh definition";
|
||||
if (!areaRegionDir.empty())
|
||||
{
|
||||
Info<< " [" << areaRegionName << "]";
|
||||
}
|
||||
|
||||
Info<< nl
|
||||
<< " " << io.objectRelPath() << nl << endl;
|
||||
|
||||
faMeshDefinitionPtr = autoPtr<IOdictionary>::New(io);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failure
|
||||
|
||||
if (exitOnFailure)
|
||||
{
|
||||
auto& err =
|
||||
FatalErrorInFunction
|
||||
<< "Did not find area-mesh definition";
|
||||
|
||||
if (!areaRegionDir.empty())
|
||||
{
|
||||
err<< " [" << areaRegionName << "]";
|
||||
}
|
||||
|
||||
err << nl
|
||||
<< " " << io.objectRelPath() << nl;
|
||||
|
||||
if (!dictPath.empty())
|
||||
{
|
||||
err << " " << dictPath << nl;
|
||||
}
|
||||
|
||||
FatalError<< exit(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
// dry-run: warning
|
||||
auto& err =
|
||||
Warning << nl
|
||||
<< "----------------" << nl
|
||||
<< "Did not find area-mesh definition";
|
||||
|
||||
if (!areaRegionDir.empty())
|
||||
{
|
||||
err << " [" << areaRegionName << "]";
|
||||
}
|
||||
|
||||
err << nl
|
||||
<< " " << io.objectRelPath() << nl;
|
||||
|
||||
if (!dictPath.empty())
|
||||
{
|
||||
err << " " << dictPath << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IOdictionary& meshDefDict = *meshDictPtr;
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2017 Wikki Ltd
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -40,7 +40,6 @@ Original Authors
|
||||
|
||||
#include "Time.H"
|
||||
#include "argList.H"
|
||||
#include "OSspecific.H"
|
||||
#include "faMesh.H"
|
||||
#include "faMeshTools.H"
|
||||
#include "IOdictionary.H"
|
||||
@ -53,6 +52,7 @@ Original Authors
|
||||
#include "PtrListOps.H"
|
||||
#include "foamVtkLineWriter.H"
|
||||
#include "foamVtkIndPatchWriter.H"
|
||||
#include "regionProperties.H"
|
||||
#include "syncTools.H"
|
||||
#include "OBJstream.H"
|
||||
|
||||
@ -104,12 +104,14 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
#include "addRegionOption.H"
|
||||
#include "addFaRegionOption.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
#include "createNamedPolyMesh.H"
|
||||
|
||||
#include "getFaRegionOption.H"
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
const bool doDecompose = !args.found("no-decompose");
|
||||
const bool doDecompFields = !args.found("no-fields");
|
||||
@ -123,56 +125,83 @@ int main(int argc, char *argv[])
|
||||
Info<< "Skip decompose of finiteArea fields" << nl;
|
||||
}
|
||||
|
||||
// Reading faMeshDefinition dictionary
|
||||
#include "findMeshDefinitionDict.H"
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Inject/overwrite name for optional 'empty' patch
|
||||
word patchName;
|
||||
if (args.readIfPresent("empty-patch", patchName))
|
||||
for (const word& areaRegionName : areaRegionNames)
|
||||
{
|
||||
meshDefDict.add("emptyPatch", patchName, true);
|
||||
}
|
||||
// Reading faMeshDefinition dictionary
|
||||
#include "findMeshDefinitionDict.H"
|
||||
|
||||
// Preliminary checks
|
||||
#include "checkPatchTopology.H"
|
||||
if (!faMeshDefinitionPtr)
|
||||
{
|
||||
if (args.dryRun())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Did not find area-mesh definition"<< nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
Info << "Create areaMesh";
|
||||
if (!Foam::polyMesh::regionName(areaRegionName).empty())
|
||||
{
|
||||
Foam::Info << ' ' << areaRegionName;
|
||||
}
|
||||
Info << " for polyMesh at time = " << runTime.timeName() << nl;
|
||||
auto& meshDefDict = (*faMeshDefinitionPtr);
|
||||
|
||||
// Create
|
||||
faMesh aMesh(areaRegionName, mesh, meshDefDict);
|
||||
|
||||
// Mesh information (less verbose)
|
||||
faMeshTools::printMeshChecks(aMesh, 0);
|
||||
// Inject/overwrite name for optional 'empty' patch
|
||||
if (word name; args.readIfPresent("empty-patch", name))
|
||||
{
|
||||
meshDefDict.add("emptyPatch", name, true);
|
||||
}
|
||||
|
||||
if (args.found("write-edges-obj"))
|
||||
{
|
||||
#include "faMeshWriteEdgesOBJ.H"
|
||||
}
|
||||
// Preliminary checks
|
||||
#include "checkPatchTopology.H"
|
||||
|
||||
if (args.found("write-vtk"))
|
||||
{
|
||||
#include "faMeshWriteVTK.H"
|
||||
}
|
||||
Info<< "Create area-mesh";
|
||||
if (!polyMesh::regionName(areaRegionName).empty())
|
||||
{
|
||||
Info<< " [" << areaRegionName << "]";
|
||||
}
|
||||
Info<< " with polyMesh at time = " << runTime.timeName() << nl;
|
||||
|
||||
if (args.dryRun())
|
||||
{
|
||||
Info<< "\ndry-run: not writing mesh or decomposing fields\n" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// More precision (for points data)
|
||||
IOstream::minPrecision(10);
|
||||
// Create
|
||||
faMesh aMesh(areaRegionName, mesh, meshDefDict);
|
||||
|
||||
Info<< nl << "Write finite area mesh." << nl;
|
||||
aMesh.write();
|
||||
// Mesh information (less verbose)
|
||||
faMeshTools::printMeshChecks(aMesh, 0);
|
||||
|
||||
Info<< endl;
|
||||
#include "decomposeFaFields.H"
|
||||
if (args.found("write-edges-obj"))
|
||||
{
|
||||
#include "faMeshWriteEdgesOBJ.H"
|
||||
}
|
||||
|
||||
if (args.found("write-vtk"))
|
||||
{
|
||||
#include "faMeshWriteVTK.H"
|
||||
}
|
||||
|
||||
if (args.dryRun())
|
||||
{
|
||||
Info<< "\ndry-run: not writing mesh or decomposing fields\n" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// More precision (for points data)
|
||||
IOstream::minPrecision(10);
|
||||
|
||||
Info<< nl << "Write finite area mesh";
|
||||
if (const word& name = aMesh.regionName(); !name.empty())
|
||||
{
|
||||
Info<< " [" << name << "]";
|
||||
}
|
||||
Info<< nl;
|
||||
|
||||
aMesh.write();
|
||||
|
||||
Info<< endl;
|
||||
#include "decomposeFaFields.H"
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "\nEnd\n" << endl;
|
||||
|
||||
@ -30,7 +30,8 @@ Group
|
||||
grpPostProcessingUtilities
|
||||
|
||||
Description
|
||||
List regions from constant/regionProperties.
|
||||
List volume regions from constant/regionProperties
|
||||
or area regions from constant/finite-area/regionProperties
|
||||
|
||||
Usage
|
||||
\b foamListRegions [OPTION]
|
||||
@ -72,6 +73,12 @@ int main(int argc, char *argv[])
|
||||
"List constant/finite-area/regionProperties (if available)"
|
||||
);
|
||||
|
||||
argList::addBoolOption
|
||||
(
|
||||
"optional",
|
||||
"A missing regionProperties is not treated as an error"
|
||||
);
|
||||
|
||||
argList::addDryRunOption
|
||||
(
|
||||
"Make reading optional and add verbosity"
|
||||
@ -92,14 +99,20 @@ int main(int argc, char *argv[])
|
||||
++optVerbose;
|
||||
}
|
||||
|
||||
// File is optional, not an error
|
||||
const bool isOptional = args.found("optional");
|
||||
|
||||
// Use finite-area regions
|
||||
const bool doFiniteArea = args.found("finite-area");
|
||||
|
||||
// The number of optional region filters to apply
|
||||
const label nFilters = (args.size()-1);
|
||||
|
||||
IOobjectOption::readOption readOpt(IOobjectOption::MUST_READ);
|
||||
|
||||
if (dryRun || doFiniteArea)
|
||||
if (dryRun || isOptional || doFiniteArea)
|
||||
{
|
||||
// Always treat finite-area regionProperties as optional
|
||||
// The finite-area regionProperties are also considered optional
|
||||
readOpt = IOobjectOption::READ_IF_PRESENT;
|
||||
}
|
||||
|
||||
@ -116,58 +129,70 @@ int main(int argc, char *argv[])
|
||||
if (doFiniteArea)
|
||||
{
|
||||
regionProps = regionProperties(runTime, faMeshPrefix, readOpt);
|
||||
|
||||
if (regionProps.empty())
|
||||
{
|
||||
InfoErr<< "No finite-area region types" << nl;
|
||||
}
|
||||
else if (optVerbose)
|
||||
{
|
||||
InfoErr
|
||||
<< "Have " << regionProps.size()
|
||||
<< " finite-area region types, "
|
||||
<< regionProps.count() << " regions" << nl << nl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regionProps = regionProperties(runTime, readOpt);
|
||||
|
||||
if (regionProps.empty())
|
||||
{
|
||||
// Probably only occurs with -dry-run option
|
||||
InfoErr<< "No region types" << nl;
|
||||
}
|
||||
else if (optVerbose)
|
||||
{
|
||||
InfoErr
|
||||
<< "Have " << regionProps.size() << " region types, "
|
||||
<< regionProps.count() << " regions" << nl << nl;
|
||||
}
|
||||
}
|
||||
|
||||
// We now handle checking args and general sanity etc.
|
||||
wordList regionTypes;
|
||||
|
||||
if (args.size() > 1)
|
||||
// Some reporting...
|
||||
if (regionProps.empty())
|
||||
{
|
||||
regionTypes.resize(args.size()-1);
|
||||
if (doFiniteArea)
|
||||
{
|
||||
InfoErr<< "No finite-area region types" << nl;
|
||||
}
|
||||
else if (isOptional)
|
||||
{
|
||||
InfoErr<< "No region types" << nl;
|
||||
}
|
||||
}
|
||||
else if (optVerbose)
|
||||
{
|
||||
InfoErr << "Have " << regionProps.size();
|
||||
|
||||
// No duplicates
|
||||
if (doFiniteArea)
|
||||
{
|
||||
InfoErr<< " finite-area";
|
||||
}
|
||||
InfoErr
|
||||
<< " region types, "
|
||||
<< regionProps.count() << " regions" << nl << nl;
|
||||
}
|
||||
|
||||
|
||||
// We now handle checking args and general sanity etc.
|
||||
|
||||
DynamicList<word> regionTypes;
|
||||
|
||||
if (isOptional && regionProps.empty())
|
||||
{
|
||||
// Nothing to do...
|
||||
}
|
||||
else if (nFilters > 0)
|
||||
{
|
||||
// Apply region filters
|
||||
|
||||
regionTypes.reserve_exact
|
||||
(
|
||||
Foam::min(nFilters, regionProps.size())
|
||||
);
|
||||
|
||||
// No duplicates, and no duplicate warnings
|
||||
wordHashSet uniq;
|
||||
|
||||
label nTypes = 0;
|
||||
for (label argi = 1; argi < args.size(); ++argi)
|
||||
{
|
||||
regionTypes[nTypes] = args[argi];
|
||||
|
||||
const word& regType = regionTypes[nTypes];
|
||||
word regType(args[argi]);
|
||||
|
||||
if (uniq.insert(regType))
|
||||
{
|
||||
if (regionProps.contains(regType))
|
||||
{
|
||||
++nTypes;
|
||||
if (!regionTypes.contains(regType))
|
||||
{
|
||||
regionTypes.push_back(std::move(regType));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -175,22 +200,22 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
regionTypes.resize(nTypes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take all regions
|
||||
regionTypes = regionProps.sortedToc();
|
||||
}
|
||||
|
||||
|
||||
for (const word& regionType : regionTypes)
|
||||
{
|
||||
const wordList& regionNames = regionProps[regionType];
|
||||
|
||||
for (const word& regionName : regionNames)
|
||||
if (const auto iter = regionProps.cfind(regionType); iter.good())
|
||||
{
|
||||
Info<< regionName << nl;
|
||||
for (const word& regionName : iter.val())
|
||||
{
|
||||
Info<< regionName << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -334,6 +334,7 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
#include "addAllRegionOptions.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
argList::addDryRunOption
|
||||
(
|
||||
@ -418,8 +419,14 @@ int main(int argc, char *argv[])
|
||||
// Allow explicit -constant, have zero from time range
|
||||
timeSelector::addOptions(true, false); // constant(true), zero(false)
|
||||
|
||||
// Prevent volume BCs from triggering finite-area
|
||||
regionModels::allowFaModels(false);
|
||||
|
||||
#include "setRootCase.H"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Configuration
|
||||
|
||||
const bool writeCellDist = args.found("cellDist");
|
||||
|
||||
// Most of these are ignored for dry-run (not triggered anywhere)
|
||||
@ -436,7 +443,6 @@ int main(int argc, char *argv[])
|
||||
bool decomposeFieldsOnly = args.found("fields");
|
||||
bool forceOverwrite = args.found("force");
|
||||
|
||||
|
||||
// Set time from database
|
||||
#include "createTime.H"
|
||||
|
||||
@ -485,9 +491,17 @@ int main(int argc, char *argv[])
|
||||
decompDictFile = runTime.globalPath()/decompDictFile;
|
||||
}
|
||||
|
||||
// Get region names
|
||||
// Handle -allRegions, -regions, -region
|
||||
#include "getAllRegionOptions.H"
|
||||
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
areaRegionNames.clear(); // For consistency
|
||||
}
|
||||
|
||||
const bool optRegions =
|
||||
(regionNames.size() != 1 || regionNames[0] != polyMesh::defaultRegion);
|
||||
|
||||
@ -807,56 +821,76 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Field objects at this time
|
||||
IOobjectList objects;
|
||||
IOobjectList faObjects;
|
||||
|
||||
// faMesh fields - can have multiple finite-area per volume
|
||||
HashTable<IOobjectList> faObjects;
|
||||
|
||||
if (doDecompFields)
|
||||
{
|
||||
// List of volume mesh objects for this instance
|
||||
objects = IOobjectList(mesh, runTime.timeName());
|
||||
|
||||
// List of area mesh objects (assuming single region)
|
||||
faObjects = IOobjectList
|
||||
(
|
||||
mesh.time(),
|
||||
runTime.timeName(),
|
||||
faMesh::dbDir(mesh, word::null),
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
// Ignore generated fields: (cellDist)
|
||||
objects.remove("cellDist");
|
||||
|
||||
// Lists of finite-area fields
|
||||
faObjects.reserve(areaRegionNames.size());
|
||||
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
// The finite-area objects for this area region
|
||||
IOobjectList objs
|
||||
(
|
||||
faMesh::Registry(mesh),
|
||||
runTime.timeName(),
|
||||
polyMesh::regionName(areaName),
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
if (!objs.empty())
|
||||
{
|
||||
faObjects.emplace_set(areaName, std::move(objs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finite area handling
|
||||
autoPtr<faMeshDecomposition> faMeshDecompPtr;
|
||||
// - all area regions use the same volume decomposition
|
||||
|
||||
HashPtrTable<faMeshDecomposition> faMeshDecompHashes;
|
||||
if (doFiniteArea)
|
||||
{
|
||||
const word boundaryInst =
|
||||
mesh.time().findInstance(mesh.meshDir(), "boundary");
|
||||
|
||||
IOobject io
|
||||
(
|
||||
"faBoundary",
|
||||
boundaryInst,
|
||||
faMesh::meshDir(mesh, word::null),
|
||||
mesh.time(),
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
);
|
||||
|
||||
if (io.typeHeaderOk<faBoundaryMesh>(true))
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
// Always based on the volume decomposition!
|
||||
faMeshDecompPtr.reset
|
||||
IOobject io
|
||||
(
|
||||
new faMeshDecomposition
|
||||
(
|
||||
mesh,
|
||||
mesh.nProcs(),
|
||||
mesh.model()
|
||||
)
|
||||
"faBoundary",
|
||||
boundaryInst,
|
||||
faMesh::meshDir(mesh, areaName),
|
||||
mesh.time(),
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
);
|
||||
|
||||
if (io.typeHeaderOk<faBoundaryMesh>(true))
|
||||
{
|
||||
// Always based on the volume decomposition!
|
||||
faMeshDecompHashes.set
|
||||
(
|
||||
areaName,
|
||||
autoPtr<faMeshDecomposition>::New
|
||||
(
|
||||
areaName,
|
||||
mesh,
|
||||
mesh.nProcs(),
|
||||
mesh.model()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1060,7 +1094,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
processorDb.setTime(runTime);
|
||||
|
||||
// read the mesh
|
||||
// Read the mesh
|
||||
if (!procMeshList.set(proci))
|
||||
{
|
||||
procMeshList.set
|
||||
@ -1267,12 +1301,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
// Finite area mesh and field decomposition
|
||||
if (faMeshDecompPtr)
|
||||
// Finite-area mesh and field decomposition
|
||||
for (auto& iter : faMeshDecompHashes.sorted())
|
||||
{
|
||||
Info<< "\nFinite area mesh decomposition" << endl;
|
||||
const word& areaName = iter.key();
|
||||
|
||||
faMeshDecomposition& aMesh = faMeshDecompPtr();
|
||||
faMeshDecomposition& aMesh = *(iter.val());
|
||||
|
||||
Info<< "\nFinite area mesh decomposition: "
|
||||
<< areaName << endl;
|
||||
|
||||
aMesh.decomposeMesh();
|
||||
aMesh.writeDecomposition();
|
||||
@ -1283,9 +1320,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
faFieldDecomposer::fieldsCache areaFieldCache;
|
||||
|
||||
if (doDecompFields)
|
||||
if
|
||||
(
|
||||
const auto objs = faObjects.cfind(areaName);
|
||||
doDecompFields && objs.good()
|
||||
)
|
||||
{
|
||||
areaFieldCache.readAllFields(aMesh, faObjects);
|
||||
areaFieldCache.readAllFields(aMesh, objs.val());
|
||||
}
|
||||
|
||||
const label nAreaFields = areaFieldCache.size();
|
||||
@ -1316,7 +1357,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
processorDb.setTime(runTime);
|
||||
|
||||
// Read the mesh
|
||||
// Read the volume mesh
|
||||
fvMesh procFvMesh
|
||||
(
|
||||
IOobject
|
||||
@ -1327,7 +1368,7 @@ int main(int argc, char *argv[])
|
||||
)
|
||||
);
|
||||
|
||||
faMesh procMesh(procFvMesh);
|
||||
faMesh procMesh(areaName, procFvMesh);
|
||||
|
||||
// // Does not work. HJ, 15/Aug/2017
|
||||
// const labelIOList& faceProcAddressing =
|
||||
@ -1386,7 +1427,11 @@ int main(int argc, char *argv[])
|
||||
boundaryProcAddressing
|
||||
);
|
||||
|
||||
areaFieldCache.decomposeAllFields(fieldDecomposer);
|
||||
areaFieldCache.decomposeAllFields
|
||||
(
|
||||
fieldDecomposer,
|
||||
args.verbose() // report
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -91,6 +91,7 @@ int main(int argc, char *argv[])
|
||||
argList::noParallel();
|
||||
|
||||
#include "addAllRegionOptions.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
argList::addVerboseOption();
|
||||
argList::addOption
|
||||
@ -135,9 +136,14 @@ int main(int argc, char *argv[])
|
||||
"Only reconstruct new times (i.e. that do not exist already)"
|
||||
);
|
||||
|
||||
// Prevent volume BCs from triggering finite-area
|
||||
regionModels::allowFaModels(false);
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Configuration
|
||||
|
||||
const bool doFields = !args.found("no-fields");
|
||||
wordRes selectedFields;
|
||||
@ -196,9 +202,17 @@ int main(int argc, char *argv[])
|
||||
|
||||
const bool newTimes = args.found("newTimes");
|
||||
|
||||
// Get region names
|
||||
// Handle -allRegions, -regions, -region
|
||||
#include "getAllRegionOptions.H"
|
||||
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
areaRegionNames.clear(); // For consistency
|
||||
}
|
||||
|
||||
// Determine the processor count
|
||||
label nProcs{0};
|
||||
|
||||
@ -386,19 +400,30 @@ int main(int argc, char *argv[])
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
IOobjectList faObjects;
|
||||
// The finite-area fields (multiple finite-area per volume)
|
||||
HashTable<IOobjectList> faObjects;
|
||||
|
||||
if (doFiniteArea && doFields)
|
||||
{
|
||||
// List of area mesh objects (assuming single region)
|
||||
// - scan on processor0
|
||||
faObjects = IOobjectList
|
||||
(
|
||||
procMeshes.meshes()[0],
|
||||
databases[0].timeName(),
|
||||
faMesh::dbDir(word::null), // local relative to mesh
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
// Lists of finite-area fields - scan on processor0
|
||||
faObjects.reserve(areaRegionNames.size());
|
||||
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
// The finite-area objects for this area region
|
||||
IOobjectList objs
|
||||
(
|
||||
procMeshes.meshes()[0],
|
||||
databases[0].timeName(),
|
||||
faMesh::dbDir(areaName), // local relative to mesh
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
if (!objs.empty())
|
||||
{
|
||||
faObjects.emplace_set(areaName, std::move(objs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doFields)
|
||||
@ -548,42 +573,60 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
// If there are any FA fields, reconstruct them
|
||||
|
||||
if (!doFiniteArea)
|
||||
// Reconstruct any finite-area fields
|
||||
if (doFiniteArea)
|
||||
{
|
||||
bool hadFaFields = false;
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
const auto objs = faObjects.cfind(areaName);
|
||||
if (!objs.good())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const auto& faObjs = objs.val();
|
||||
|
||||
if
|
||||
(
|
||||
!faObjs.count(fieldTypes::is_area)
|
||||
&& !faObjs.count<edgeScalarField>()
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hadFaFields = true;
|
||||
|
||||
Info<< "Reconstructing finite-area fields ["
|
||||
<< polyMesh::regionName(areaName)
|
||||
<< "]" << nl << endl;
|
||||
|
||||
const faMesh aMesh(areaName, mesh);
|
||||
|
||||
processorFaMeshes procFaMeshes
|
||||
(
|
||||
procMeshes.meshes(),
|
||||
areaName
|
||||
);
|
||||
|
||||
faFieldReconstructor reconstructor
|
||||
(
|
||||
aMesh,
|
||||
procFaMeshes.meshes(),
|
||||
procFaMeshes.edgeProcAddressing(),
|
||||
procFaMeshes.faceProcAddressing(),
|
||||
procFaMeshes.boundaryProcAddressing()
|
||||
);
|
||||
|
||||
reconstructor.reconstructAllFields(faObjs);
|
||||
}
|
||||
|
||||
if (!hadFaFields)
|
||||
{
|
||||
Info << "No finite-area fields" << nl << endl;
|
||||
}
|
||||
}
|
||||
else if
|
||||
(
|
||||
faObjects.count<areaScalarField>()
|
||||
|| faObjects.count<areaVectorField>()
|
||||
|| faObjects.count<areaSphericalTensorField>()
|
||||
|| faObjects.count<areaSymmTensorField>()
|
||||
|| faObjects.count<areaTensorField>()
|
||||
|| faObjects.count<edgeScalarField>()
|
||||
)
|
||||
{
|
||||
Info << "Reconstructing FA fields" << nl << endl;
|
||||
|
||||
faMesh aMesh(mesh);
|
||||
|
||||
processorFaMeshes procFaMeshes(procMeshes.meshes());
|
||||
|
||||
faFieldReconstructor reconstructor
|
||||
(
|
||||
aMesh,
|
||||
procFaMeshes.meshes(),
|
||||
procFaMeshes.edgeProcAddressing(),
|
||||
procFaMeshes.faceProcAddressing(),
|
||||
procFaMeshes.boundaryProcAddressing()
|
||||
);
|
||||
|
||||
reconstructor.reconstructAllFields(faObjects);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info << "No FA fields" << nl << endl;
|
||||
}
|
||||
|
||||
if (doReconstructSets)
|
||||
{
|
||||
|
||||
@ -119,17 +119,10 @@ autoPtr<faceCoupleInfo> determineCoupledFaces
|
||||
const polyBoundaryMesh& masterPatches = masterMesh.boundaryMesh();
|
||||
|
||||
|
||||
DynamicList<label> masterFaces
|
||||
(
|
||||
masterMesh.nFaces()
|
||||
- masterMesh.nInternalFaces()
|
||||
);
|
||||
DynamicList<label> masterFaces(masterMesh.nBoundaryFaces());
|
||||
|
||||
|
||||
forAll(masterPatches, patchi)
|
||||
for (const polyPatch& pp : masterPatches)
|
||||
{
|
||||
const polyPatch& pp = masterPatches[patchi];
|
||||
|
||||
if (isA<processorPolyPatch>(pp))
|
||||
{
|
||||
for
|
||||
@ -139,11 +132,8 @@ autoPtr<faceCoupleInfo> determineCoupledFaces
|
||||
proci++
|
||||
)
|
||||
{
|
||||
const string toProcString("to" + name(proci));
|
||||
if (
|
||||
pp.name().rfind(toProcString)
|
||||
== (pp.name().size()-toProcString.size())
|
||||
)
|
||||
const string toProcString("to" + Foam::name(proci));
|
||||
if (pp.name().ends_with(toProcString))
|
||||
{
|
||||
label meshFacei = pp.start();
|
||||
forAll(pp, i)
|
||||
@ -156,7 +146,6 @@ autoPtr<faceCoupleInfo> determineCoupledFaces
|
||||
|
||||
}
|
||||
}
|
||||
masterFaces.shrink();
|
||||
|
||||
|
||||
// Pick up all patches on meshToAdd ending in "procBoundaryDDDtoYYY"
|
||||
@ -164,16 +153,10 @@ autoPtr<faceCoupleInfo> determineCoupledFaces
|
||||
|
||||
const polyBoundaryMesh& addPatches = meshToAdd.boundaryMesh();
|
||||
|
||||
DynamicList<label> addFaces
|
||||
(
|
||||
meshToAdd.nFaces()
|
||||
- meshToAdd.nInternalFaces()
|
||||
);
|
||||
DynamicList<label> addFaces(meshToAdd.nBoundaryFaces());
|
||||
|
||||
forAll(addPatches, patchi)
|
||||
for (const polyPatch& pp : addPatches)
|
||||
{
|
||||
const polyPatch& pp = addPatches[patchi];
|
||||
|
||||
if (isA<processorPolyPatch>(pp))
|
||||
{
|
||||
bool isConnected = false;
|
||||
@ -215,7 +198,6 @@ autoPtr<faceCoupleInfo> determineCoupledFaces
|
||||
}
|
||||
}
|
||||
}
|
||||
addFaces.shrink();
|
||||
|
||||
return autoPtr<faceCoupleInfo>::New
|
||||
(
|
||||
@ -502,15 +484,14 @@ void writeMaps
|
||||
|
||||
Info<< " pointProcAddressing" << endl;
|
||||
ioAddr.rename("pointProcAddressing");
|
||||
IOList<label>::writeContents(ioAddr, pointProcAddressing);
|
||||
labelIOList::writeContents(ioAddr, pointProcAddressing);
|
||||
|
||||
// From processor face to reconstructed mesh face
|
||||
Info<< " faceProcAddressing" << endl;
|
||||
ioAddr.rename("faceProcAddressing");
|
||||
labelIOList faceProcAddr(ioAddr, faceProcAddressing);
|
||||
// - add turning index to faceProcAddressing.
|
||||
// See reconstructPar for meaning of turning index.
|
||||
|
||||
labelList faceProcAddr(faceProcAddressing);
|
||||
|
||||
// Now add turning index to faceProcAddressing.
|
||||
// See reconstructPar for meaning of turning index.
|
||||
forAll(faceProcAddr, procFacei)
|
||||
{
|
||||
const label masterFacei = faceProcAddr[procFacei];
|
||||
@ -545,19 +526,21 @@ void writeMaps
|
||||
}
|
||||
}
|
||||
|
||||
faceProcAddr.write();
|
||||
|
||||
Info<< " faceProcAddressing" << endl;
|
||||
ioAddr.rename("faceProcAddressing");
|
||||
labelIOList::writeContents(ioAddr, faceProcAddr);
|
||||
faceProcAddr.clear();
|
||||
|
||||
// From processor cell to reconstructed mesh cell
|
||||
Info<< " cellProcAddressing" << endl;
|
||||
ioAddr.rename("cellProcAddressing");
|
||||
IOList<label>::writeContents(ioAddr, cellProcAddressing);
|
||||
labelIOList::writeContents(ioAddr, cellProcAddressing);
|
||||
|
||||
|
||||
// From processor patch to reconstructed mesh patch
|
||||
Info<< " boundaryProcAddressing" << endl;
|
||||
ioAddr.rename("boundaryProcAddressing");
|
||||
IOList<label>::writeContents(ioAddr, boundProcAddressing);
|
||||
labelIOList::writeContents(ioAddr, boundProcAddressing);
|
||||
|
||||
Info<< endl;
|
||||
}
|
||||
@ -645,7 +628,8 @@ void sortFaEdgeMapping
|
||||
{
|
||||
// From faMeshReconstructor.C - edge shuffling on patches
|
||||
|
||||
Map<label> remapGlobal(2*onePatch.nEdges());
|
||||
Map<label> remapGlobal;
|
||||
remapGlobal.reserve(onePatch.nEdges());
|
||||
for (label edgei = 0; edgei < onePatch.nInternalEdges(); ++edgei)
|
||||
{
|
||||
remapGlobal.insert(edgei, remapGlobal.size());
|
||||
@ -779,12 +763,23 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
#include "addAllRegionOptions.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
// Prevent volume fields [with regionFaModels] from incidental
|
||||
// triggering finite-area
|
||||
regionModels::allowFaModels(false);
|
||||
|
||||
// Prevent volume BCs from triggering finite-area
|
||||
regionModels::allowFaModels(false);
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
|
||||
printWarning();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Configuration
|
||||
|
||||
const bool fullMatch = args.found("fullMatch");
|
||||
const bool procMatch = args.found("procMatch");
|
||||
const bool writeCellDist = args.found("cellDist");
|
||||
@ -835,9 +830,17 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// Get region names
|
||||
// Handle -allRegions, -regions, -region
|
||||
#include "getAllRegionOptions.H"
|
||||
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
areaRegionNames.clear(); // For consistency
|
||||
}
|
||||
|
||||
// Determine the processor count
|
||||
label nProcs{0};
|
||||
|
||||
@ -929,7 +932,8 @@ int main(int argc, char *argv[])
|
||||
polyMesh::meshDir(regionName),
|
||||
databases[0],
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
);
|
||||
|
||||
// Problem: faceCompactIOList recognises both 'faceList' and
|
||||
@ -1399,8 +1403,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
|
||||
// Read finite-area
|
||||
PtrList<faMesh> procFaMeshes(databases.size());
|
||||
// For each named area region that exists create a HashTable
|
||||
// entry that will contain the PtrList for all processors
|
||||
|
||||
PtrList<polyMesh> procMeshes(databases.size());
|
||||
HashTable<PtrList<faMesh>> procAreaRegionMeshes;
|
||||
procAreaRegionMeshes.reserve(areaRegionNames.size());
|
||||
|
||||
forAll(databases, proci)
|
||||
{
|
||||
@ -1408,20 +1416,16 @@ int main(int argc, char *argv[])
|
||||
<< "Read processor mesh: "
|
||||
<< (databases[proci].caseName()/regionDir) << endl;
|
||||
|
||||
procMeshes.set
|
||||
const polyMesh& procMesh = procMeshes.emplace
|
||||
(
|
||||
proci,
|
||||
new polyMesh
|
||||
IOobject
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
databases[proci].timeName(),
|
||||
databases[proci]
|
||||
)
|
||||
regionName,
|
||||
databases[proci].timeName(),
|
||||
databases[proci]
|
||||
)
|
||||
);
|
||||
const polyMesh& procMesh = procMeshes[proci];
|
||||
|
||||
writeMaps
|
||||
(
|
||||
@ -1444,38 +1448,67 @@ int main(int argc, char *argv[])
|
||||
"boundary"
|
||||
);
|
||||
|
||||
IOobject io
|
||||
(
|
||||
"faBoundary",
|
||||
boundaryInst,
|
||||
faMesh::meshDir(procMesh, word::null),
|
||||
procMesh.time(),
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
);
|
||||
|
||||
if (io.typeHeaderOk<faBoundaryMesh>(true))
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
// Always based on the volume decomposition!
|
||||
procFaMeshes.set(proci, new faMesh(procMesh));
|
||||
IOobject io
|
||||
(
|
||||
"faBoundary",
|
||||
boundaryInst,
|
||||
faMesh::meshDir(procMesh, areaName),
|
||||
procMesh.time(),
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
);
|
||||
|
||||
if (io.typeHeaderOk<faBoundaryMesh>(true))
|
||||
{
|
||||
// Always based on the volume decomposition!
|
||||
auto& procFaMeshes = procAreaRegionMeshes(areaName);
|
||||
procFaMeshes.resize(databases.size());
|
||||
|
||||
procFaMeshes.set
|
||||
(
|
||||
proci,
|
||||
new faMesh(areaName, procMesh)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Finite-area mapping
|
||||
doFiniteArea = false;
|
||||
forAll(procFaMeshes, proci)
|
||||
// A finite-area mapping exists if procFaMeshes was filled
|
||||
|
||||
// Re-read reconstructed polyMesh. Note: could probably be avoided
|
||||
// by merging into loops above.
|
||||
refPtr<polyMesh> masterPolyMeshPtr;
|
||||
|
||||
if (!procAreaRegionMeshes.empty())
|
||||
{
|
||||
if (procFaMeshes.set(proci))
|
||||
{
|
||||
doFiniteArea = true;
|
||||
}
|
||||
masterPolyMeshPtr.reset
|
||||
(
|
||||
new polyMesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
runTime.timeName(),
|
||||
runTime
|
||||
),
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (doFiniteArea)
|
||||
// Process any finite-area meshes
|
||||
for (const auto& iter : procAreaRegionMeshes.csorted())
|
||||
{
|
||||
const auto& areaName = iter.key();
|
||||
const auto& procFaMeshes = iter.val();
|
||||
|
||||
const polyMesh& masterMesh = masterPolyMeshPtr();
|
||||
|
||||
// Addressing from processor to reconstructed case
|
||||
labelListList faFaceProcAddressing(nProcs);
|
||||
labelListList faEdgeProcAddressing(nProcs);
|
||||
@ -1493,32 +1526,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
faBoundProcAddressing[proci] = identity(bm.size());
|
||||
// Mark processor patches
|
||||
for
|
||||
(
|
||||
label patchi = bm.nNonProcessor();
|
||||
patchi < bm.size();
|
||||
++patchi
|
||||
)
|
||||
{
|
||||
faBoundProcAddressing[proci][patchi] = -1;
|
||||
}
|
||||
faBoundProcAddressing[proci].slice(bm.nNonProcessor()) = -1;
|
||||
}
|
||||
|
||||
|
||||
// Re-read reconstructed polyMesh. Note: could probably be avoided
|
||||
// by merging into loops above.
|
||||
const polyMesh masterMesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
runTime.timeName(),
|
||||
runTime
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
// faceProcAddressing
|
||||
// ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -1553,13 +1564,13 @@ int main(int argc, char *argv[])
|
||||
// Construct without patches
|
||||
faMesh masterFaMesh
|
||||
(
|
||||
areaName,
|
||||
masterMesh,
|
||||
std::move(masterFaceLabels),
|
||||
io
|
||||
);
|
||||
|
||||
const uindirectPrimitivePatch& masterPatch =
|
||||
masterFaMesh.patch();
|
||||
const auto& masterPatch = masterFaMesh.patch();
|
||||
|
||||
|
||||
// pointProcAddressing
|
||||
@ -1571,7 +1582,7 @@ int main(int argc, char *argv[])
|
||||
const auto& procPatch = procFaMeshes[proci].patch();
|
||||
const auto& mp = procPatch.meshPoints();
|
||||
|
||||
labelList& pointAddr = faPointProcAddressing[proci];
|
||||
auto& pointAddr = faPointProcAddressing[proci];
|
||||
pointAddr.resize_nocopy(mp.size());
|
||||
|
||||
forAll(mp, i)
|
||||
@ -1620,8 +1631,7 @@ int main(int argc, char *argv[])
|
||||
label nPatches = 0;
|
||||
forAll(completePatches, patchi)
|
||||
{
|
||||
const labelList& patchEdgeLabels =
|
||||
singlePatchEdgeLabels[patchi];
|
||||
const auto& patchEdgeLabels = singlePatchEdgeLabels[patchi];
|
||||
|
||||
const faPatch& fap = procMesh0.boundary()[patchi];
|
||||
|
||||
@ -1652,11 +1662,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Serial mesh - no parallel communication
|
||||
|
||||
const bool oldParRun = Pstream::parRun(false);
|
||||
const bool oldParRun = UPstream::parRun(false);
|
||||
|
||||
masterFaMesh.addFaPatches(completePatches);
|
||||
|
||||
Pstream::parRun(oldParRun); // Restore parallel state
|
||||
UPstream::parRun(oldParRun); // Restore parallel state
|
||||
|
||||
|
||||
// Write mesh & individual addressing
|
||||
|
||||
@ -33,99 +33,266 @@ License
|
||||
#include "decomposedBlockData.H"
|
||||
#include "IFstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::checkFileExistence(const fileName& fName)
|
||||
// Trimmed-down version of lookupAndCacheProcessorsPath
|
||||
// with Foam::exists() check. No caching.
|
||||
|
||||
// Check for two conditions:
|
||||
// - file has to exist
|
||||
// - if collated the entry has to exist inside the file
|
||||
|
||||
// Note: bypass fileOperation::filePath(IOobject&) since has problems
|
||||
// with going to a different number of processors
|
||||
// (in collated format). Use file-based searching instead
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// Trimmed-down version of lookupAndCacheProcessorsPath
|
||||
// with Foam::exists() check. No caching.
|
||||
|
||||
// Check for two conditions:
|
||||
// - file has to exist
|
||||
// - if collated the entry has to exist inside the file
|
||||
|
||||
// Note: bypass fileOperation::filePath(IOobject&) since has problems
|
||||
// with going to a different number of processors
|
||||
// (in collated format). Use file-based searching instead
|
||||
|
||||
const auto& handler = Foam::fileHandler();
|
||||
typedef fileOperation::procRangeType procRangeType;
|
||||
|
||||
fileName path, pDir, local;
|
||||
procRangeType group;
|
||||
label numProcs;
|
||||
const label proci =
|
||||
fileOperation::splitProcessorPath
|
||||
(fName, path, pDir, local, group, numProcs);
|
||||
// If indeed collated format:
|
||||
// Collect block-number in individual filenames
|
||||
// (might differ on different processors)
|
||||
static bool checkFileExistenceCollated
|
||||
(
|
||||
const Foam::fileOperation& handler,
|
||||
const Foam::fileName& fName
|
||||
)
|
||||
{
|
||||
// using namespace Foam;
|
||||
|
||||
bool found = false;
|
||||
|
||||
if (proci != -1)
|
||||
{
|
||||
// Read all directories to see any beginning with processor
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
const label handlerComm = handler.comm();
|
||||
|
||||
const fileNameList dirEntries
|
||||
(
|
||||
handler.readDir(path, fileName::Type::DIRECTORY)
|
||||
);
|
||||
const label globalProci = UPstream::myProcNo(UPstream::worldComm);
|
||||
const label handlerProci = UPstream::myProcNo(handlerComm);
|
||||
const label nHandlerProcs = UPstream::nProcs(handlerComm);
|
||||
|
||||
// Extract info from processorN or processorsNN
|
||||
// - highest processor number
|
||||
// - directory+offset containing data for proci
|
||||
|
||||
// label nProcs = 0;
|
||||
for (const fileName& dirN : dirEntries)
|
||||
// Determine my local block number
|
||||
label myBlockNumber = -1;
|
||||
{
|
||||
// Analyse directory name
|
||||
label rNum(-1);
|
||||
const label readProci =
|
||||
fileOperation::detectProcessorPath(dirN, group, &rNum);
|
||||
fileOperation::procRangeType group;
|
||||
label proci = fileOperation::detectProcessorPath(fName, group);
|
||||
|
||||
if (proci == readProci)
|
||||
if (proci == -1 && group.empty())
|
||||
{
|
||||
// Found "processorN"
|
||||
if (Foam::exists(path/dirN/local))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
// 'processorsXXX' format so contains all ranks
|
||||
// according to worldComm
|
||||
myBlockNumber = globalProci;
|
||||
}
|
||||
else if (rNum != -1)
|
||||
else
|
||||
{
|
||||
// "processorsNN" or "processorsNN_start-end"
|
||||
if (group.empty())
|
||||
{
|
||||
// "processorsNN"
|
||||
if (proci < rNum && Foam::exists(path/dirN/local))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (group.contains(proci))
|
||||
{
|
||||
// "processorsNN_start-end"
|
||||
// - save the local proc offset
|
||||
|
||||
if (Foam::exists(path/dirN/local))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 'processorsXXX_n-m' format so check for relative rank
|
||||
myBlockNumber = handlerProci;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
found = Foam::exists(fName);
|
||||
// Since we are streaming anyhow, could also pack as tuple:
|
||||
// Tuple2<fileName, label>
|
||||
|
||||
|
||||
// Collect file names on master of local communicator
|
||||
const fileNameList fNames
|
||||
(
|
||||
Pstream::listGatherValues
|
||||
(
|
||||
fName,
|
||||
handlerComm,
|
||||
UPstream::msgType()
|
||||
)
|
||||
);
|
||||
|
||||
// Collect block numbers on master of local communicator
|
||||
const labelList myBlockNumbers
|
||||
(
|
||||
Pstream::listGatherValues
|
||||
(
|
||||
myBlockNumber,
|
||||
handlerComm,
|
||||
UPstream::msgType()
|
||||
)
|
||||
);
|
||||
|
||||
// Determine for all whether the filename exists in the collated file.
|
||||
boolList allFound;
|
||||
|
||||
if (UPstream::master(handlerComm))
|
||||
{
|
||||
allFound.resize(nHandlerProcs, false);
|
||||
|
||||
// Store nBlocks and index of file that was used for nBlocks
|
||||
label nBlocks = -1;
|
||||
label blockRanki = -1;
|
||||
forAll(fNames, ranki)
|
||||
{
|
||||
if
|
||||
(
|
||||
blockRanki == -1
|
||||
|| (fNames[ranki] != fNames[blockRanki])
|
||||
)
|
||||
{
|
||||
blockRanki = ranki;
|
||||
IFstream is(fNames[ranki]);
|
||||
nBlocks = decomposedBlockData::getNumBlocks(is);
|
||||
}
|
||||
|
||||
allFound[ranki] = (myBlockNumbers[ranki] < nBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
// Scatter using the handler communicator
|
||||
found = Pstream::listScatterValues
|
||||
(
|
||||
allFound,
|
||||
handlerComm,
|
||||
UPstream::msgType()
|
||||
);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
} // End namespace
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::bitSet Foam::haveProcessorFile
|
||||
(
|
||||
const word& name, // eg "faces"
|
||||
const fileName& instance, // eg "constant"
|
||||
const fileName& local, // eg, polyMesh
|
||||
const Time& runTime,
|
||||
const bool verbose
|
||||
)
|
||||
{
|
||||
const auto& handler = Foam::fileHandler();
|
||||
|
||||
const fileName fName
|
||||
(
|
||||
handler.filePath(runTime.path()/instance/local/name)
|
||||
);
|
||||
|
||||
bool found = handler.isFile(fName);
|
||||
|
||||
// Assume non-collated (as fallback value).
|
||||
// If everyone claims to have the file, use master to verify if
|
||||
// collated is involved.
|
||||
|
||||
bool isCollated = false;
|
||||
|
||||
if (returnReduceAnd(found, UPstream::worldComm))
|
||||
{
|
||||
// Test for collated format.
|
||||
// Note: can test only world-master. Since even host-collated will have
|
||||
// same file format type for all processors
|
||||
if (UPstream::master(UPstream::worldComm))
|
||||
{
|
||||
const bool oldParRun = UPstream::parRun(false);
|
||||
|
||||
if (IFstream is(fName); is.good())
|
||||
{
|
||||
IOobject io(name, instance, local, runTime);
|
||||
io.readHeader(is);
|
||||
|
||||
isCollated = decomposedBlockData::isCollatedType(io);
|
||||
}
|
||||
|
||||
UPstream::parRun(oldParRun);
|
||||
}
|
||||
Pstream::broadcast(isCollated, UPstream::worldComm);
|
||||
}
|
||||
|
||||
// For collated, check that the corresponding blocks exist
|
||||
if (isCollated)
|
||||
{
|
||||
found = checkFileExistenceCollated(handler, fName);
|
||||
}
|
||||
|
||||
|
||||
// Globally consistent information about who has the file
|
||||
bitSet haveFileOnProc = bitSet::allGather(found, UPstream::worldComm);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "Per processor availability of \""
|
||||
<< name << "\" file in " << instance/local << nl
|
||||
<< " " << flatOutput(haveFileOnProc) << nl << endl;
|
||||
}
|
||||
|
||||
return haveFileOnProc;
|
||||
}
|
||||
|
||||
|
||||
Foam::boolList Foam::haveMeshFile
|
||||
(
|
||||
const word& name, // eg "faces"
|
||||
const fileName& instance, // eg "constant"
|
||||
const fileName& local, // eg, polyMesh
|
||||
const Time& runTime,
|
||||
const bool verbose
|
||||
)
|
||||
{
|
||||
const auto& handler = Foam::fileHandler();
|
||||
|
||||
const fileName fName
|
||||
(
|
||||
handler.filePath(runTime.path()/instance/local/name)
|
||||
);
|
||||
|
||||
bool found = handler.isFile(fName);
|
||||
|
||||
// Assume non-collated (as fallback value).
|
||||
// If everyone claims to have the file, use master to verify if
|
||||
// collated is involved.
|
||||
|
||||
bool isCollated = false;
|
||||
|
||||
if (returnReduceAnd(found, UPstream::worldComm))
|
||||
{
|
||||
// Test for collated format.
|
||||
// Note: can test only world-master. Since even host-collated will have
|
||||
// same file format type for all processors
|
||||
if (UPstream::master(UPstream::worldComm))
|
||||
{
|
||||
const bool oldParRun = UPstream::parRun(false);
|
||||
|
||||
if (IFstream is(fName); is.good())
|
||||
{
|
||||
IOobject io(name, instance, local, runTime);
|
||||
io.readHeader(is);
|
||||
|
||||
isCollated = decomposedBlockData::isCollatedType(io);
|
||||
}
|
||||
|
||||
UPstream::parRun(oldParRun);
|
||||
}
|
||||
Pstream::broadcast(isCollated, UPstream::worldComm);
|
||||
}
|
||||
|
||||
// For collated, check that the corresponding blocks exist
|
||||
if (isCollated)
|
||||
{
|
||||
found = checkFileExistenceCollated(handler, fName);
|
||||
}
|
||||
|
||||
|
||||
// Globally consistent information about who has a mesh
|
||||
boolList haveFileOnProc
|
||||
(
|
||||
UPstream::allGatherValues<bool>(found, UPstream::worldComm)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "Per processor availability of \""
|
||||
<< name << "\" file in " << instance/local << nl
|
||||
<< " " << flatOutput(haveFileOnProc) << nl << endl;
|
||||
}
|
||||
|
||||
return haveFileOnProc;
|
||||
}
|
||||
|
||||
|
||||
Foam::boolList Foam::haveMeshFile
|
||||
(
|
||||
@ -135,143 +302,49 @@ Foam::boolList Foam::haveMeshFile
|
||||
const bool verbose
|
||||
)
|
||||
{
|
||||
#if 0
|
||||
|
||||
// Simple directory scanning - too fragile
|
||||
bool found = checkFileExistence(runTime.path()/meshPath/meshFile);
|
||||
|
||||
#else
|
||||
|
||||
// Trimmed-down version of lookupAndCacheProcessorsPath
|
||||
// with Foam::exists() check. No caching.
|
||||
|
||||
// Check for two conditions:
|
||||
// - file has to exist
|
||||
// - if collated the entry has to exist inside the file
|
||||
|
||||
// Note: bypass fileOperation::filePath(IOobject&) since has problems
|
||||
// with going to a different number of processors
|
||||
// (in collated format). Use file-based searching instead
|
||||
|
||||
const auto& handler = Foam::fileHandler();
|
||||
typedef fileOperation::procRangeType procRangeType;
|
||||
|
||||
const fileName fName
|
||||
(
|
||||
handler.filePath(runTime.path()/meshPath/meshFile)
|
||||
);
|
||||
|
||||
bool found = handler.isFile(fName);
|
||||
if (returnReduceAnd(found)) // worldComm
|
||||
|
||||
// Assume non-collated (as fallback value).
|
||||
// If everyone claims to have the file, use master to verify if
|
||||
// collated is involved.
|
||||
|
||||
bool isCollated = false;
|
||||
|
||||
if (returnReduceAnd(found, UPstream::worldComm))
|
||||
{
|
||||
// Bit tricky: avoid having all slaves open file since this involves
|
||||
// reading it on master and broadcasting it. This fails if file > 2G.
|
||||
// So instead only read on master
|
||||
|
||||
bool isCollated = false;
|
||||
|
||||
// Test for collated format.
|
||||
// Note: can test only world-master. Since even host-collated will have
|
||||
// same file format type for all processors
|
||||
if (UPstream::master(UPstream::worldComm))
|
||||
{
|
||||
const bool oldParRun = UPstream::parRun(false);
|
||||
|
||||
IFstream is(fName);
|
||||
if (is.good())
|
||||
if (IFstream is(fName); is.good())
|
||||
{
|
||||
IOobject io(meshFile, meshPath, runTime);
|
||||
io.readHeader(is);
|
||||
|
||||
isCollated = decomposedBlockData::isCollatedType(io);
|
||||
}
|
||||
|
||||
UPstream::parRun(oldParRun);
|
||||
}
|
||||
Pstream::broadcast(isCollated); //UPstream::worldComm
|
||||
|
||||
|
||||
// Collect block-number in individual filenames (might differ
|
||||
// on different processors)
|
||||
if (isCollated)
|
||||
{
|
||||
const label nProcs = UPstream::nProcs(fileHandler().comm());
|
||||
const label myProcNo = UPstream::myProcNo(fileHandler().comm());
|
||||
|
||||
// Collect file names on master of local communicator
|
||||
const fileNameList fNames
|
||||
(
|
||||
Pstream::listGatherValues
|
||||
(
|
||||
fName,
|
||||
fileHandler().comm(),
|
||||
UPstream::msgType()
|
||||
)
|
||||
);
|
||||
|
||||
// Collect local block number
|
||||
label myBlockNumber = -1;
|
||||
{
|
||||
procRangeType group;
|
||||
label proci = fileOperation::detectProcessorPath(fName, group);
|
||||
|
||||
if (proci == -1 && group.empty())
|
||||
{
|
||||
// 'processorsXXX' format so contains all ranks
|
||||
// according to worldComm
|
||||
myBlockNumber = UPstream::myProcNo(UPstream::worldComm);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 'processorsXXX_n-m' format so check for the
|
||||
// relative rank
|
||||
myBlockNumber = myProcNo;
|
||||
}
|
||||
}
|
||||
const labelList myBlockNumbers
|
||||
(
|
||||
Pstream::listGatherValues
|
||||
(
|
||||
myBlockNumber,
|
||||
fileHandler().comm(),
|
||||
UPstream::msgType()
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Determine for all whether the filename exists in the collated
|
||||
// file.
|
||||
boolList allFound(nProcs, false);
|
||||
|
||||
if (UPstream::master(fileHandler().comm()))
|
||||
{
|
||||
// Store nBlocks and index of file that was used for nBlocks
|
||||
label nBlocks = -1;
|
||||
label blockRanki = -1;
|
||||
forAll(fNames, ranki)
|
||||
{
|
||||
if
|
||||
(
|
||||
blockRanki == -1
|
||||
|| (fNames[ranki] != fNames[blockRanki])
|
||||
)
|
||||
{
|
||||
blockRanki = ranki;
|
||||
IFstream is(fNames[ranki]);
|
||||
nBlocks = decomposedBlockData::getNumBlocks(is);
|
||||
}
|
||||
|
||||
allFound[ranki] = (myBlockNumbers[ranki] < nBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
found = Pstream::listScatterValues
|
||||
(
|
||||
allFound,
|
||||
fileHandler().comm(),
|
||||
UPstream::msgType()
|
||||
);
|
||||
}
|
||||
Pstream::broadcast(isCollated, UPstream::worldComm);
|
||||
}
|
||||
#endif
|
||||
|
||||
// For collated, check that the corresponding blocks exist
|
||||
if (isCollated)
|
||||
{
|
||||
found = checkFileExistenceCollated(handler, fName);
|
||||
}
|
||||
|
||||
|
||||
// Globally consistent information about who has a mesh
|
||||
boolList haveFileOnProc
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012 OpenFOAM Foundation
|
||||
Copyright (C) 2022-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2022-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -48,15 +48,32 @@ namespace Foam
|
||||
// Forward Declarations
|
||||
class faMesh;
|
||||
|
||||
//- Check for availability of given file
|
||||
bool checkFileExistence(const fileName& fName);
|
||||
//- Check for availability of specified file (on all ranks)
|
||||
bitSet haveProcessorFile
|
||||
(
|
||||
const word& name, // eg, "faces"
|
||||
const fileName& instance, // eg, "constant"
|
||||
const fileName& local, // eg, "polyMesh"
|
||||
const Time& runTime,
|
||||
const bool verbose = true
|
||||
);
|
||||
|
||||
//- Check for availability of specified mesh file (default: "faces")
|
||||
//- Check for availability of specified file (on all ranks)
|
||||
boolList haveMeshFile
|
||||
(
|
||||
const word& name, // eg, "faces"
|
||||
const fileName& instance, // eg, "constant"
|
||||
const fileName& local, // eg, "polyMesh"
|
||||
const Time& runTime,
|
||||
const bool verbose = true
|
||||
);
|
||||
|
||||
//- Check for availability of specified mesh file
|
||||
boolList haveMeshFile
|
||||
(
|
||||
const Time& runTime,
|
||||
const fileName& meshPath,
|
||||
const word& meshFile = "faces",
|
||||
const word& meshFile,
|
||||
const bool verbose = true
|
||||
);
|
||||
|
||||
@ -75,7 +92,7 @@ void masterMeshInstance
|
||||
fileName& pointsInstance
|
||||
);
|
||||
|
||||
}
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -21,44 +21,59 @@ Requires
|
||||
|
||||
// Initially all possible objects that are available at the final time
|
||||
List<wordHashSet> availableRegionObjectNames(meshes.size());
|
||||
List<wordHashSet> availableFaRegionObjectNames(meshes.size());
|
||||
List<HashTable<wordHashSet>> availableFaRegionObjectNames(meshes.size());
|
||||
|
||||
forAll(meshes, regioni)
|
||||
{
|
||||
const auto& mesh = meshes[regioni];
|
||||
|
||||
IOobjectList objects;
|
||||
IOobjectList faObjects;
|
||||
HashTable<IOobjectList> faObjects;
|
||||
|
||||
if (doConvertFields && !timeDirs.empty())
|
||||
{
|
||||
// const word& checkTimeDir = timeDirs.back().name();
|
||||
|
||||
// List of volume mesh objects for this instance
|
||||
objects = IOobjectList(mesh, timeDirs.back().name());
|
||||
|
||||
// List of area mesh objects (assuming single region)
|
||||
faObjects = IOobjectList
|
||||
(
|
||||
mesh.time(),
|
||||
timeDirs.back().name(),
|
||||
faMesh::dbDir(mesh, word::null),
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
if (fieldSelector)
|
||||
{
|
||||
objects.filterObjects(fieldSelector);
|
||||
faObjects.filterObjects(fieldSelector);
|
||||
}
|
||||
|
||||
// Remove "*_0" restart fields
|
||||
objects.prune_0();
|
||||
faObjects.prune_0();
|
||||
|
||||
if (!doPointValues)
|
||||
{
|
||||
// Prune point fields if disabled
|
||||
objects.filterClasses(Foam::fieldTypes::is_point, true);
|
||||
}
|
||||
|
||||
|
||||
// The finite-area regions and their fields for this volume region
|
||||
// and instance
|
||||
faObjects.reserve(areaRegionNames.size());
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
IOobjectList objs
|
||||
(
|
||||
faMesh::Registry(mesh),
|
||||
timeDirs.back().name(),
|
||||
polyMesh::regionName(areaName),
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
if (fieldSelector)
|
||||
{
|
||||
objs.filterObjects(fieldSelector);
|
||||
}
|
||||
|
||||
// Remove "*_0" restart fields
|
||||
objs.prune_0();
|
||||
faObjects(areaName) = std::move(objs);
|
||||
}
|
||||
}
|
||||
|
||||
// Volume fields
|
||||
@ -78,20 +93,29 @@ forAll(meshes, regioni)
|
||||
}
|
||||
|
||||
// Area fields
|
||||
if (!faObjects.empty())
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
wordList objectNames(faObjects.sortedNames());
|
||||
wordList objectNames;
|
||||
|
||||
// Check availability for all times... (assuming single region)
|
||||
checkData
|
||||
if (const auto iter = faObjects.cfind(areaName); iter.good())
|
||||
{
|
||||
objectNames = iter.val().sortedNames();
|
||||
|
||||
// Check availability for all times...
|
||||
checkData
|
||||
(
|
||||
faMesh::Registry(mesh),
|
||||
timeDirs,
|
||||
objectNames,
|
||||
polyMesh::regionName(areaName)
|
||||
);
|
||||
}
|
||||
|
||||
availableFaRegionObjectNames[regioni].emplace_set
|
||||
(
|
||||
mesh.time(),
|
||||
timeDirs,
|
||||
objectNames,
|
||||
faMesh::dbDir(mesh, word::null)
|
||||
areaName,
|
||||
std::move(objectNames)
|
||||
);
|
||||
|
||||
availableFaRegionObjectNames[regioni] = objectNames;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
@ -15,12 +15,14 @@ Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// Cases and meshes per volume region
|
||||
PtrList<ensightCase> ensightCases(regionNames.size());
|
||||
PtrList<ensightMesh> ensightMeshes(regionNames.size());
|
||||
|
||||
PtrList<faMesh> meshesFa(regionNames.size());
|
||||
PtrList<ensightCase> ensightCasesFa(regionNames.size());
|
||||
PtrList<ensightFaMesh> ensightMeshesFa(regionNames.size());
|
||||
// Per volume region can have multiple finite-area regions
|
||||
List<PtrDynList<faMesh>> meshesFa(regionNames.size());
|
||||
List<PtrDynList<ensightCase>> ensightCasesFa(regionNames.size());
|
||||
List<PtrDynList<ensightFaMesh>> ensightMeshesFa(regionNames.size());
|
||||
|
||||
{
|
||||
forAll(regionNames, regioni)
|
||||
@ -45,6 +47,7 @@ PtrList<ensightFaMesh> ensightMeshesFa(regionNames.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Volume mesh
|
||||
ensightMeshes.set
|
||||
(
|
||||
regioni,
|
||||
@ -59,33 +62,60 @@ PtrList<ensightFaMesh> ensightMeshesFa(regionNames.size());
|
||||
new ensightCase(ensCasePath, ensCaseName, caseOpts)
|
||||
);
|
||||
|
||||
if (doFiniteArea)
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
autoPtr<faMesh> faMeshPtr(faMesh::TryNew(mesh));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Note: not every volume region is guaranteed to have
|
||||
// any or all area region(s)
|
||||
|
||||
meshesFa[regioni].reserve_exact(areaRegionNames.size());
|
||||
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
auto faMeshPtr = faMesh::TryNew(areaName, mesh);
|
||||
|
||||
if (faMeshPtr)
|
||||
{
|
||||
ensightCasesFa.set
|
||||
(
|
||||
regioni,
|
||||
new ensightCase
|
||||
(
|
||||
ensCasePath/"finite-area",
|
||||
"finite-area",
|
||||
caseOpts
|
||||
)
|
||||
);
|
||||
|
||||
meshesFa.set(regioni, std::move(faMeshPtr));
|
||||
|
||||
ensightMeshesFa.set
|
||||
(
|
||||
regioni,
|
||||
new ensightFaMesh(meshesFa[regioni])
|
||||
);
|
||||
ensightMeshesFa[regioni].verbose(optVerbose);
|
||||
meshesFa[regioni].push_back(std::move(faMeshPtr));
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the ensight components
|
||||
const label nAreas = meshesFa[regioni].size();
|
||||
ensightCasesFa[regioni].reserve_exact(nAreas);
|
||||
ensightMeshesFa[regioni].reserve_exact(nAreas);
|
||||
|
||||
for (const faMesh& areaMesh : meshesFa[regioni])
|
||||
{
|
||||
// Use regionName() - automatically filters for defaultRegion
|
||||
const word& areaName = areaMesh.regionName();
|
||||
|
||||
if (areaName.empty())
|
||||
{
|
||||
// single-region
|
||||
ensightCasesFa[regioni].emplace_back
|
||||
(
|
||||
ensCasePath/"finite-area",
|
||||
"finite-area",
|
||||
caseOpts
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// multi-region
|
||||
ensightCasesFa[regioni].emplace_back
|
||||
(
|
||||
ensCasePath/"finite-area"/areaName,
|
||||
areaName,
|
||||
caseOpts
|
||||
);
|
||||
}
|
||||
|
||||
auto& ensFaMesh = ensightMeshesFa[regioni].emplace_back(areaMesh);
|
||||
ensFaMesh.verbose(optVerbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -124,6 +124,7 @@ Usage
|
||||
#include "OFstream.H"
|
||||
#include "Pstream.H"
|
||||
#include "HashOps.H"
|
||||
#include "PtrDynList.H"
|
||||
#include "regionProperties.H"
|
||||
|
||||
#include "fvc.H"
|
||||
@ -172,6 +173,7 @@ int main(int argc, char *argv[])
|
||||
argList::addVerboseOption();
|
||||
|
||||
#include "addAllRegionOptions.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
argList::addBoolOption
|
||||
(
|
||||
@ -323,6 +325,9 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
argList::addOptionCompat("cellZones", {"cellZone", 1912});
|
||||
|
||||
// Prevent volume BCs from triggering finite-area
|
||||
regionModels::allowFaModels(false);
|
||||
|
||||
#include "setRootCase.H"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -436,6 +441,14 @@ int main(int argc, char *argv[])
|
||||
// Handle -allRegions, -regions, -region
|
||||
#include "getAllRegionOptions.H"
|
||||
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
areaRegionNames.clear(); // For consistency
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Directory management
|
||||
|
||||
@ -515,29 +528,32 @@ int main(int argc, char *argv[])
|
||||
polyMesh::readUpdateState meshState = mesh.readUpdate();
|
||||
const bool moving = (meshState != polyMesh::UNCHANGED);
|
||||
|
||||
// Ensight
|
||||
// Ensight (fvMesh)
|
||||
auto& ensCase = ensightCases[regioni];
|
||||
auto& ensMesh = ensightMeshes[regioni];
|
||||
|
||||
// Finite-area (can be missing)
|
||||
auto* ensFaCasePtr = ensightCasesFa.get(regioni);
|
||||
auto* ensFaMeshPtr = ensightMeshesFa.get(regioni);
|
||||
|
||||
ensCase.setTime(timeDirs[timei], timeIndex);
|
||||
if (ensFaCasePtr)
|
||||
|
||||
// Finite-area (optional)
|
||||
// Accounting exists for each volume region but may be empty
|
||||
auto& ensFaCases = ensightCasesFa[regioni];
|
||||
auto& ensFaMeshes = ensightMeshesFa[regioni];
|
||||
|
||||
for (auto& ensFaCase : ensFaCases)
|
||||
{
|
||||
ensFaCasePtr->setTime(timeDirs[timei], timeIndex);
|
||||
ensFaCase.setTime(timeDirs[timei], timeIndex);
|
||||
}
|
||||
|
||||
// Movement
|
||||
if (moving)
|
||||
{
|
||||
ensMesh.expire();
|
||||
ensMesh.correct();
|
||||
|
||||
if (ensFaMeshPtr)
|
||||
for (auto& ensFaMesh : ensFaMeshes)
|
||||
{
|
||||
ensFaMeshPtr->expire();
|
||||
ensFaMeshPtr->correct();
|
||||
ensFaMesh.expire();
|
||||
ensFaMesh.correct();
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,15 +568,19 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// finite-area
|
||||
if (ensFaCasePtr && ensFaMeshPtr)
|
||||
forAll(ensFaMeshes, areai)
|
||||
{
|
||||
autoPtr<ensightGeoFile> os =
|
||||
ensFaCasePtr->newGeometry(hasMovingMesh);
|
||||
const auto& ensFaCase = ensFaCases[areai];
|
||||
const auto& ensFaMesh = ensFaMeshes[areai];
|
||||
|
||||
ensFaMeshPtr->write(os.ref());
|
||||
autoPtr<ensightGeoFile> os =
|
||||
ensFaCase.newGeometry(hasMovingMesh);
|
||||
|
||||
ensFaMesh.write(os.ref());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Objects at this time
|
||||
IOobjectList objects(mesh, runTime.timeName());
|
||||
|
||||
@ -572,23 +592,37 @@ int main(int argc, char *argv[])
|
||||
// Volume, internal, point fields
|
||||
#include "convertVolumeFields.H"
|
||||
|
||||
// The finite-area objects at this time
|
||||
IOobjectList faObjects;
|
||||
|
||||
if (ensFaMeshPtr)
|
||||
// finite-area
|
||||
forAll(ensFaMeshes, areai)
|
||||
{
|
||||
faObjects =
|
||||
IOobjectList(ensFaMeshPtr->mesh(), runTime.timeName());
|
||||
auto* ensFaCasePtr = ensFaCases.get(areai);
|
||||
auto* ensFaMeshPtr = ensFaMeshes.get(areai);
|
||||
|
||||
faObjects.filterObjects
|
||||
(
|
||||
availableFaRegionObjectNames[regioni]
|
||||
);
|
||||
// The finite-area region objects at this time
|
||||
IOobjectList faObjects;
|
||||
|
||||
if (ensFaMeshPtr)
|
||||
{
|
||||
const word& areaName = ensFaMeshPtr->mesh().name();
|
||||
|
||||
faObjects = IOobjectList
|
||||
(
|
||||
faMesh::Registry(mesh),
|
||||
runTime.timeName(),
|
||||
polyMesh::regionName(areaName),
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
faObjects.filterObjects
|
||||
(
|
||||
availableFaRegionObjectNames[regioni](areaName)
|
||||
);
|
||||
}
|
||||
|
||||
// The finiteArea fields
|
||||
#include "convertAreaFields.H"
|
||||
}
|
||||
|
||||
// The finiteArea fields
|
||||
#include "convertAreaFields.H"
|
||||
|
||||
// Lagrangian fields
|
||||
#include "convertLagrangian.H"
|
||||
}
|
||||
@ -601,14 +635,13 @@ int main(int argc, char *argv[])
|
||||
// Write cases
|
||||
forAll(ensightCases, regioni)
|
||||
{
|
||||
// finite-volume
|
||||
ensightCases[regioni].write();
|
||||
}
|
||||
|
||||
forAll(ensightCasesFa, regioni)
|
||||
{
|
||||
if (ensightCasesFa.set(regioni))
|
||||
// Finite-area (if any)
|
||||
for (const auto& ensFaCase : ensightCasesFa[regioni])
|
||||
{
|
||||
ensightCasesFa[regioni].write();
|
||||
ensFaCase.write();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,7 +26,6 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "readFields.H"
|
||||
#include "volFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
@ -42,26 +41,30 @@ Foam::label Foam::checkData
|
||||
|
||||
wordHashSet goodFields;
|
||||
|
||||
IOobject io
|
||||
(
|
||||
"any-name", // placeholder
|
||||
"constant", // placeholder
|
||||
local,
|
||||
obr,
|
||||
IOobjectOption::NO_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
for (const word& fieldName : objectNames)
|
||||
{
|
||||
// // If prune_0() not previously used...
|
||||
// if (objectNames.ends_with("_0")) continue;
|
||||
// In case prune_0() not previously used...
|
||||
if (fieldName.ends_with("_0")) continue;
|
||||
|
||||
bool good = false;
|
||||
|
||||
for (const instant& inst : timeDirs)
|
||||
{
|
||||
good =
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
inst.name(),
|
||||
local,
|
||||
obr,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
).typeHeaderOk<volScalarField>(false, false);
|
||||
io.resetHeader(fieldName);
|
||||
io.instance() = inst.name();
|
||||
|
||||
good = io.typeHeaderOk<regIOobject>(false, false);
|
||||
|
||||
if (!good)
|
||||
{
|
||||
|
||||
@ -22,24 +22,66 @@ Description
|
||||
//
|
||||
|
||||
// No subsetting!
|
||||
if (doFiniteArea)
|
||||
if (doFiniteArea && !areaRegionNames.empty())
|
||||
{
|
||||
using reportFields = foamToVtkReportFields;
|
||||
|
||||
autoPtr<faMesh> faMeshPtr;
|
||||
// The (region) polyMesh being used. No subsetting possible
|
||||
const auto& basePolyMesh = meshProxy.baseMesh();
|
||||
|
||||
const label nAreaFields = faObjects.count(Foam::fieldTypes::is_area);
|
||||
|
||||
if (nAreaFields || withMeshIds)
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
faMeshPtr = faMesh::TryNew(meshProxy.baseMesh());
|
||||
}
|
||||
const bool isDefaultRegion(polyMesh::regionName(areaName).empty());
|
||||
|
||||
if (faMeshPtr && (nAreaFields || withMeshIds))
|
||||
{
|
||||
const faMesh& areaMesh = faMeshPtr();
|
||||
// CAUTION
|
||||
// If we want to have constant access to the HashTable:
|
||||
//
|
||||
// (SEGFAULT)
|
||||
// const auto& faObjs = faObjects.lookup(areaName, IOobjectList());
|
||||
//
|
||||
// Use an empty fallback to avoid binding to a temporary:
|
||||
//
|
||||
// const IOobjectList emptyObjectList;
|
||||
// const auto& faObjs = faObjects.lookup(areaName, emptyObjectList);
|
||||
|
||||
reportFields::area(Info, faObjects);
|
||||
// Since we do not need the area fields afterwards,
|
||||
// just move them out from the HashTable
|
||||
|
||||
IOobjectList faObjs;
|
||||
if (auto iter = faObjects.find(areaName); iter.good())
|
||||
{
|
||||
faObjs = std::move(iter.val());
|
||||
}
|
||||
|
||||
const label nAreaFields = faObjs.count(Foam::fieldTypes::is_area);
|
||||
|
||||
autoPtr<faMesh> faMeshPtr;
|
||||
|
||||
if (nAreaFields || withMeshIds)
|
||||
{
|
||||
faMeshPtr = faMesh::TryNew(areaName, basePolyMesh);
|
||||
}
|
||||
|
||||
if (!faMeshPtr)
|
||||
{
|
||||
if (!isDefaultRegion)
|
||||
{
|
||||
// Report any area region specified but missing
|
||||
// - silently ignore region0
|
||||
Info<< "No area-mesh [" << polyMesh::regionName(areaName)
|
||||
<< "] on volume-region ["
|
||||
<< basePolyMesh.regionName() << "]" << endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const auto& areaMesh = faMeshPtr();
|
||||
|
||||
Info<< "Using area-mesh [" << polyMesh::regionName(areaName)
|
||||
<< "] on volume-region ["
|
||||
<< basePolyMesh.regionName() << "]" << endl;
|
||||
|
||||
|
||||
reportFields::area(Info, faObjs);
|
||||
|
||||
const auto& pp = faMeshPtr->patch();
|
||||
|
||||
@ -49,7 +91,12 @@ if (doFiniteArea)
|
||||
writeOpts,
|
||||
(
|
||||
outputDir/regionDir/"finite-area"
|
||||
/ "finiteArea" + timeDesc
|
||||
/ (
|
||||
isDefaultRegion
|
||||
? fileName("finiteArea")
|
||||
: fileName(areaName/areaName)
|
||||
)
|
||||
+ timeDesc
|
||||
),
|
||||
UPstream::parRun()
|
||||
);
|
||||
@ -96,7 +143,7 @@ if (doFiniteArea)
|
||||
(
|
||||
writer,
|
||||
areaMesh,
|
||||
faObjects,
|
||||
faObjs,
|
||||
true // syncPar
|
||||
);
|
||||
|
||||
|
||||
@ -135,13 +135,13 @@ Note
|
||||
#include "emptyPolyPatch.H"
|
||||
#include "volPointInterpolation.H"
|
||||
#include "faceZoneMesh.H"
|
||||
#include "faMesh.H"
|
||||
#include "areaFields.H"
|
||||
#include "fvMeshSubsetProxy.H"
|
||||
#include "faceSet.H"
|
||||
#include "pointSet.H"
|
||||
#include "HashOps.H"
|
||||
#include "regionProperties.H"
|
||||
#include "stringListOps.H" // For stringListOps::findMatching()
|
||||
|
||||
#include "Cloud.H"
|
||||
#include "readFields.H"
|
||||
@ -434,6 +434,7 @@ int main(int argc, char *argv[])
|
||||
argList::addOptionCompat("one-boundary", {"allPatches", 1806});
|
||||
|
||||
#include "addAllRegionOptions.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
argList::addOption
|
||||
(
|
||||
@ -479,8 +480,14 @@ int main(int argc, char *argv[])
|
||||
"Directory name for VTK output (default: 'VTK')"
|
||||
);
|
||||
|
||||
// Prevent volume BCs from triggering finite-area
|
||||
regionModels::allowFaModels(false);
|
||||
|
||||
#include "setRootCase.H"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Configuration
|
||||
|
||||
/// const int optVerbose = args.verbose();
|
||||
const bool decomposePoly = args.found("poly-decomp");
|
||||
const bool doBoundary = !args.found("no-boundary");
|
||||
@ -624,6 +631,16 @@ int main(int argc, char *argv[])
|
||||
// Handle -allRegions, -regions, -region
|
||||
#include "getAllRegionOptions.H"
|
||||
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
if (!doFiniteArea)
|
||||
{
|
||||
areaRegionNames.clear(); // For consistency
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Names for sets and zones
|
||||
word cellSelectionName;
|
||||
word faceSetName;
|
||||
@ -771,8 +788,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// fvMesh fields
|
||||
IOobjectList objects;
|
||||
IOobjectList faObjects;
|
||||
|
||||
// faMesh fields (multiple finite-area regions per volume region)
|
||||
HashTable<IOobjectList> faObjects;
|
||||
|
||||
if (doConvertFields)
|
||||
{
|
||||
@ -780,33 +800,51 @@ int main(int argc, char *argv[])
|
||||
objects =
|
||||
IOobjectList(meshProxy.baseMesh(), runTime.timeName());
|
||||
|
||||
// List of area mesh objects (assuming single region)
|
||||
faObjects =
|
||||
IOobjectList
|
||||
(
|
||||
runTime,
|
||||
runTime.timeName(),
|
||||
faMesh::dbDir(meshProxy.baseMesh(), word::null),
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
if (fieldSelector)
|
||||
{
|
||||
objects.filterObjects(fieldSelector);
|
||||
faObjects.filterObjects(fieldSelector);
|
||||
}
|
||||
|
||||
// Remove "*_0" restart fields
|
||||
objects.prune_0();
|
||||
faObjects.prune_0();
|
||||
|
||||
if (!doPointValues)
|
||||
{
|
||||
// Prune point fields if disabled
|
||||
objects.filterClasses(Foam::fieldTypes::is_point, true);
|
||||
}
|
||||
|
||||
|
||||
// Lists of finite-area fields
|
||||
faObjects.reserve(areaRegionNames.size());
|
||||
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
// The finite-area objects for given area region.
|
||||
// Add as method to faMeshesRegistry?
|
||||
|
||||
IOobjectList objs
|
||||
(
|
||||
faMesh::Registry(meshProxy.baseMesh()),
|
||||
runTime.timeName(),
|
||||
polyMesh::regionName(areaName),
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
if (fieldSelector)
|
||||
{
|
||||
objs.filterObjects(fieldSelector);
|
||||
}
|
||||
// Remove "*_0" restart fields
|
||||
objs.prune_0();
|
||||
|
||||
if (!objs.empty())
|
||||
{
|
||||
faObjects.emplace_set(areaName, std::move(objs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (processorFieldsOnly)
|
||||
{
|
||||
// Processor-patches only and continue
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/finiteArea/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude
|
||||
-I$(LIB_SRC)/finiteArea/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lmeshTools \
|
||||
-lfiniteVolume \
|
||||
-lfiniteArea \
|
||||
-lmeshTools \
|
||||
-lgenericPatchFields
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2022-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2022-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -47,6 +47,7 @@ Description
|
||||
#include "areaFields.H"
|
||||
#include "coupledFvPatch.H"
|
||||
#include "coupledFaPatch.H"
|
||||
#include "regionProperties.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
@ -86,17 +87,18 @@ bool consumeUnusedType(const fieldDescription& fieldDesc, Istream& is)
|
||||
//? typedef GeometricField<Type, faePatchField, areaMesh> fieldType3;
|
||||
//? typedef GeometricField<Type, fvsPatchField, volMesh> fieldType4;
|
||||
|
||||
if
|
||||
const bool isExpectedType
|
||||
(
|
||||
fieldDesc.type() == fieldType1::typeName
|
||||
|| fieldDesc.type() == fieldType2::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (isExpectedType)
|
||||
{
|
||||
(void) pTraits<Type>(is);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return isExpectedType;
|
||||
}
|
||||
|
||||
|
||||
@ -122,13 +124,18 @@ bool setCellFieldType
|
||||
(
|
||||
const fieldDescription& fieldDesc,
|
||||
const fvMesh& mesh,
|
||||
const labelList& selectedCells,
|
||||
const labelUList& selectedCells,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
|
||||
|
||||
if (fieldDesc.type() != fieldType::typeName)
|
||||
const bool isExpectedType
|
||||
(
|
||||
fieldDesc.type() == fieldType::typeName
|
||||
);
|
||||
|
||||
if (!isExpectedType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -143,7 +150,9 @@ bool setCellFieldType
|
||||
fieldDesc.name(),
|
||||
mesh.thisDb().time().timeName(),
|
||||
mesh.thisDb(),
|
||||
IOobject::MUST_READ
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
bool found = fieldHeader.typeHeaderOk<fieldType>(true);
|
||||
@ -151,13 +160,8 @@ bool setCellFieldType
|
||||
if (!found)
|
||||
{
|
||||
// Fallback to "constant" directory
|
||||
fieldHeader = IOobject
|
||||
(
|
||||
fieldDesc.name(),
|
||||
mesh.thisDb().time().constant(),
|
||||
mesh.thisDb(),
|
||||
IOobject::MUST_READ
|
||||
);
|
||||
fieldHeader.resetHeader();
|
||||
fieldHeader.instance() = mesh.thisDb().time().constant();
|
||||
found = fieldHeader.typeHeaderOk<fieldType>(true);
|
||||
}
|
||||
|
||||
@ -171,7 +175,7 @@ bool setCellFieldType
|
||||
|
||||
fieldType field(fieldHeader, mesh, false);
|
||||
|
||||
if (isNull(selectedCells) || selectedCells.size() == field.size())
|
||||
if (isNull(selectedCells) || (selectedCells.size() == field.size()))
|
||||
{
|
||||
field.primitiveFieldRef() = fieldValue;
|
||||
}
|
||||
@ -204,7 +208,7 @@ bool setCellFieldType
|
||||
<< "Field " << fieldDesc.name() << " not found" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
return isExpectedType;
|
||||
}
|
||||
|
||||
|
||||
@ -216,13 +220,18 @@ bool setAreaFieldType
|
||||
(
|
||||
const fieldDescription& fieldDesc,
|
||||
const faMesh& mesh,
|
||||
const labelList& selectedFaces,
|
||||
const labelUList& selectedFaces,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, faPatchField, areaMesh> fieldType;
|
||||
|
||||
if (fieldDesc.type() != fieldType::typeName)
|
||||
const bool isExpectedType
|
||||
(
|
||||
fieldDesc.type() == fieldType::typeName
|
||||
);
|
||||
|
||||
if (!isExpectedType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -237,7 +246,9 @@ bool setAreaFieldType
|
||||
fieldDesc.name(),
|
||||
mesh.thisDb().time().timeName(),
|
||||
mesh.thisDb(),
|
||||
IOobject::MUST_READ
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
bool found = fieldHeader.typeHeaderOk<fieldType>(true);
|
||||
@ -245,13 +256,8 @@ bool setAreaFieldType
|
||||
if (!found)
|
||||
{
|
||||
// Fallback to "constant" directory
|
||||
fieldHeader = IOobject
|
||||
(
|
||||
fieldDesc.name(),
|
||||
mesh.thisDb().time().constant(),
|
||||
mesh.thisDb(),
|
||||
IOobject::MUST_READ
|
||||
);
|
||||
fieldHeader.resetHeader();
|
||||
fieldHeader.instance() = mesh.thisDb().time().constant(),
|
||||
found = fieldHeader.typeHeaderOk<fieldType>(true);
|
||||
}
|
||||
|
||||
@ -292,7 +298,7 @@ bool setAreaFieldType
|
||||
<< "Field " << fieldDesc.name() << " not found" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
return isExpectedType;
|
||||
}
|
||||
|
||||
|
||||
@ -304,13 +310,18 @@ bool setFaceFieldType
|
||||
(
|
||||
const fieldDescription& fieldDesc,
|
||||
const fvMesh& mesh,
|
||||
const labelList& selectedFaces,
|
||||
const labelUList& selectedFaces,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
|
||||
|
||||
if (fieldDesc.type() != fieldType::typeName)
|
||||
const bool isExpectedType
|
||||
(
|
||||
fieldDesc.type() == fieldType::typeName
|
||||
);
|
||||
|
||||
if (!isExpectedType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -325,7 +336,9 @@ bool setFaceFieldType
|
||||
fieldDesc.name(),
|
||||
mesh.thisDb().time().timeName(),
|
||||
mesh.thisDb(),
|
||||
IOobject::MUST_READ
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER
|
||||
);
|
||||
|
||||
bool found = fieldHeader.typeHeaderOk<fieldType>(true);
|
||||
@ -333,13 +346,8 @@ bool setFaceFieldType
|
||||
if (!found)
|
||||
{
|
||||
// Fallback to "constant" directory
|
||||
fieldHeader = IOobject
|
||||
(
|
||||
fieldDesc.name(),
|
||||
mesh.thisDb().time().constant(),
|
||||
mesh.thisDb(),
|
||||
IOobject::MUST_READ
|
||||
);
|
||||
fieldHeader.resetHeader();
|
||||
fieldHeader.instance() = mesh.thisDb().time().constant();
|
||||
found = fieldHeader.typeHeaderOk<fieldType>(true);
|
||||
}
|
||||
|
||||
@ -355,15 +363,14 @@ bool setFaceFieldType
|
||||
|
||||
// Create flat list of selected faces and their value.
|
||||
Field<Type> allBoundaryValues(mesh.nBoundaryFaces());
|
||||
forAll(field.boundaryField(), patchi)
|
||||
for (const auto& pfld : field.boundaryField())
|
||||
{
|
||||
SubField<Type>
|
||||
(
|
||||
allBoundaryValues,
|
||||
field.boundaryField()[patchi].size(),
|
||||
field.boundaryField()[patchi].patch().start()
|
||||
- mesh.nInternalFaces()
|
||||
) = field.boundaryField()[patchi];
|
||||
pfld.size(),
|
||||
pfld.patch().offset()
|
||||
) = pfld;
|
||||
}
|
||||
|
||||
// Override
|
||||
@ -424,8 +431,7 @@ bool setFaceFieldType
|
||||
(
|
||||
allBoundaryValues,
|
||||
fieldBf[patchi].size(),
|
||||
fieldBf[patchi].patch().start()
|
||||
- mesh.nInternalFaces()
|
||||
fieldBf[patchi].patch().offset()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -445,7 +451,7 @@ bool setFaceFieldType
|
||||
<< "Field " << fieldDesc.name() << " not found" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
return isExpectedType;
|
||||
}
|
||||
|
||||
|
||||
@ -460,7 +466,7 @@ struct setCellField
|
||||
(
|
||||
const fieldDescription& fieldDesc,
|
||||
const fvMesh& m,
|
||||
const labelList& selectedCells,
|
||||
const labelUList& selectedCells,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
@ -477,11 +483,11 @@ struct setCellField
|
||||
class iNew
|
||||
{
|
||||
const fvMesh& mesh_;
|
||||
const labelList& selected_;
|
||||
const labelUList& selected_;
|
||||
|
||||
public:
|
||||
|
||||
iNew(const fvMesh& mesh, const labelList& selectedCells)
|
||||
iNew(const fvMesh& mesh, const labelUList& selectedCells) noexcept
|
||||
:
|
||||
mesh_(mesh),
|
||||
selected_(selectedCells)
|
||||
@ -528,7 +534,7 @@ struct setFaceField
|
||||
(
|
||||
const fieldDescription& fieldDesc,
|
||||
const fvMesh& m,
|
||||
const labelList& selectedFaces,
|
||||
const labelUList& selectedFaces,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
@ -545,11 +551,11 @@ struct setFaceField
|
||||
class iNew
|
||||
{
|
||||
const fvMesh& mesh_;
|
||||
const labelList& selected_;
|
||||
const labelUList& selected_;
|
||||
|
||||
public:
|
||||
|
||||
iNew(const fvMesh& mesh, const labelList& selectedFaces)
|
||||
iNew(const fvMesh& mesh, const labelUList& selectedFaces) noexcept
|
||||
:
|
||||
mesh_(mesh),
|
||||
selected_(selectedFaces)
|
||||
@ -596,7 +602,7 @@ struct setAreaField
|
||||
(
|
||||
const fieldDescription& fieldDesc,
|
||||
const faMesh& m,
|
||||
const labelList& selectedFaces,
|
||||
const labelUList& selectedFaces,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
@ -613,11 +619,11 @@ struct setAreaField
|
||||
class iNew
|
||||
{
|
||||
const faMesh& mesh_;
|
||||
const labelList& selected_;
|
||||
const labelUList& selected_;
|
||||
|
||||
public:
|
||||
|
||||
iNew(const faMesh& mesh, const labelList& selectedFaces)
|
||||
iNew(const faMesh& mesh, const labelUList& selectedFaces) noexcept
|
||||
:
|
||||
mesh_(mesh),
|
||||
selected_(selectedFaces)
|
||||
@ -675,6 +681,7 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
#include "addRegionOption.H"
|
||||
#include "addAllFaRegionOptions.H"
|
||||
|
||||
// -------------------------
|
||||
|
||||
@ -686,15 +693,59 @@ int main(int argc, char *argv[])
|
||||
|
||||
#include "createNamedMesh.H"
|
||||
|
||||
autoPtr<faMesh> faMeshPtr;
|
||||
// Handle -all-area-regions, -area-regions, -area-region
|
||||
#include "getAllFaRegionOptions.H"
|
||||
|
||||
if (!args.found("no-finite-area"))
|
||||
if (args.found("no-finite-area"))
|
||||
{
|
||||
faMeshPtr = faMesh::TryNew(mesh);
|
||||
areaRegionNames.clear(); // For consistency
|
||||
}
|
||||
if (faMeshPtr)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
PtrList<faMesh> faMeshes;
|
||||
|
||||
// Setup all area meshes on this region
|
||||
if (!areaRegionNames.empty()) // ie, !args.found("no-finite-area")
|
||||
{
|
||||
Info<< "Detected finite-area mesh" << nl;
|
||||
faMeshes.resize(areaRegionNames.size());
|
||||
|
||||
label nGoodRegions(0);
|
||||
|
||||
for (const word& areaName : areaRegionNames)
|
||||
{
|
||||
autoPtr<faMesh> faMeshPtr = faMesh::TryNew(areaName, mesh);
|
||||
|
||||
if (faMeshPtr)
|
||||
{
|
||||
faMeshes.set(nGoodRegions++, std::move(faMeshPtr));
|
||||
}
|
||||
}
|
||||
|
||||
faMeshes.resize(nGoodRegions);
|
||||
}
|
||||
|
||||
if (faMeshes.size() == 1)
|
||||
{
|
||||
Info<< "Using finite-area mesh";
|
||||
if
|
||||
(
|
||||
const word& name = polyMesh::regionName(faMeshes[0].name());
|
||||
!name.empty()
|
||||
)
|
||||
{
|
||||
Info<< " [" << name << "]";
|
||||
}
|
||||
Info<< nl;
|
||||
}
|
||||
else if (faMeshes.size() > 1)
|
||||
{
|
||||
Info<< "Detected finite-area meshes:";
|
||||
for (const faMesh& areaMesh : faMeshes)
|
||||
{
|
||||
Info<< " [" << areaMesh.name() << "]";
|
||||
}
|
||||
Info<< nl;
|
||||
}
|
||||
|
||||
const word dictName("setFieldsDict");
|
||||
@ -712,37 +763,45 @@ int main(int argc, char *argv[])
|
||||
|
||||
|
||||
// Default field values
|
||||
if
|
||||
(
|
||||
const auto* eptr
|
||||
= setFieldsDict.findEntry("defaultFieldValues", keyType::LITERAL)
|
||||
)
|
||||
{
|
||||
const entry* eptr =
|
||||
setFieldsDict.findEntry("defaultFieldValues", keyType::LITERAL);
|
||||
ITstream& is = eptr->stream();
|
||||
|
||||
if (eptr)
|
||||
Info<< "Setting volume field default values" << endl;
|
||||
|
||||
PtrList<setCellField> defaultFieldValues
|
||||
(
|
||||
is,
|
||||
setCellField::iNew(mesh, labelList::null())
|
||||
);
|
||||
|
||||
for (const faMesh& areaMesh : faMeshes)
|
||||
{
|
||||
ITstream& is = eptr->stream();
|
||||
Info<< "Setting area field default values";
|
||||
|
||||
Info<< "Setting volume field default values" << endl;
|
||||
|
||||
PtrList<setCellField> defaultFieldValues
|
||||
if
|
||||
(
|
||||
is,
|
||||
setCellField::iNew(mesh, labelList::null())
|
||||
);
|
||||
|
||||
if (faMeshPtr)
|
||||
const word& name = polyMesh::regionName(areaMesh.name());
|
||||
!name.empty()
|
||||
)
|
||||
{
|
||||
const faMesh& areaMesh = faMeshPtr();
|
||||
is.rewind();
|
||||
|
||||
Info<< "Setting area field default values" << endl;
|
||||
|
||||
PtrList<setAreaField> defaultFieldValues
|
||||
(
|
||||
is,
|
||||
setAreaField::iNew(areaMesh, labelList::null())
|
||||
);
|
||||
Info<< " [" << name << "]";
|
||||
}
|
||||
Info<< endl;
|
||||
|
||||
is.rewind();
|
||||
|
||||
PtrList<setAreaField> defaultAreaFieldValues
|
||||
(
|
||||
is,
|
||||
setAreaField::iNew(areaMesh, labelList::null())
|
||||
);
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
|
||||
@ -768,11 +827,15 @@ int main(int argc, char *argv[])
|
||||
|
||||
labelList selectedCells(subset.sortedToc());
|
||||
|
||||
Info<< " Selected "
|
||||
<< returnReduce(selectedCells.size(), sumOp<label>())
|
||||
<< '/'
|
||||
<< returnReduce(mesh.nCells(), sumOp<label>())
|
||||
<< " cells" << nl;
|
||||
{
|
||||
FixedList<label, 2> stats;
|
||||
stats[0] = selectedCells.size();
|
||||
stats[1] = mesh.nCells();
|
||||
reduce(stats, sumOp<label>());
|
||||
|
||||
Info<< " Selected " << stats[0] << '/' << stats[1]
|
||||
<< " cells" << nl;
|
||||
}
|
||||
|
||||
ITstream& is = region.dict().lookup("fieldValues");
|
||||
|
||||
@ -806,10 +869,8 @@ int main(int argc, char *argv[])
|
||||
setFaceField::iNew(mesh, selectedFaces)
|
||||
);
|
||||
|
||||
if (faMeshPtr)
|
||||
for (const faMesh& areaMesh : faMeshes)
|
||||
{
|
||||
const faMesh& areaMesh = faMeshPtr();
|
||||
|
||||
const labelUList& faceLabels = areaMesh.faceLabels();
|
||||
|
||||
// Transcribe from mesh faces to finite-area addressing
|
||||
@ -828,11 +889,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
areaFaces.resize(nUsed);
|
||||
|
||||
Info<< " Selected "
|
||||
<< returnReduce(areaFaces.size(), sumOp<label>())
|
||||
<< '/'
|
||||
<< returnReduce(faceLabels.size(), sumOp<label>())
|
||||
<< " area faces" << nl;
|
||||
{
|
||||
FixedList<label, 2> stats;
|
||||
stats[0] = areaFaces.size();
|
||||
stats[1] = faceLabels.size();
|
||||
reduce(stats, sumOp<label>());
|
||||
|
||||
Info<< " Selected " << stats[0] << '/' << stats[1]
|
||||
<< " area faces for " << areaMesh.name() << endl;
|
||||
}
|
||||
|
||||
is.rewind();
|
||||
|
||||
|
||||
138
bin/foamCleanFaMesh
Executable file
138
bin/foamCleanFaMesh
Executable file
@ -0,0 +1,138 @@
|
||||
#!/bin/sh
|
||||
#------------------------------------------------------------------------------
|
||||
# ========= |
|
||||
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
# \\ / O peration |
|
||||
# \\ / A nd | www.openfoam.com
|
||||
# \\/ M anipulation |
|
||||
#-------------------------------------------------------------------------------
|
||||
# Copyright (C) 2011 OpenFOAM Foundation
|
||||
# Copyright (C) 2025 OpenCFD Ltd.
|
||||
#------------------------------------------------------------------------------
|
||||
# License
|
||||
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
#
|
||||
# Script
|
||||
# foamCleanFaMesh
|
||||
#
|
||||
# Description
|
||||
# Remove the contents of the constant/finite-area/faMesh directory
|
||||
# as per the Foam::faMesh::removeFiles() method.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
usage() {
|
||||
exec 1>&2
|
||||
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
|
||||
cat <<USAGE
|
||||
|
||||
Usage: ${0##*/} [OPTION]
|
||||
options:
|
||||
-case <dir> case directory, default is the cwd
|
||||
-area-region <name> area-mesh region
|
||||
-dry-run | -n report actions but do not remove
|
||||
-help print the usage
|
||||
|
||||
Remove the contents of the constant/finite-area/faMesh directory as per the
|
||||
Foam::faMesh::removeFiles() method.
|
||||
|
||||
USAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Parse options
|
||||
unset caseDir areaRegion optDryRun
|
||||
|
||||
while [ "$#" -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-h | -help*)
|
||||
usage
|
||||
;;
|
||||
-dry-run | -n)
|
||||
optDryRun="(dry-run) "
|
||||
;;
|
||||
|
||||
-case=*)
|
||||
caseDir="${1#*=}"
|
||||
;;
|
||||
|
||||
-case)
|
||||
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
|
||||
cd "$2" 2>/dev/null || usage "directory does not exist: '$2'"
|
||||
caseDir=$2
|
||||
shift
|
||||
;;
|
||||
|
||||
-area-region)
|
||||
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
|
||||
areaRegion=$2
|
||||
shift
|
||||
;;
|
||||
|
||||
(*)
|
||||
usage "unknown option/argument: '$*'"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Remove files (mesh etc)
|
||||
# also remove .gz versions of the same files
|
||||
|
||||
removeFiles()
|
||||
{
|
||||
local directory="$1"
|
||||
|
||||
for i in \
|
||||
faceLabels \
|
||||
faBoundary \
|
||||
;
|
||||
do
|
||||
if [ -n "$optDryRun" ]
|
||||
then
|
||||
echo "${optDryRun} rm -rf $directory/{$i,$i.gz}"
|
||||
else
|
||||
rm -rf -- "$directory/$i" "$directory/$i.gz"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
meshDir="constant/finite-area/${areaRegion}${areaRegion:+/}faMesh"
|
||||
|
||||
if [ -d "$meshDir" ]
|
||||
then
|
||||
# [OK] has constant/finite-areaRegion/<region>/faMesh
|
||||
:
|
||||
|
||||
elif [ -n "$caseDir" ]
|
||||
then
|
||||
# Specified -case, so no extra magic...
|
||||
echo "Error: no <$meshDir> in $caseDir" 1>&2
|
||||
exit 1
|
||||
|
||||
else
|
||||
# Try some other combinations
|
||||
other="${meshDir#constant/}"
|
||||
|
||||
if [ -d "$other" ]
|
||||
then
|
||||
# Probably already within constant/
|
||||
meshDir="$other}"
|
||||
elif [ "${PWD##*/}" = faMesh ] && [ -z "$areaRegion" ]
|
||||
then
|
||||
# Apparently already within faMesh/
|
||||
meshDir=.
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
echo "Cleaning ${caseDir:-.}/$meshDir" 1>&2
|
||||
|
||||
removeFiles "$meshDir"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@ -7,7 +7,7 @@
|
||||
# \\/ M anipulation |
|
||||
#-------------------------------------------------------------------------------
|
||||
# Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
# Copyright (C) 2022 OpenCFD Ltd.
|
||||
# Copyright (C) 2022,2025 OpenCFD Ltd.
|
||||
#------------------------------------------------------------------------------
|
||||
# License
|
||||
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
@ -27,9 +27,10 @@ usage() {
|
||||
|
||||
Usage: ${0##*/} [OPTION]
|
||||
options:
|
||||
-case <dir> specify alternative case directory, default is the cwd
|
||||
-region <name> specify alternative mesh region
|
||||
-help print the usage
|
||||
-case <dir> case directory, default is the cwd
|
||||
-region <name> mesh region
|
||||
-dry-run | -n report actions but do not remove
|
||||
-help print the usage
|
||||
|
||||
Remove the contents of the constant/polyMesh directory as per the
|
||||
Foam::polyMesh::removeFiles() method.
|
||||
@ -38,58 +39,101 @@ USAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
unset caseDir regionName
|
||||
#------------------------------------------------------------------------------
|
||||
# Parse options
|
||||
unset caseDir regionName optDryRun
|
||||
|
||||
# Parse a single option
|
||||
while [ "$#" -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-h | -help*)
|
||||
usage
|
||||
;;
|
||||
-dry-run | -n)
|
||||
optDryRun="(dry-run) "
|
||||
;;
|
||||
|
||||
-case=*)
|
||||
caseDir="${1#*=}"
|
||||
;;
|
||||
|
||||
-case)
|
||||
caseDir="$2"
|
||||
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
|
||||
cd "$2" 2>/dev/null || usage "directory does not exist: '$2'"
|
||||
caseDir=$2
|
||||
shift 2
|
||||
shift
|
||||
;;
|
||||
|
||||
-region)
|
||||
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
|
||||
regionName=$2
|
||||
shift 2
|
||||
regionName="$2"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
|
||||
(*)
|
||||
usage "unknown option/argument: '$*'"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
meshDir=polyMesh
|
||||
if [ -n "$regionName" ]
|
||||
then
|
||||
meshDir="$regionName/$meshDir"
|
||||
fi
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# If -case was specified: insist upon 'constant/polyMesh'
|
||||
if [ -n "$caseDir" ]
|
||||
# Remove files (mesh itself, modifiers, snappyHexMesh ones) and subdirectories
|
||||
# also remove .gz versions of the same files
|
||||
|
||||
removeFiles()
|
||||
{
|
||||
local directory="$1"
|
||||
|
||||
for i in \
|
||||
points faces \
|
||||
owner neighbour \
|
||||
boundary \
|
||||
cells \
|
||||
cellZones faceZones pointZones \
|
||||
meshModifiers \
|
||||
parallelData \
|
||||
sets \
|
||||
cellLevel pointLevel \
|
||||
level0Edge \
|
||||
refinementHistory \
|
||||
surfaceIndex \
|
||||
;
|
||||
do
|
||||
if [ -n "$optDryRun" ]
|
||||
then
|
||||
echo "${optDryRun} rm -rf $directory/{$i,$i.gz}"
|
||||
else
|
||||
rm -rf -- "$directory/$i" "$directory/$i.gz"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
meshDir="constant/${regionName}${regionName:+/}polyMesh"
|
||||
|
||||
if [ -d "$meshDir" ]
|
||||
then
|
||||
if [ -d constant/"$meshDir" ]
|
||||
then
|
||||
# Use constant/polyMesh
|
||||
meshDir=constant/"$meshDir"
|
||||
else
|
||||
echo "Error: no 'constant/$meshDir' in $caseDir" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
# [OK] has constant/<region>/polyMesh
|
||||
:
|
||||
|
||||
elif [ -n "$caseDir" ]
|
||||
then
|
||||
# Specified -case, so no extra magic...
|
||||
echo "Error: no <$meshDir> in $caseDir" 1>&2
|
||||
exit 1
|
||||
|
||||
else
|
||||
if [ -d constant/"$meshDir" ]
|
||||
# Try some other combinations
|
||||
other="${meshDir#constant/}"
|
||||
|
||||
if [ -d "$other" ]
|
||||
then
|
||||
# Use constant/polyMesh
|
||||
meshDir=constant/"$meshDir"
|
||||
elif [ -d "$meshDir" ]
|
||||
then
|
||||
# Likely already in constant/ - do not adjust anything
|
||||
:
|
||||
# Probably already within constant/
|
||||
meshDir="$other}"
|
||||
elif [ "${PWD##*/}" = polyMesh ] && [ -z "$regionName" ]
|
||||
then
|
||||
# Apparently already within polyMesh/
|
||||
@ -98,31 +142,8 @@ else
|
||||
fi
|
||||
|
||||
|
||||
# Remove files (mesh itself, modifiers, snappyHexMesh ones) and subdirectories
|
||||
# also remove .gz versions of the same files
|
||||
echo "Cleaning ${caseDir:-.}/$meshDir" 1>&2
|
||||
|
||||
for i in \
|
||||
points \
|
||||
faces \
|
||||
owner \
|
||||
neighbour \
|
||||
cells \
|
||||
boundary \
|
||||
pointZones \
|
||||
faceZones \
|
||||
cellZones \
|
||||
meshModifiers \
|
||||
parallelData \
|
||||
sets \
|
||||
cellLevel \
|
||||
pointLevel \
|
||||
level0Edge \
|
||||
refinementHistory \
|
||||
surfaceIndex \
|
||||
;
|
||||
do
|
||||
rm -rf "$meshDir/$i" "$meshDir/$i.gz"
|
||||
done
|
||||
removeFiles "$meshDir"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -108,54 +108,116 @@ cleanPostProcessing()
|
||||
}
|
||||
|
||||
|
||||
# ---------------
|
||||
# Remove constant/finite-area/faMesh or constant/finite-area/{region}/faMesh
|
||||
#
|
||||
# Accepts following options:
|
||||
# -region <name> The region name
|
||||
# -- End of options
|
||||
# ---------------
|
||||
cleanFaMesh()
|
||||
{
|
||||
if [ -e constant/finite-area/faMesh ]
|
||||
local region
|
||||
|
||||
# Parse options
|
||||
while [ "$#" -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
('') ;; # Ignore empty option
|
||||
(--) shift; break ;; # Stop option parsing
|
||||
|
||||
(-region) region="$2"; shift ;;
|
||||
(*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# safety
|
||||
if [ "$region" = "--" ]; then unset region; fi
|
||||
|
||||
local meshDir="constant/finite-area/${region}${region:+/}faMesh"
|
||||
|
||||
if [ -e "$meshDir" ]
|
||||
then
|
||||
rm -rf constant/finite-area/faMesh
|
||||
[ -n "$region" ] && echo "Clearing $meshDir" 1>&2
|
||||
rm -rf -- "$meshDir"
|
||||
fi
|
||||
if [ -e constant/faMesh ]
|
||||
|
||||
# Legacy location <constant/faMesh>
|
||||
# - may still have remnant <constant/faMesh/faMeshDefinition>
|
||||
|
||||
meshDir="constant/faMesh"
|
||||
if [ -e "$meshDir" ] && [ -z "$region" ]
|
||||
then
|
||||
if [ -e constant/faMesh/faMeshDefinition ]
|
||||
if [ -e "$meshDir"/faMeshDefinition ]
|
||||
then
|
||||
# Old constant/faMesh location for faMeshDefinition still in use:
|
||||
# - warn but don't remove anything
|
||||
# VERY OLD LOCATION
|
||||
echo
|
||||
echo "Warning: not removing constant/faMesh/"
|
||||
echo "WARNING: not removing $meshDir/"
|
||||
echo " It contains a 'faMeshDefinition' file"
|
||||
echo " Please relocate file(s) to system/ !!"
|
||||
echo " Please relocate file(s) to system/finite-area/ !!"
|
||||
echo
|
||||
else
|
||||
# Can remove constant/faMesh/ entirely (no faMeshDefinition)
|
||||
rm -rf constant/faMesh
|
||||
echo "Clearing $meshDir" 1>&2
|
||||
rm -rf -- "$meshDir"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# ---------------
|
||||
# Remove constant/polyMesh or constant/<region>/polyMesh
|
||||
#
|
||||
# Accepts following options:
|
||||
# -region <name> The region name
|
||||
# -- End of options
|
||||
# ---------------
|
||||
cleanPolyMesh()
|
||||
{
|
||||
if [ -e constant/polyMesh ]
|
||||
local region
|
||||
|
||||
# Parse options
|
||||
while [ "$#" -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
('') ;; # Ignore empty option
|
||||
(--) shift; break ;; # Stop option parsing
|
||||
|
||||
(-region) region="$2"; shift ;;
|
||||
(*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# safety
|
||||
if [ "$region" = "--" ]; then unset region; fi
|
||||
|
||||
local meshDir="constant/${region}${region:+/}polyMesh"
|
||||
|
||||
if [ -e "$meshDir" ]
|
||||
then
|
||||
if [ -e constant/polyMesh/blockMeshDict ] \
|
||||
|| [ -e constant/polyMesh/blockMeshDict.m4 ]
|
||||
[ -n "$region" ] && echo "Clearing $meshDir" 1>&2
|
||||
|
||||
if [ -e "$meshDir"/blockMeshDict ] \
|
||||
|| [ -e "$meshDir"/blockMeshDict.m4 ]
|
||||
then
|
||||
# Old constant/polyMesh location for blockMeshDict still in use:
|
||||
# - warn but don't remove anything
|
||||
# VERY OLD LOCATION
|
||||
echo
|
||||
echo "Warning: not removing constant/polyMesh/"
|
||||
echo "WARNING: not removing $meshDir/"
|
||||
echo " It contains a 'blockMeshDict' or 'blockMeshDict.m4' file"
|
||||
echo " Please relocate file(s) to system/ !!"
|
||||
echo
|
||||
else
|
||||
# Can remove constant/polyMesh/ entirely (no blockMeshDict)
|
||||
rm -rf constant/polyMesh
|
||||
rm -rf -- "$meshDir"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -e system/blockMeshDict.m4 ]
|
||||
meshDir="system${region:+/}${region}"
|
||||
if [ -e "$meshDir"/blockMeshDict.m4 ]
|
||||
then
|
||||
rm -f system/blockMeshDict
|
||||
rm -f -- "$meshDir"/blockMeshDict
|
||||
fi
|
||||
}
|
||||
|
||||
@ -212,7 +274,7 @@ cleanCase0()
|
||||
removeCase()
|
||||
{
|
||||
echo "Removing case ${1:-unknown}"
|
||||
[ "$#" -ge 1 ] && rm -rf "$1"
|
||||
[ "$#" -ge 1 ] && rm -rf -- "$1"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -517,9 +517,11 @@ cloneParallelCase()
|
||||
}
|
||||
|
||||
|
||||
# ---------------
|
||||
# If 0.orig/ exists, copy (overwrite) into 0/ [ie, serial case]
|
||||
# * -processor : copy into processor directories instead
|
||||
# * -all : copy into serial and processor directories
|
||||
# ---------------
|
||||
restore0Dir()
|
||||
{
|
||||
if [ ! -d 0.orig ]
|
||||
@ -553,4 +555,61 @@ restore0Dir()
|
||||
}
|
||||
|
||||
|
||||
# ---------------
|
||||
# Helper routine to remove specified fields from the 0/ directory.
|
||||
# Often used in combination with foamListRegions.
|
||||
#
|
||||
# Accepts following options:
|
||||
# -region <name> The region name
|
||||
# -- End of options
|
||||
#
|
||||
# any remaining parameters are taken to be fields names
|
||||
# ---------------
|
||||
remove0DirFields()
|
||||
{
|
||||
local region
|
||||
|
||||
# Parse options
|
||||
while [ "$#" -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
('') ;; # Ignore empty option
|
||||
(--) shift; break ;; # Stop option parsing
|
||||
|
||||
(-region) region="$2"; shift ;;
|
||||
(*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# safety
|
||||
if [ "$region" = "--" ]; then unset region; fi
|
||||
|
||||
if [ "$#" -eq 0 ]
|
||||
then
|
||||
echo "No fields specified for ${region:+region=$region }" 1>&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Remove 0/ fields${region:+ [$region]} : $@" 1>&2
|
||||
|
||||
local subdir
|
||||
for subdir in 0/"$region" processor*/0/"$region"
|
||||
do
|
||||
if [ -d "$subdir" ]
|
||||
then
|
||||
for field in $@ ## unquoted for IFS splitting [SIC]
|
||||
do
|
||||
# Cautious with removal
|
||||
if [ -f "$subdir/$field" ]
|
||||
then
|
||||
rm -f -- "$subdir/$field"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -140,6 +140,11 @@ _of_complete_()
|
||||
# Could use "foamListTimes -withZero", but still doesn't address ranges
|
||||
COMPREPLY=($(compgen -d -X '![-0-9]*' -- ${cur}))
|
||||
;;
|
||||
-area-region)
|
||||
# Or: $(find system/finite-area -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed -e 's%.*/%%')
|
||||
choices=$(\ls -d system/finite-area/*/ 2>/dev/null | sed -e 's%/$%%; s%^.*/%%')
|
||||
COMPREPLY=($(compgen -W "$choices" -- ${cur}))
|
||||
;;
|
||||
-region)
|
||||
# Or: $(find system -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed -e 's%.*/%%')
|
||||
choices=$(\ls -d system/*/ 2>/dev/null | sed -e 's%/$%%; s%^.*/%%')
|
||||
|
||||
@ -341,22 +341,6 @@ inline Ostream& operator<<(Ostream& os, std::string_view s)
|
||||
return os;
|
||||
}
|
||||
|
||||
//- Write operator for character span. Output like string data
|
||||
inline Ostream& operator<<(Ostream& os, stdFoam::span<char> s)
|
||||
{
|
||||
os.writeQuoted(s.data(), s.size(), true); // quoted
|
||||
os.check("Foam::operator<<(Ostream&, stdFoam::span<char>)");
|
||||
return os;
|
||||
}
|
||||
|
||||
//- Write operator for const character span. Output like string data
|
||||
inline Ostream& operator<<(Ostream& os, stdFoam::span<const char> s)
|
||||
{
|
||||
os.writeQuoted(s.data(), s.size(), true); // quoted
|
||||
os.check("Foam::operator<<(Ostream&, stdFoam::span<const char>)");
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Manipulators (without arguments)
|
||||
|
||||
@ -343,11 +343,22 @@ void Foam::UPstream::mpiGatherv
|
||||
}
|
||||
// Nothing further to do
|
||||
}
|
||||
else if constexpr (UPstream_basic_dataType<Type>::value)
|
||||
else if constexpr (UPstream_dataType<Type>::value)
|
||||
{
|
||||
// Restrict to basic (or aliased) MPI types to avoid recalculating
|
||||
// the list of counts/offsets.
|
||||
|
||||
// The sizing factor (constexpr) must be 1 otherwise
|
||||
// [recvCounts,recvOffsets] are likely incorrect
|
||||
|
||||
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
|
||||
|
||||
static_assert
|
||||
(
|
||||
(count == 1),
|
||||
"Code does not (yet) work with aggregate types"
|
||||
);
|
||||
|
||||
UPstream::mpi_gatherv
|
||||
(
|
||||
sendData,
|
||||
@ -356,7 +367,7 @@ void Foam::UPstream::mpiGatherv
|
||||
recvCounts,
|
||||
recvOffsets,
|
||||
|
||||
UPstream_basic_dataType<Type>::datatype_id,
|
||||
UPstream_dataType<Type>::datatype_id,
|
||||
communicator
|
||||
);
|
||||
}
|
||||
@ -364,7 +375,8 @@ void Foam::UPstream::mpiGatherv
|
||||
{
|
||||
static_assert
|
||||
(
|
||||
stdFoam::dependent_false_v<Type>, "Only basic MPI data types"
|
||||
stdFoam::dependent_false_v<Type>,
|
||||
"Only basic and user data types"
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -392,11 +404,22 @@ void Foam::UPstream::mpiScatterv
|
||||
}
|
||||
// Nothing further to do
|
||||
}
|
||||
else if constexpr (UPstream_basic_dataType<Type>::value)
|
||||
else if constexpr (UPstream_dataType<Type>::value)
|
||||
{
|
||||
// Restrict to basic (or aliased) MPI types to avoid recalculating
|
||||
// the list of counts/offsets.
|
||||
|
||||
// The sizing factor (constexpr) must be 1 otherwise
|
||||
// [sendCounts,sendOffsets] are likely incorrect
|
||||
|
||||
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
|
||||
|
||||
static_assert
|
||||
(
|
||||
(count == 1),
|
||||
"Code does not (yet) work with aggregate types"
|
||||
);
|
||||
|
||||
UPstream::mpi_scatterv
|
||||
(
|
||||
sendData,
|
||||
@ -405,7 +428,7 @@ void Foam::UPstream::mpiScatterv
|
||||
recvData,
|
||||
recvCount,
|
||||
|
||||
UPstream_basic_dataType<Type>::datatype_id,
|
||||
UPstream_dataType<Type>::datatype_id,
|
||||
communicator
|
||||
);
|
||||
}
|
||||
@ -413,7 +436,8 @@ void Foam::UPstream::mpiScatterv
|
||||
{
|
||||
static_assert
|
||||
(
|
||||
stdFoam::dependent_false_v<Type>, "Only basic MPI data types"
|
||||
stdFoam::dependent_false_v<Type>,
|
||||
"Only basic and user data types"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ struct UPstream_basic_dataType
|
||||
UPstream_alias_dataType<base>::datatype_id;
|
||||
|
||||
//- The size in terms of the number of underlying data elements
|
||||
static std::streamsize size(std::streamsize n) noexcept
|
||||
static constexpr std::streamsize size(std::streamsize n) noexcept
|
||||
{
|
||||
if constexpr (UPstream_alias_dataType<T>::value)
|
||||
{
|
||||
@ -373,7 +373,10 @@ struct UPstream_basic_dataType
|
||||
template<> struct UPstream_basic_dataType<void> : UPstream_mpi_dataType<void>
|
||||
{
|
||||
using base = void;
|
||||
static std::streamsize size(std::streamsize n) noexcept { return n; }
|
||||
static constexpr std::streamsize size(std::streamsize n) noexcept
|
||||
{
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -410,7 +413,7 @@ struct UPstream_dataType
|
||||
UPstream_any_dataType<base>::datatype_id;
|
||||
|
||||
//- The size in terms of the number of base data elements
|
||||
static std::streamsize size(std::streamsize n) noexcept
|
||||
static constexpr std::streamsize size(std::streamsize n) noexcept
|
||||
{
|
||||
if constexpr (UPstream_any_dataType<T>::value)
|
||||
{
|
||||
|
||||
@ -95,10 +95,12 @@ Foam::tokenList Foam::ITstream::parse_chars
|
||||
IOstreamOption streamOpt
|
||||
)
|
||||
{
|
||||
ISpanStream is(s, nbytes, streamOpt);
|
||||
|
||||
tokenList tokens;
|
||||
parseStream(is, tokens);
|
||||
if (s && nbytes > 0) // extra safety
|
||||
{
|
||||
ISpanStream is(s, nbytes, streamOpt);
|
||||
parseStream(is, tokens);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
@ -107,10 +109,19 @@ Foam::tokenList Foam::ITstream::parse_chars
|
||||
|
||||
void Foam::ITstream::reset(const char* input, size_t nbytes)
|
||||
{
|
||||
ISpanStream is(input, nbytes, static_cast<IOstreamOption>(*this));
|
||||
tokenList tokens;
|
||||
if (input && nbytes > 0) // extra safety
|
||||
{
|
||||
ISpanStream is(input, nbytes, static_cast<IOstreamOption>(*this));
|
||||
|
||||
parseStream(is, static_cast<tokenList&>(*this));
|
||||
ITstream::seek(0); // rewind() bypassing virtual
|
||||
parseStream(is, static_cast<tokenList&>(*this));
|
||||
ITstream::seek(0); // rewind() bypassing virtual
|
||||
}
|
||||
else
|
||||
{
|
||||
ITstream::seek(0); // rewind() bypassing virtual
|
||||
tokenList::clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -248,7 +259,10 @@ Foam::ITstream::ITstream
|
||||
:
|
||||
ITstream(streamOpt, name)
|
||||
{
|
||||
reset(input, strlen(input));
|
||||
if (input)
|
||||
{
|
||||
reset(input, strlen(input));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -77,7 +77,8 @@ class ITstream
|
||||
// but leave any excess capacity (ie, like reserve).
|
||||
void reserveCapacity(const label newCapacity);
|
||||
|
||||
//- Convert input sequence into a list of tokens,
|
||||
//- Convert input sequence into a list of tokens.
|
||||
// Includes nullptr guard
|
||||
static tokenList parse_chars
|
||||
(
|
||||
const char* s,
|
||||
@ -87,6 +88,7 @@ class ITstream
|
||||
|
||||
//- Convert input sequence into a list of tokens,
|
||||
//- using the existing stream format. Rewinds the stream
|
||||
// Includes nullptr guard
|
||||
void reset(const char* input, size_t nbytes);
|
||||
|
||||
//- Failsafe read-access to token at specified location
|
||||
@ -175,32 +177,6 @@ public:
|
||||
reset(s.data(), s.size());
|
||||
}
|
||||
|
||||
//- Construct token list by parsing the input character sequence
|
||||
// Uses static parse function internally.
|
||||
explicit ITstream
|
||||
(
|
||||
stdFoam::span<char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
ITstream(streamOpt)
|
||||
{
|
||||
reset(s.data(), s.size());
|
||||
}
|
||||
|
||||
//- Construct token list by parsing the input character sequence
|
||||
// Uses static parse function internally.
|
||||
explicit ITstream
|
||||
(
|
||||
stdFoam::span<const char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
ITstream(streamOpt)
|
||||
{
|
||||
reset(s.data(), s.size());
|
||||
}
|
||||
|
||||
|
||||
// Additional constructors
|
||||
|
||||
@ -255,17 +231,6 @@ public:
|
||||
return parse_chars(input.cdata(), input.size(), streamOpt);
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input string
|
||||
//- until no good tokens remain.
|
||||
static tokenList parse
|
||||
(
|
||||
const std::string& input,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
{
|
||||
return parse_chars(input.data(), input.size(), streamOpt);
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input character sequence
|
||||
//- until no good tokens remain.
|
||||
static tokenList parse
|
||||
@ -274,7 +239,14 @@ public:
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
{
|
||||
return parse_chars(input, strlen(input), streamOpt);
|
||||
if (input)
|
||||
{
|
||||
return parse_chars(input, strlen(input), streamOpt);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tokenList();
|
||||
}
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input character sequence
|
||||
@ -288,28 +260,6 @@ public:
|
||||
return parse_chars(s.data(), s.size(), streamOpt);
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input character sequence
|
||||
//- until no good tokens remain.
|
||||
static tokenList parse
|
||||
(
|
||||
stdFoam::span<char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
{
|
||||
return parse_chars(s.data(), s.size(), streamOpt);
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input character sequence
|
||||
//- until no good tokens remain.
|
||||
static tokenList parse
|
||||
(
|
||||
stdFoam::span<const char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
{
|
||||
return parse_chars(s.data(), s.size(), streamOpt);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
@ -387,7 +337,7 @@ public:
|
||||
label& tokenIndex() noexcept { return tokenIndex_; }
|
||||
|
||||
//- Set the token index (no checks). \return the previous value
|
||||
label tokenIndex(const label num) noexcept
|
||||
label tokenIndex(label num) noexcept
|
||||
{
|
||||
label old(tokenIndex_);
|
||||
tokenIndex_ = num;
|
||||
|
||||
@ -123,20 +123,6 @@ public:
|
||||
stream_type(static_cast<buffer_type*>(this))
|
||||
{}
|
||||
|
||||
//- Construct (shallow copy) from span character content
|
||||
explicit ispanstream(stdFoam::span<char> s)
|
||||
:
|
||||
buffer_type(const_cast<char*>(s.data()), s.size()),
|
||||
stream_type(static_cast<buffer_type*>(this))
|
||||
{}
|
||||
|
||||
//- Construct (shallow copy) from span character content
|
||||
explicit ispanstream(stdFoam::span<const char> s)
|
||||
:
|
||||
buffer_type(const_cast<char*>(s.data()), s.size()),
|
||||
stream_type(static_cast<buffer_type*>(this))
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
@ -325,26 +311,6 @@ public:
|
||||
ISpanStream(buffer.cdata(), buffer.size(), streamOpt)
|
||||
{}
|
||||
|
||||
//- Construct (shallow copy) from span character content
|
||||
explicit ISpanStream
|
||||
(
|
||||
stdFoam::span<const char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
ISpanStream(s.data(), s.size(), streamOpt)
|
||||
{}
|
||||
|
||||
//- Construct (shallow copy) from span character content
|
||||
explicit ISpanStream
|
||||
(
|
||||
stdFoam::span<char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
ISpanStream(s.data(), s.size(), streamOpt)
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
@ -402,20 +368,6 @@ public:
|
||||
syncState();
|
||||
}
|
||||
|
||||
//- Reset input area to use data from span character content
|
||||
void reset(stdFoam::span<char> s)
|
||||
{
|
||||
stream_.reset(s.data(), s.size());
|
||||
syncState();
|
||||
}
|
||||
|
||||
//- Reset input area to use data from span character content
|
||||
void reset(stdFoam::span<const char> s)
|
||||
{
|
||||
stream_.reset(s.data(), s.size());
|
||||
syncState();
|
||||
}
|
||||
|
||||
//- Rewind the stream, clearing any old errors
|
||||
virtual void rewind() override
|
||||
{
|
||||
|
||||
@ -38,6 +38,7 @@ Description
|
||||
#include "DynamicList.H"
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
@ -113,6 +113,7 @@ SeeAlso
|
||||
#include "label.H"
|
||||
#include "scalar.H"
|
||||
#include "regExpFwd.H"
|
||||
#include "Switch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
@ -55,6 +55,8 @@ SourceFiles
|
||||
|
||||
#include "label.H"
|
||||
#include "word.H"
|
||||
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ SourceFiles
|
||||
|
||||
#include "Dictionary.H"
|
||||
#include "simpleRegIOobject.H"
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -333,7 +333,7 @@ Foam::fileMonitor& Foam::fileOperation::monitor() const
|
||||
|
||||
void Foam::fileOperation::mergeTimes
|
||||
(
|
||||
const instantList& extraTimes,
|
||||
const UList<instant>& extraTimes,
|
||||
const word& constantName,
|
||||
instantList& times
|
||||
)
|
||||
|
||||
@ -198,8 +198,10 @@ protected:
|
||||
//- Merge two times
|
||||
static void mergeTimes
|
||||
(
|
||||
const instantList& extraTimes,
|
||||
const UList<instant>& extraTimes,
|
||||
//! The "constant" name
|
||||
const word& constantName,
|
||||
//! [in,out] Updated with any extra times
|
||||
instantList& times
|
||||
);
|
||||
|
||||
@ -870,7 +872,13 @@ public:
|
||||
) const;
|
||||
|
||||
//- Get sorted list of times
|
||||
virtual instantList findTimes(const fileName&, const word&) const;
|
||||
virtual instantList findTimes
|
||||
(
|
||||
//! The directory to search
|
||||
const fileName& directory,
|
||||
//! The "constant" name
|
||||
const word& constantName = "constant"
|
||||
) const;
|
||||
|
||||
//- Find time instance where IOobject is located.
|
||||
//- The name of the IOobject can be empty, in which case only the
|
||||
|
||||
@ -748,7 +748,13 @@ public:
|
||||
// Other
|
||||
|
||||
//- Get sorted list of times
|
||||
virtual instantList findTimes(const fileName&, const word&) const;
|
||||
virtual instantList findTimes
|
||||
(
|
||||
//! The directory to search
|
||||
const fileName& directory,
|
||||
//! The "constant" name
|
||||
const word& constantName = "constant"
|
||||
) const;
|
||||
|
||||
//- Find time instance where IOobject is located.
|
||||
//- The name of the IOobject can be empty, in which case only the
|
||||
|
||||
@ -11,7 +11,10 @@ License
|
||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
|
||||
Description
|
||||
Add multi-region command-line options: -allRegions, -regions, -region
|
||||
Add multi-region command-line options:
|
||||
-allRegions | -all-regions
|
||||
-regions
|
||||
-region
|
||||
|
||||
Required Classes
|
||||
- Foam::argList
|
||||
@ -24,10 +27,10 @@ See Also
|
||||
{
|
||||
Foam::argList::addBoolOption
|
||||
(
|
||||
"all-regions",
|
||||
"allRegions",
|
||||
"Use all regions in regionProperties"
|
||||
);
|
||||
Foam::argList::addOptionCompat("all-regions", { "allRegions", -2506 });
|
||||
Foam::argList::addOptionCompat("allRegions", { "all-regions", 0 });
|
||||
|
||||
Foam::argList::addOption
|
||||
(
|
||||
|
||||
@ -45,12 +45,19 @@ See Also
|
||||
|
||||
wordList regionNames;
|
||||
{
|
||||
// Local alias
|
||||
auto& names = regionNames;
|
||||
// Exit or fallback if nothing matches
|
||||
constexpr bool exitOnNoMatches = true;
|
||||
|
||||
if (args.found("all-regions"))
|
||||
// Local aliases
|
||||
auto& names = regionNames;
|
||||
const auto& fallback = Foam::polyMesh::defaultRegion;
|
||||
|
||||
if
|
||||
(
|
||||
// Handle both here (independent of which is an alias)
|
||||
args.found("all-regions")
|
||||
|| args.found("allRegions")
|
||||
)
|
||||
{
|
||||
names =
|
||||
(
|
||||
@ -81,11 +88,11 @@ wordList regionNames;
|
||||
{
|
||||
select.uniq(); // Normally a no-op
|
||||
|
||||
if (select.size() == 1 && select.front().isLiteral())
|
||||
if (select.size() == 1 && select[0].isLiteral())
|
||||
{
|
||||
// Identical to -region NAME
|
||||
names.resize(1);
|
||||
names.front() = select.front();
|
||||
names[0] = select[0];
|
||||
}
|
||||
else if (select.size())
|
||||
{
|
||||
@ -116,12 +123,12 @@ wordList regionNames;
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoErr<< "... ignoring and using default region"
|
||||
InfoErr
|
||||
<< "... ignoring and using default region"
|
||||
<< nl << endl;
|
||||
|
||||
// Arbitrary fallback, but can handle this further on
|
||||
names.resize(1);
|
||||
names.front() = Foam::polyMesh::defaultRegion;
|
||||
names[0] = fallback;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -160,7 +167,7 @@ wordList regionNames;
|
||||
else
|
||||
{
|
||||
names.resize(1);
|
||||
names.front() = Foam::polyMesh::defaultRegion;
|
||||
names[0] = fallback;
|
||||
|
||||
InfoErr
|
||||
<< "Warning: No regionProperties, "
|
||||
@ -169,17 +176,30 @@ wordList regionNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (args.found("region"))
|
||||
else
|
||||
{
|
||||
// Single region option or fallback
|
||||
names.resize(1);
|
||||
names.front() = args.get<word>("region");
|
||||
auto& name = names[0];
|
||||
|
||||
if
|
||||
(
|
||||
!args.readIfPresent("region", name)
|
||||
)
|
||||
{
|
||||
name = fallback;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to defaultRegion
|
||||
// Final sanity checks and/or fallback
|
||||
if (names.empty())
|
||||
{
|
||||
names.resize(1);
|
||||
names.front() = Foam::polyMesh::defaultRegion;
|
||||
names[0] = fallback;
|
||||
}
|
||||
else if (names.size() == 1 && names[0].empty())
|
||||
{
|
||||
names[0] = fallback;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -221,9 +221,14 @@ Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
|
||||
auto tcoarseCellMap = tmp<labelField>::New(nFineCells, -1);
|
||||
auto& coarseCellMap = tcoarseCellMap.ref();
|
||||
|
||||
// Small tolerance to account for faces potentially having slightly
|
||||
// different truncation error in their weights from run to run
|
||||
// (e.g. due to offloading). If all the largest faces per cell are
|
||||
// within this tolerance use the first one. This guarantees repeatability.
|
||||
const scalar tol = 1E-10;
|
||||
|
||||
nCoarseCells = 0;
|
||||
label celli;
|
||||
|
||||
for (label cellfi=0; cellfi<nFineCells; cellfi++)
|
||||
{
|
||||
// Change cell ordering depending on direction for this level
|
||||
@ -250,7 +255,7 @@ Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
|
||||
(
|
||||
coarseCellMap[upperAddr[facei]] < 0
|
||||
&& coarseCellMap[lowerAddr[facei]] < 0
|
||||
&& faceWeights[facei] > maxFaceWeight
|
||||
&& faceWeights[facei] > maxFaceWeight*(1.0 + tol)
|
||||
)
|
||||
{
|
||||
// Match found. Pick up all the necessary data
|
||||
@ -282,7 +287,7 @@ Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
|
||||
{
|
||||
label facei = cellFaces[faceOs];
|
||||
|
||||
if (faceWeights[facei] > clusterMaxFaceCoeff)
|
||||
if (faceWeights[facei] > clusterMaxFaceCoeff*(1.0 + tol))
|
||||
{
|
||||
clusterMatchFaceNo = facei;
|
||||
clusterMaxFaceCoeff = faceWeights[facei];
|
||||
|
||||
@ -27,6 +27,7 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "globalIndex.H"
|
||||
#include <functional>
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
@ -696,159 +697,94 @@ void Foam::globalIndex::mpiGather
|
||||
const UList<Type>& sendData,
|
||||
OutputContainer& allData,
|
||||
const label comm,
|
||||
UPstream::commsTypes commsType,
|
||||
const int tag
|
||||
[[maybe_unused]] UPstream::commsTypes commsType,
|
||||
[[maybe_unused]] const int tag
|
||||
) const
|
||||
{
|
||||
if (!UPstream::parRun())
|
||||
if (!UPstream::is_parallel(comm))
|
||||
{
|
||||
// Serial: direct copy
|
||||
allData = sendData;
|
||||
return;
|
||||
}
|
||||
|
||||
// MPI_Gatherv requires contiguous data, but a byte-wise transfer can
|
||||
// quickly exceed the 'int' limits used for MPI sizes/offsets.
|
||||
// Thus gather label/scalar components when possible to increase the
|
||||
// effective size limit.
|
||||
//
|
||||
// Note: cannot rely on pTraits (cmptType, nComponents) since this method
|
||||
// needs to compile (and work) even with things like strings etc.
|
||||
|
||||
// Single char ad hoc "enum":
|
||||
// - b(yte): gather bytes
|
||||
// - f(loat): gather scalars components
|
||||
// - i(nt): gather label components
|
||||
// - 0: gather with Pstream read/write etc.
|
||||
|
||||
List<int> recvCounts;
|
||||
List<int> recvOffsets;
|
||||
|
||||
char dataMode(0);
|
||||
int nCmpts(0);
|
||||
|
||||
if constexpr (is_contiguous_v<Type>)
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
if constexpr (is_contiguous_scalar<Type>::value)
|
||||
{
|
||||
dataMode = 'f';
|
||||
nCmpts = static_cast<int>(sizeof(Type)/sizeof(scalar));
|
||||
}
|
||||
else if constexpr (is_contiguous_label<Type>::value)
|
||||
{
|
||||
dataMode = 'i';
|
||||
nCmpts = static_cast<int>(sizeof(Type)/sizeof(label));
|
||||
}
|
||||
else
|
||||
{
|
||||
dataMode = 'b';
|
||||
nCmpts = static_cast<int>(sizeof(Type));
|
||||
}
|
||||
allData.resize_nocopy(offsets_.back()); // == totalSize()
|
||||
}
|
||||
else
|
||||
{
|
||||
allData.clear(); // zero-size on non-master
|
||||
}
|
||||
|
||||
if constexpr (UPstream_dataType<Type>::value)
|
||||
{
|
||||
// Restrict to basic (or aliased) MPI types
|
||||
// - simplifies calculating counts/offsets
|
||||
// and can call UPstream::mpiGatherv directly
|
||||
|
||||
// The sizing factor is constexpr
|
||||
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
|
||||
|
||||
static_assert
|
||||
(
|
||||
(count == 1),
|
||||
"Code does not (yet) work with aggregate types"
|
||||
);
|
||||
|
||||
List<int> recvCounts;
|
||||
List<int> recvOffsets;
|
||||
|
||||
// Offsets must fit into int
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
const globalIndex& globalAddr = *this;
|
||||
// Must be same as Pstream::nProcs(comm), at least on master!
|
||||
// if (UPstream::nProcs(comm) != this->nProcs()) ...
|
||||
|
||||
if (globalAddr.totalSize() > (INT_MAX/nCmpts))
|
||||
{
|
||||
// Offsets do not fit into int - revert to manual.
|
||||
dataMode = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must be same as Pstream::nProcs(comm), at least on master!
|
||||
const label nproc = globalAddr.nProcs();
|
||||
recvCounts.resize(offsets_.size()-1);
|
||||
recvOffsets.resize(offsets_.size());
|
||||
|
||||
allData.resize_nocopy(globalAddr.totalSize());
|
||||
// Copy offsets
|
||||
std::copy(offsets_.begin(), offsets_.end(), recvOffsets.begin());
|
||||
|
||||
recvCounts.resize(nproc);
|
||||
recvOffsets.resize(nproc+1);
|
||||
// Calculate sizes. Currently without std::minus <functional>
|
||||
std::transform
|
||||
(
|
||||
offsets_.begin()+1, offsets_.end(),
|
||||
offsets_.begin(), recvCounts.begin(),
|
||||
std::minus<>{}
|
||||
);
|
||||
|
||||
for (label proci = 0; proci < nproc; ++proci)
|
||||
{
|
||||
recvCounts[proci] = globalAddr.localSize(proci)*nCmpts;
|
||||
recvOffsets[proci] = globalAddr.localStart(proci)*nCmpts;
|
||||
}
|
||||
recvOffsets[nproc] = globalAddr.totalSize()*nCmpts;
|
||||
|
||||
// Assign local data directly
|
||||
|
||||
recvCounts[0] = 0; // ie, ignore for MPI_Gatherv
|
||||
SubList<Type>(allData, globalAddr.range(0)) =
|
||||
SubList<Type>(sendData, globalAddr.range(0));
|
||||
}
|
||||
// FUTURE .. fix sizes and offsets by the element factor...
|
||||
// if constexpr (UPstream_basic_dataType<Type>::size(1) > 1)
|
||||
}
|
||||
|
||||
// Consistent information for everyone
|
||||
UPstream::broadcast(&dataMode, 1, comm);
|
||||
int sendSize = static_cast<int>(sendData.size());
|
||||
|
||||
// Note we let MPI_Gatherv copy back the local data as well...
|
||||
|
||||
UPstream::mpiGatherv
|
||||
(
|
||||
sendData.cdata(),
|
||||
sendSize,
|
||||
allData.data(),
|
||||
recvCounts,
|
||||
recvOffsets,
|
||||
comm
|
||||
);
|
||||
}
|
||||
|
||||
// Dispatch
|
||||
switch (dataMode)
|
||||
else
|
||||
{
|
||||
case 'b': // Byte-wise
|
||||
{
|
||||
UPstream::mpiGatherv
|
||||
(
|
||||
sendData.cdata_bytes(),
|
||||
sendData.size_bytes(),
|
||||
allData.data_bytes(),
|
||||
recvCounts,
|
||||
recvOffsets,
|
||||
comm
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'f': // Float (scalar) components
|
||||
{
|
||||
typedef scalar cmptType;
|
||||
|
||||
UPstream::mpiGatherv
|
||||
(
|
||||
reinterpret_cast<const cmptType*>(sendData.cdata()),
|
||||
(sendData.size()*nCmpts),
|
||||
reinterpret_cast<cmptType*>(allData.data()),
|
||||
recvCounts,
|
||||
recvOffsets,
|
||||
comm
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'i': // Int (label) components
|
||||
{
|
||||
typedef label cmptType;
|
||||
|
||||
UPstream::mpiGatherv
|
||||
(
|
||||
reinterpret_cast<const cmptType*>(sendData.cdata()),
|
||||
(sendData.size()*nCmpts),
|
||||
reinterpret_cast<cmptType*>(allData.data()),
|
||||
recvCounts,
|
||||
recvOffsets,
|
||||
comm
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: // Regular (manual) gathering
|
||||
{
|
||||
globalIndex::gather
|
||||
(
|
||||
offsets_, // needed on master only
|
||||
comm,
|
||||
UPstream::allProcs(comm), // All communicator ranks
|
||||
sendData,
|
||||
allData,
|
||||
tag,
|
||||
commsType
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!UPstream::master(comm))
|
||||
{
|
||||
allData.clear(); // safety: zero-size on non-master
|
||||
// Regular (manual) gathering
|
||||
globalIndex::gather
|
||||
(
|
||||
offsets_, // needed on master only
|
||||
comm,
|
||||
UPstream::allProcs(comm), // All communicator ranks
|
||||
sendData,
|
||||
allData,
|
||||
tag,
|
||||
commsType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -43,6 +43,9 @@ SourceFiles
|
||||
#include "bool.H"
|
||||
#include "stdFoam.H"
|
||||
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
// Avoid any pre-processor conflicts with enum names
|
||||
#undef FALSE
|
||||
#undef TRUE
|
||||
|
||||
@ -58,6 +58,9 @@ Description
|
||||
|
||||
#include <algorithm> // std::copy
|
||||
#include <utility> // std::initializer_list
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -93,6 +96,11 @@ class CStringList
|
||||
// \return location one-past end of dest (ie, the next destination)
|
||||
static inline char* stringCopy(char* dest, const char* src);
|
||||
|
||||
//- Copy string characters into dest as NUL-terminated string.
|
||||
//
|
||||
// \return location one-past end of dest (ie, the next destination)
|
||||
static inline char* stringCopy(char *dest, std::string_view src);
|
||||
|
||||
//- Copy string characters into dest as NUL-terminated string.
|
||||
// Forces conversion of std::sub_match to string form
|
||||
//
|
||||
@ -133,9 +141,17 @@ public:
|
||||
template<class StringType>
|
||||
inline explicit CStringList(const UList<StringType>& input);
|
||||
|
||||
//- Copy construct from a list of string_views
|
||||
// Copies the input characters.
|
||||
inline explicit CStringList(const UList<std::string_view>& input);
|
||||
|
||||
//- Copy construct from a list of string_views
|
||||
// Copies the input characters.
|
||||
inline explicit CStringList(const std::vector<std::string_view>& input);
|
||||
|
||||
//- Copy construct from a list of sub-string references
|
||||
// Copies the input characters.
|
||||
explicit CStringList(const SubStrings& input);
|
||||
inline explicit CStringList(const SubStrings& input);
|
||||
|
||||
|
||||
//- Destructor. Invokes clear() to free memory.
|
||||
@ -157,6 +173,9 @@ public:
|
||||
//- Return the number of C-strings (ie, argc)
|
||||
int size() const noexcept { return argc_; }
|
||||
|
||||
//- The flattened character content, with interspersed nul-chars
|
||||
inline std::string_view view() const;
|
||||
|
||||
//- The flattened character content, with interspersed nul-chars
|
||||
const char* cdata_bytes() const noexcept { return data_; }
|
||||
|
||||
|
||||
@ -28,16 +28,6 @@ License
|
||||
#include "CStringList.H"
|
||||
#include "Ostream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::CStringList::CStringList(const SubStrings& input)
|
||||
:
|
||||
CStringList()
|
||||
{
|
||||
resetContent(input);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
// Largely identical to resetContent() except with 'c-string'
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -35,6 +35,14 @@ inline char* Foam::CStringList::stringCopy(char* dest, const char* src)
|
||||
}
|
||||
|
||||
|
||||
inline char* Foam::CStringList::stringCopy(char *dest, std::string_view src)
|
||||
{
|
||||
dest = std::copy_n(src.data(), src.size(), dest);
|
||||
*(dest++) = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
inline char* Foam::CStringList::stringCopy(char *dest, const std::string& src)
|
||||
{
|
||||
dest = std::copy_n(src.data(), src.size(), dest);
|
||||
@ -90,6 +98,33 @@ inline Foam::CStringList::CStringList(const UList<StringType>& input)
|
||||
}
|
||||
|
||||
|
||||
inline Foam::CStringList::CStringList(const UList<std::string_view>& input)
|
||||
:
|
||||
CStringList()
|
||||
{
|
||||
resetContent(input);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::CStringList::CStringList
|
||||
(
|
||||
const std::vector<std::string_view>& input
|
||||
)
|
||||
:
|
||||
CStringList()
|
||||
{
|
||||
resetContent(input);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::CStringList::CStringList(const SubStrings& input)
|
||||
:
|
||||
CStringList()
|
||||
{
|
||||
resetContent(input);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::CStringList::~CStringList()
|
||||
@ -100,6 +135,12 @@ inline Foam::CStringList::~CStringList()
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline std::string_view Foam::CStringList::view() const
|
||||
{
|
||||
return std::string_view(data_, nbytes_);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::CStringList::clear()
|
||||
{
|
||||
argc_ = 0;
|
||||
|
||||
@ -37,6 +37,7 @@ Description
|
||||
|
||||
#include <regex> // For std::ssub_match
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@ -69,6 +69,7 @@ SourceFiles
|
||||
#define Foam_regExpCxx_H
|
||||
|
||||
#include <regex>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -54,6 +54,7 @@ SourceFiles
|
||||
#include "Hasher.H"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -46,85 +46,106 @@ namespace Foam
|
||||
namespace stringOps
|
||||
{
|
||||
|
||||
//- 'Natural' compare for C-strings
|
||||
// Uses algorithm and code from Jan-Marten Spit <jmspit@euronet.nl>
|
||||
//
|
||||
// In the 'natural' comparison, strings are compared alphabetically
|
||||
// and numerically. Thus 'file010.txt' sorts after 'file2.txt'
|
||||
//
|
||||
// \param s1 left string
|
||||
// \param s2 right string
|
||||
//- 'Natural' compare for C-strings
|
||||
// Uses algorithm and code from Jan-Marten Spit <jmspit@euronet.nl>
|
||||
//
|
||||
// In the 'natural' comparison, strings are compared alphabetically
|
||||
// and numerically. Thus 'file010.txt' sorts after 'file2.txt'
|
||||
//
|
||||
// \param s1 left string
|
||||
// \param s2 right string
|
||||
// \return -1 when s1 < s2, 0 when s1 == s2, 1 when s1 > s2
|
||||
int natstrcmp(const char* s1, const char* s2);
|
||||
|
||||
|
||||
//- Encapsulation of natural order sorting for algorithms
|
||||
struct natural_sort
|
||||
{
|
||||
//- Natural compare for std::string
|
||||
// \return -1 when s1 < s2, 0 when s1 == s2, 1 when s1 > s2
|
||||
int natstrcmp(const char* s1, const char* s2);
|
||||
|
||||
|
||||
//- Encapsulation of natural order sorting for algorithms
|
||||
struct natural_sort
|
||||
static inline int compare
|
||||
(
|
||||
const std::string& s1,
|
||||
const std::string& s2
|
||||
)
|
||||
{
|
||||
//- Natural compare for std::string
|
||||
// \return -1 when s1 < s2, 0 when s1 == s2, 1 when s1 > s2
|
||||
static inline int compare
|
||||
(
|
||||
const std::string& s1,
|
||||
const std::string& s2
|
||||
)
|
||||
{
|
||||
return natstrcmp(s1.data(), s2.data());
|
||||
}
|
||||
return stringOps::natstrcmp(s1.data(), s2.data());
|
||||
}
|
||||
|
||||
//- Default (forward) natural sorting
|
||||
//- Natural compare two strings for a less-than relationship
|
||||
static inline bool less
|
||||
(
|
||||
const std::string& s1,
|
||||
const std::string& s2
|
||||
)
|
||||
{
|
||||
return (natural_sort::compare(s1, s2) < 0);
|
||||
}
|
||||
|
||||
//- Natural compare two strings for a greater-than relationship
|
||||
static inline bool greater
|
||||
(
|
||||
const std::string& s1,
|
||||
const std::string& s2
|
||||
)
|
||||
{
|
||||
return (natural_sort::compare(s1, s2) > 0);
|
||||
}
|
||||
|
||||
//- Default (forward) natural sorting
|
||||
bool operator()(const std::string& s1, const std::string& s2) const
|
||||
{
|
||||
return (natural_sort::compare(s1, s2) < 0);
|
||||
}
|
||||
|
||||
//- Reverse natural sorting
|
||||
struct reverse
|
||||
{
|
||||
//- Reverse natural sorting
|
||||
bool operator()(const std::string& s1, const std::string& s2) const
|
||||
{
|
||||
return natural_sort::compare(s1, s2) < 0;
|
||||
return (natural_sort::compare(s1, s2) > 0);
|
||||
}
|
||||
|
||||
//- Reverse natural sorting
|
||||
struct reverse
|
||||
{
|
||||
//- Reverse natural sorting
|
||||
bool operator()(const std::string& s1, const std::string& s2) const
|
||||
{
|
||||
return natural_sort::compare(s1, s2) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- A list compare binary predicate for natural sort
|
||||
template<class T>
|
||||
struct less
|
||||
{
|
||||
const UList<T>& values;
|
||||
|
||||
less(const UList<T>& list)
|
||||
:
|
||||
values(list)
|
||||
{}
|
||||
|
||||
bool operator()(const label a, const label b) const
|
||||
{
|
||||
return natural_sort::compare(values[a], values[b]) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- A list compare binary predicate for reverse natural sort
|
||||
template<class T>
|
||||
struct greater
|
||||
{
|
||||
const UList<T>& values;
|
||||
|
||||
greater(const UList<T>& list)
|
||||
:
|
||||
values(list)
|
||||
{}
|
||||
|
||||
bool operator()(const label a, const label b) const
|
||||
{
|
||||
return natural_sort::compare(values[a], values[b]) > 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//- A UList compare binary predicate for natural sort
|
||||
template<class T>
|
||||
struct list_less
|
||||
{
|
||||
const UList<T>& values;
|
||||
|
||||
list_less(const UList<T>& list) noexcept
|
||||
:
|
||||
values(list)
|
||||
{}
|
||||
|
||||
bool operator()(label a, label b) const
|
||||
{
|
||||
return (natural_sort::compare(values[a], values[b]) < 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- A Ulist compare binary predicate for reverse natural sort
|
||||
template<class T>
|
||||
struct list_greater
|
||||
{
|
||||
const UList<T>& values;
|
||||
|
||||
list_greater(const UList<T>& list) noexcept
|
||||
:
|
||||
values(list)
|
||||
{}
|
||||
|
||||
bool operator()(label a, label b) const
|
||||
{
|
||||
return (natural_sort::compare(values[a], values[b]) > 0);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // End namespace stringOps
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
@ -28,33 +28,45 @@ License
|
||||
#include "Pstream.H"
|
||||
#include "PstreamGlobals.H"
|
||||
#include "UPstreamWrapping.H"
|
||||
#include "vector.H" // for debugging
|
||||
|
||||
#undef STRINGIFY
|
||||
#undef STRING_QUOTE
|
||||
|
||||
#define STRINGIFY(content) #content
|
||||
#define STRING_QUOTE(input) STRINGIFY(input)
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
static inline bool is_basic_dataType(Foam::UPstream::dataTypes id) noexcept
|
||||
namespace
|
||||
{
|
||||
|
||||
inline bool is_nonAggregate(Foam::UPstream::dataTypes id) noexcept
|
||||
{
|
||||
return
|
||||
(
|
||||
int(id) >= int(Foam::UPstream::dataTypes::Basic_begin)
|
||||
&& int(id) < int(Foam::UPstream::dataTypes::Basic_end)
|
||||
)
|
||||
||
|
||||
(
|
||||
int(id) >= int(Foam::UPstream::dataTypes::User_begin)
|
||||
&& int(id) < int(Foam::UPstream::dataTypes::User_end)
|
||||
);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// Local function to print some error information
|
||||
inline void printErrorNonIntrinsic
|
||||
(
|
||||
const char* context,
|
||||
UPstream::dataTypes dataTypeId
|
||||
Foam::UPstream::dataTypes dataTypeId
|
||||
)
|
||||
{
|
||||
using namespace Foam;
|
||||
|
||||
FatalError
|
||||
<< "Bad input for " << context << ": likely a programming problem\n"
|
||||
<< " Non-intrinsic data (" << int(dataTypeId) << ")\n"
|
||||
<< " Non-intrinsic/non-user data (type:" << int(dataTypeId) << ")\n"
|
||||
<< Foam::endl;
|
||||
}
|
||||
|
||||
@ -214,19 +226,37 @@ void Foam::UPstream::mpi_gatherv
|
||||
{
|
||||
MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
|
||||
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
!is_basic_dataType(dataTypeId)
|
||||
)
|
||||
)
|
||||
// Runtime assert that we are not using aggregated data types
|
||||
if (FOAM_UNLIKELY(!is_nonAggregate(dataTypeId)))
|
||||
{
|
||||
FatalErrorInFunction;
|
||||
printErrorNonIntrinsic("MPI_Gatherv()", dataTypeId);
|
||||
FatalError << Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
const label np = UPstream::nProcs(communicator);
|
||||
|
||||
// For total-size calculation,
|
||||
// don't rely on recvOffsets being (np+1)
|
||||
const int totalSize =
|
||||
(
|
||||
(UPstream::master(communicator) && np > 1)
|
||||
? (recvOffsets[np-1] + recvCounts[np-1])
|
||||
: 0
|
||||
);
|
||||
|
||||
if (FOAM_UNLIKELY(UPstream::debug))
|
||||
{
|
||||
Perr<< "[mpi_gatherv] :"
|
||||
<< " type:" << int(dataTypeId)
|
||||
<< " count:" << sendCount
|
||||
<< " total:" << totalSize
|
||||
<< " comm:" << communicator
|
||||
<< " recvCounts:" << flatOutput(recvCounts)
|
||||
<< " recvOffsets:" << flatOutput(recvOffsets)
|
||||
<< Foam::endl;
|
||||
}
|
||||
|
||||
{
|
||||
PstreamDetail::gatherv
|
||||
(
|
||||
@ -235,6 +265,48 @@ void Foam::UPstream::mpi_gatherv
|
||||
datatype, communicator
|
||||
);
|
||||
}
|
||||
|
||||
// Extended debugging. Limit to master:
|
||||
|
||||
#if 0
|
||||
if (FOAM_UNLIKELY(UPstream::debug))
|
||||
{
|
||||
if (UPstream::master(communicator))
|
||||
{
|
||||
switch (dataTypeId)
|
||||
{
|
||||
#undef dataPrinter
|
||||
#define dataPrinter(enumType, nativeType) \
|
||||
case UPstream::dataTypes::enumType : \
|
||||
{ \
|
||||
UList<nativeType> combined \
|
||||
( \
|
||||
static_cast<nativeType*>(recvData), \
|
||||
totalSize \
|
||||
); \
|
||||
\
|
||||
Info<< "[mpi_gatherv] => " \
|
||||
"List<" STRING_QUOTE(nativeType) "> "; \
|
||||
combined.writeList(Info) << Foam::endl; \
|
||||
\
|
||||
break; \
|
||||
}
|
||||
|
||||
// Some common types
|
||||
dataPrinter(type_int32, int32_t);
|
||||
dataPrinter(type_int64, int64_t);
|
||||
dataPrinter(type_float, float);
|
||||
dataPrinter(type_double, double);
|
||||
dataPrinter(type_3float, floatVector);
|
||||
dataPrinter(type_3double, doubleVector);
|
||||
|
||||
// Some other type
|
||||
default: break;
|
||||
#undef dataPrinter
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -255,13 +327,8 @@ void Foam::UPstream::mpi_scatterv
|
||||
{
|
||||
MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
|
||||
|
||||
if
|
||||
(
|
||||
FOAM_UNLIKELY
|
||||
(
|
||||
!is_basic_dataType(dataTypeId)
|
||||
)
|
||||
)
|
||||
// Runtime assert that we are not using aggregated data types
|
||||
if (FOAM_UNLIKELY(!is_nonAggregate(dataTypeId)))
|
||||
{
|
||||
FatalErrorInFunction;
|
||||
printErrorNonIntrinsic("MPI_Scatterv()", dataTypeId);
|
||||
|
||||
@ -16,6 +16,6 @@ starcd/STARCDMeshWriter.C
|
||||
|
||||
polyDualMesh/polyDualMesh.C
|
||||
|
||||
vtk/output/foamVtkSurfaceFieldWriter.C
|
||||
vtk/output/foamVtkSurfaceFieldWriter.cxx
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/libconversion
|
||||
|
||||
@ -98,7 +98,7 @@ bool writeAreaField
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ensightOutputAreaFieldTemplates.C"
|
||||
#include "ensightOutputAreaField.txx"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -177,7 +177,7 @@ bool writePointField
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ensightOutputVolFieldTemplates.C"
|
||||
#include "ensightOutputVolField.txx"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -39,7 +39,7 @@ Note
|
||||
|
||||
SourceFiles
|
||||
foamVtkToolsI.H
|
||||
foamVtkToolsTemplates.C
|
||||
foamVtkTools.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -358,7 +358,7 @@ void Foam::vtk::Tools::remapTuple<Foam::symmTensor>(double data[])
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "foamVtkToolsTemplates.C"
|
||||
#include "foamVtkTools.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -39,7 +39,7 @@ Note
|
||||
|
||||
SourceFiles
|
||||
foamVtkVtuAdaptorI.H
|
||||
foamVtkVtuAdaptorTemplates.C
|
||||
foamVtkVtuAdaptor.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -156,7 +156,7 @@ public:
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "foamVtkVtuAdaptorTemplates.C"
|
||||
#include "foamVtkVtuAdaptor.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -32,7 +32,7 @@ Description
|
||||
Caution, currently only works properly for indirect patches.
|
||||
|
||||
SourceFiles
|
||||
foamVtkGenericPatchGeoFieldsWriter.C
|
||||
foamVtkGenericPatchGeoFieldsWriter.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -117,7 +117,7 @@ public:
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "foamVtkGenericPatchGeoFieldsWriter.C"
|
||||
#include "foamVtkGenericPatchGeoFieldsWriter.txx"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ See Also
|
||||
Foam::vtk::internalMeshWriter
|
||||
|
||||
SourceFiles
|
||||
foamVtkInternalWriterTemplates.C
|
||||
foamVtkInternalWriter.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -183,7 +183,7 @@ public:
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "foamVtkInternalWriterTemplates.C"
|
||||
#include "foamVtkInternalWriter.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -43,7 +43,7 @@ See Also
|
||||
Foam::vtk::patchMeshWriter
|
||||
|
||||
SourceFiles
|
||||
foamVtkPatchWriterTemplates.C
|
||||
foamVtkPatchWriter.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -202,7 +202,7 @@ public:
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "foamVtkPatchWriterTemplates.C"
|
||||
#include "foamVtkPatchWriter.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -47,7 +47,7 @@ Note
|
||||
may be addressed using ghost points.
|
||||
|
||||
SourceFiles
|
||||
surfaceFieldWriter.C
|
||||
foamVtkSurfaceFieldWriter.cxx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ faceSetOption/faceSetOption.C
|
||||
derivedSources=sources/derived
|
||||
|
||||
$(derivedSources)/externalHeatFluxSource/externalHeatFluxSource.C
|
||||
$(derivedSources)/jouleHeatingSource/jouleHeatingSource.C
|
||||
$(derivedSources)/jouleHeatingSource/jouleHeatingSource.cxx
|
||||
$(derivedSources)/contactHeatFluxSource/contactHeatFluxSource.C
|
||||
$(derivedSources)/externalFileSource/externalFileSource.C
|
||||
|
||||
|
||||
@ -81,6 +81,33 @@ Foam::fa::option::option
|
||||
active_(dict.getOrDefault("active", true)),
|
||||
log(true)
|
||||
{
|
||||
// Suffix hint for variable names
|
||||
if
|
||||
(
|
||||
coeffs_.readIfPresent("suffixing", suffixHint_)
|
||||
|| dict.readIfPresent("suffixing", suffixHint_)
|
||||
)
|
||||
{
|
||||
Switch sw = Switch::find(suffixHint_);
|
||||
|
||||
if (sw.good())
|
||||
{
|
||||
if (!sw) // No suffix
|
||||
{
|
||||
suffixHint_.clear();
|
||||
}
|
||||
}
|
||||
else if (suffixHint_ == "default")
|
||||
{
|
||||
sw = true;
|
||||
}
|
||||
|
||||
if (sw) // Default suffix
|
||||
{
|
||||
suffixHint_ = '_' + regionName_;
|
||||
}
|
||||
}
|
||||
|
||||
if (dict.readIfPresent("area", areaName_))
|
||||
{
|
||||
if (!sameRegionNames(areaName_, defaultAreaName))
|
||||
@ -95,9 +122,14 @@ Foam::fa::option::option
|
||||
}
|
||||
}
|
||||
|
||||
Log << incrIndent << indent << "Source: " << name_
|
||||
<< " [" << polyMesh::regionName(areaName_) << ']' << endl
|
||||
<< decrIndent;
|
||||
Log << incrIndent << indent << "Source: " << name_;
|
||||
|
||||
if (!polyMesh::regionName(areaName_).empty())
|
||||
{
|
||||
Log<< " [" << areaName_ << ']';
|
||||
}
|
||||
|
||||
Info<< decrIndent << endl;
|
||||
}
|
||||
|
||||
|
||||
@ -117,13 +149,20 @@ Foam::autoPtr<Foam::fa::option> Foam::fa::option::New
|
||||
coeffs.readIfPresent("area", areaName);
|
||||
|
||||
Info<< indent
|
||||
<< "Selecting finite-area option, type " << modelType
|
||||
<< " [" << polyMesh::regionName(areaName) << ']';
|
||||
<< "Selecting finite-area option, type " << modelType;
|
||||
|
||||
if (!sameRegionNames(areaName, defaultAreaName))
|
||||
if (sameRegionNames(areaName, defaultAreaName))
|
||||
{
|
||||
Info<< " != " << defaultAreaName << nl;
|
||||
if (!polyMesh::regionName(areaName).empty())
|
||||
{
|
||||
Info<< " [" << areaName << ']';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " [" << areaName << "] != [" << defaultAreaName << ']';
|
||||
}
|
||||
|
||||
Info<< endl;
|
||||
|
||||
mesh.time().libs().open
|
||||
|
||||
@ -65,10 +65,13 @@ Usage
|
||||
--> the selected faOption settings | dictionary | no | -
|
||||
active | Flag to (de)activate faOption | bool | no | true
|
||||
log | Flag to log faOption-related info | bool | no | true
|
||||
suffixing | Suffix hint for option variables | word | no | -
|
||||
\endtable
|
||||
|
||||
Note
|
||||
- Source/sink options are to be added to the right-hand side of equations.
|
||||
- Suffixing (true|false|none|default|...) currently selects between
|
||||
no suffix and ('_'+region).
|
||||
|
||||
SourceFiles
|
||||
faOption.C
|
||||
@ -136,6 +139,9 @@ protected:
|
||||
//- The model region name (finite-area)
|
||||
word regionName_;
|
||||
|
||||
//- Suffix hint for variable names (default: "")
|
||||
word suffixHint_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
@ -273,7 +279,7 @@ public:
|
||||
//- The source name
|
||||
const word& name() const noexcept { return name_; }
|
||||
|
||||
//- Return const access to the mesh database
|
||||
//- Return const access to the volume mesh
|
||||
const fvMesh& mesh() const noexcept { return mesh_; }
|
||||
|
||||
//- Return dictionary
|
||||
@ -304,6 +310,18 @@ public:
|
||||
inline bool active(bool on) noexcept;
|
||||
|
||||
|
||||
// Helper Functions
|
||||
|
||||
//- The suffix hint when generating variable names
|
||||
const word& suffixHint() const noexcept { return suffixHint_; }
|
||||
|
||||
//- Return the concatenation of \p base and the suffix hint
|
||||
inline word suffixed(const char* base) const;
|
||||
|
||||
//- Return the concatenation of \p base and the suffix hint
|
||||
inline word suffixed(const std::string& base) const;
|
||||
|
||||
|
||||
// Checks
|
||||
|
||||
//- Is the source active?
|
||||
|
||||
@ -61,4 +61,18 @@ inline const Foam::volSurfaceMapping& Foam::fa::option::vsm() const
|
||||
}
|
||||
|
||||
|
||||
inline Foam::word
|
||||
Foam::fa::option::suffixed(const char* base) const
|
||||
{
|
||||
return word(base + suffixHint_);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::word
|
||||
Foam::fa::option::suffixed(const std::string& base) const
|
||||
{
|
||||
return word(base + suffixHint_);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -27,7 +27,6 @@ License
|
||||
|
||||
#include "faOptions.H"
|
||||
#include "faMesh.H"
|
||||
#include "faMeshesRegistry.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -68,7 +67,7 @@ Foam::IOobject createIOobject
|
||||
lookupName,
|
||||
mesh.time().constant(),
|
||||
// located under finite-area
|
||||
faMeshesRegistry::New(mesh).thisDb(),
|
||||
faMesh::Registry(mesh),
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::REGISTER
|
||||
@ -188,11 +187,7 @@ Foam::fa::options& Foam::fa::options::New
|
||||
);
|
||||
|
||||
// Registered under finite-area?
|
||||
auto* ptr =
|
||||
faMeshesRegistry::New(mesh).thisDb().getObjectPtr<fa::options>
|
||||
(
|
||||
lookupName
|
||||
);
|
||||
auto* ptr = faMesh::Registry(mesh).getObjectPtr<fa::options>(lookupName);
|
||||
|
||||
if (!ptr && polyMesh::regionName(defaultAreaName).empty())
|
||||
{
|
||||
|
||||
@ -30,7 +30,6 @@ License
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "volFields.H"
|
||||
#include "famSup.H"
|
||||
#include "zeroGradientFaPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
@ -57,13 +56,10 @@ Foam::fa::contactHeatFluxSource::contactHeatFluxSource
|
||||
:
|
||||
fa::faceSetOption(sourceName, modelType, dict, mesh, defaultAreaName),
|
||||
TName_(dict.getOrDefault<word>("T", "T")),
|
||||
TprimaryName_(dict.get<word>("Tprimary")),
|
||||
TprimaryName_(dict.getOrDefault<word>("Tprimary", "T")),
|
||||
Tprimary_(mesh_.lookupObject<volScalarField>(TprimaryName_)),
|
||||
thicknessLayers_(),
|
||||
kappaLayers_(),
|
||||
contactRes_(0),
|
||||
curTimeIndex_(-1),
|
||||
coupling_()
|
||||
curTimeIndex_(-1)
|
||||
{
|
||||
fieldNames_.resize(1, TName_);
|
||||
|
||||
@ -131,30 +127,30 @@ void Foam::fa::contactHeatFluxSource::addSup
|
||||
const label fieldi
|
||||
)
|
||||
{
|
||||
if (isActive())
|
||||
if (!isActive())
|
||||
{
|
||||
DebugInfo
|
||||
<< name() << ": applying source to "
|
||||
<< eqn.psi().name() << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (curTimeIndex_ != mesh().time().timeIndex())
|
||||
{
|
||||
tmp<DimensionedField<scalar, areaMesh>> htcw(htc());
|
||||
DebugInfo<< name() << ": applying source to " << eqn.psi().name() << endl;
|
||||
|
||||
// Wall temperature - mapped from primary field to finite-area
|
||||
auto Twall = DimensionedField<scalar, areaMesh>::New
|
||||
(
|
||||
"Tw_" + option::name(),
|
||||
regionMesh(),
|
||||
dimensionedScalar(dimTemperature, Zero)
|
||||
);
|
||||
if (curTimeIndex_ != mesh().time().timeIndex())
|
||||
{
|
||||
tmp<DimensionedField<scalar, areaMesh>> htcw(htc());
|
||||
|
||||
vsm().mapInternalToSurface<scalar>(Tprimary_, Twall.ref().field());
|
||||
// Wall temperature - mapped from primary field to finite-area
|
||||
auto Twall = DimensionedField<scalar, areaMesh>::New
|
||||
(
|
||||
"Tw_" + option::name(),
|
||||
regionMesh(),
|
||||
dimensionedScalar(dimTemperature, Zero)
|
||||
);
|
||||
|
||||
eqn += -fam::Sp(htcw(), eqn.psi()) + htcw()*Twall;
|
||||
vsm().mapInternalToSurface<scalar>(Tprimary_, Twall.ref().field());
|
||||
|
||||
curTimeIndex_ = mesh().time().timeIndex();
|
||||
}
|
||||
eqn += -fam::Sp(htcw(), eqn.psi()) + htcw()*Twall;
|
||||
|
||||
curTimeIndex_ = mesh().time().timeIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,8 +186,14 @@ bool Foam::fa::contactHeatFluxSource::read(const dictionary& dict)
|
||||
|
||||
const labelList& patches = regionMesh().whichPolyPatches();
|
||||
|
||||
coupling_.clear();
|
||||
coupling_.resize(patches.empty() ? 0 : (patches.last()+1));
|
||||
if (patches.empty())
|
||||
{
|
||||
coupling_.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
coupling_.resize_null(patches.back()+1);
|
||||
}
|
||||
|
||||
for (const label patchi : patches)
|
||||
{
|
||||
|
||||
@ -40,6 +40,8 @@ Usage
|
||||
{
|
||||
// Mandatory entries (unmodifiable)
|
||||
type contactHeatFluxSource;
|
||||
|
||||
// Optional entries (unmodifiable)
|
||||
Tprimary <TprimaryFieldName>;
|
||||
|
||||
// Optional entries (runtime modifiable)
|
||||
@ -60,12 +62,19 @@ Usage
|
||||
\table
|
||||
Property | Description | Type | Reqd | Dflt
|
||||
type | Type name: contactHeatFluxSource | word | yes | -
|
||||
Tprimary | Name of primary temperature field | word | yes | -
|
||||
T | Name of operand temperature field | word | no | T
|
||||
Tprimary | Name of primary temperature field | word | no | T
|
||||
thicknessLayers | List of thicknesses of layers | scalarList | no | -
|
||||
kappaLayers | List of conductivities of layers | scalarList | cndtnl | -
|
||||
\endtable
|
||||
|
||||
Fields/variables used:
|
||||
\table
|
||||
Property | Description | Type | Deflt
|
||||
T | Temperature | shell | T
|
||||
Tprimary | Temperature | volume | T
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link faOption.H \endlink
|
||||
- \link faceSetOption.H \endlink
|
||||
@ -124,13 +133,13 @@ class contactHeatFluxSource
|
||||
|
||||
// Private Data
|
||||
|
||||
//- Name of temperature field
|
||||
//- Name of shell temperature field (default: "T")
|
||||
word TName_;
|
||||
|
||||
//- Name of primary temperature field
|
||||
word TprimaryName_;
|
||||
//- Name of volume temperature field (default: "T")
|
||||
const word TprimaryName_;
|
||||
|
||||
//- Primary region temperature
|
||||
//- Primary (volume) region temperature
|
||||
const volScalarField& Tprimary_;
|
||||
|
||||
//- Thickness of layers
|
||||
|
||||
@ -72,10 +72,6 @@ Foam::fa::externalHeatFluxSource::externalHeatFluxSource
|
||||
fa::faceSetOption(sourceName, modelType, dict, m, defaultAreaName),
|
||||
mode_(operationModeNames.get("mode", dict)),
|
||||
TName_(dict.getOrDefault<word>("T", "T")),
|
||||
Q_(nullptr),
|
||||
q_(nullptr),
|
||||
h_(nullptr),
|
||||
Ta_(nullptr),
|
||||
emissivity_(dict.getOrDefault<scalar>("emissivity", 0))
|
||||
{
|
||||
fieldNames_.resize(1, TName_);
|
||||
@ -205,6 +201,11 @@ bool Foam::fa::externalHeatFluxSource::read(const dictionary& dict)
|
||||
|
||||
mode_ = operationModeNames.get("mode", dict);
|
||||
|
||||
Q_.reset(nullptr);
|
||||
q_.reset(nullptr);
|
||||
h_.reset(nullptr);
|
||||
Ta_.reset(nullptr);
|
||||
|
||||
switch (mode_)
|
||||
{
|
||||
case fixedPower:
|
||||
|
||||
@ -103,7 +103,7 @@ Usage
|
||||
\verbatim
|
||||
power | Use fixed power (supply Q)
|
||||
flux | Use fixed heat flux (supply q)
|
||||
coefficient | Use fixes heat transfer coefficient (supply h and T)
|
||||
coefficient | Use fixes heat transfer coefficient (supply h and Ta)
|
||||
\endverbatim
|
||||
|
||||
See also
|
||||
@ -159,7 +159,7 @@ private:
|
||||
//- Operation mode
|
||||
operationMode mode_;
|
||||
|
||||
//- Name of temperature field
|
||||
//- Name of shell temperature field (default: "T")
|
||||
word TName_;
|
||||
|
||||
//- Heat power [W]
|
||||
@ -174,7 +174,7 @@ private:
|
||||
//- Ambient temperature [K]
|
||||
autoPtr<Function1<scalar>> Ta_;
|
||||
|
||||
//- Optional surface emissivity for radiative transfer to ambient
|
||||
//- Surface emissivity for radiative transfer to ambient (default: 0)
|
||||
scalar emissivity_;
|
||||
|
||||
|
||||
|
||||
@ -115,23 +115,30 @@ Usage
|
||||
- \link faceSetOption.H \endlink
|
||||
|
||||
Note
|
||||
- \c anisotropicElectricalConductivity=true enables
|
||||
anisotropic (tensorial) electrical conductivity.
|
||||
- \c anisotropicElectricalConductivity=false enables
|
||||
isotropic (scalar) electrical conductivity.
|
||||
- The electrical conductivity can be specified using either:
|
||||
- If the \c sigma entry is present the electrical conductivity is specified
|
||||
as a function of temperature using a \c Function1 type.
|
||||
- If not present the \c sigma field will be read from file.
|
||||
- If the \c anisotropicElectricalConductivity flag is set to \c true,
|
||||
\c sigma should be specified as a tensor quantity.
|
||||
If the \c sigma entry is present, the electrical conductivity is specified
|
||||
as a function of temperature using a \c Function1 type, otherwise
|
||||
the \c sigma field will be read from file.
|
||||
When the \c anisotropicElectricalConductivity flag is set to \c true,
|
||||
\c sigma should be specified as a \em tensor quantity instead of as
|
||||
an isotropic \em scalar quantity.
|
||||
|
||||
BREAKING Naming changes from 2056 and earlier for the fields:
|
||||
\table
|
||||
Field | Scoped names | Scoped names (old)
|
||||
V | \<scope\>:V (suffix) | \<scope\>:V_ + regionName
|
||||
sigma | \<scope\>:sigma (suffix) | \<scope\>:sigma_ + regionName
|
||||
\endtable
|
||||
|
||||
It is possible to replicate the older naming by specifying
|
||||
the \c suffixing to ('_' + regionName).
|
||||
|
||||
See also
|
||||
- Foam::Function1
|
||||
- Foam::fv::jouleHeatingSource
|
||||
|
||||
SourceFiles
|
||||
jouleHeatingSource.C
|
||||
jouleHeatingSourceTemplates.C
|
||||
jouleHeatingSource.cxx
|
||||
jouleHeatingSourceImpl.cxx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -188,13 +195,13 @@ class jouleHeatingSource
|
||||
void initialiseSigma
|
||||
(
|
||||
const dictionary& dict,
|
||||
autoPtr<Function1<Type>>& sigmaVsTPtr
|
||||
autoPtr<Function1<Type>>& sigmaFunctionPtr
|
||||
);
|
||||
|
||||
//- Update the electrical conductivity field
|
||||
template<class Type>
|
||||
const GeometricField<Type, faPatchField, areaMesh>&
|
||||
updateSigma(const autoPtr<Function1<Type>>& sigmaVsTPtr) const;
|
||||
updateSigma(const autoPtr<Function1<Type>>& sigmaFunctionPtr) const;
|
||||
|
||||
|
||||
public:
|
||||
@ -229,22 +236,22 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Evaluation
|
||||
// Evaluation
|
||||
|
||||
//- Add explicit contribution to compressible momentum equation
|
||||
virtual void addSup
|
||||
(
|
||||
const areaScalarField& h,
|
||||
const areaScalarField& rho,
|
||||
faMatrix<scalar>& eqn,
|
||||
const label fieldi
|
||||
);
|
||||
//- Add explicit contribution to energy equation
|
||||
virtual void addSup
|
||||
(
|
||||
const areaScalarField& h,
|
||||
const areaScalarField& rho,
|
||||
faMatrix<scalar>& eqn,
|
||||
const label fieldi
|
||||
);
|
||||
|
||||
|
||||
// IO
|
||||
// IO
|
||||
|
||||
//- Read source dictionary
|
||||
virtual bool read(const dictionary& dict);
|
||||
//- Read source dictionary
|
||||
virtual bool read(const dictionary& dict);
|
||||
};
|
||||
|
||||
|
||||
@ -255,12 +262,6 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "jouleHeatingSourceTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -42,6 +42,12 @@ namespace fa
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Implementation
|
||||
#include "jouleHeatingSourceImpl.cxx"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fa::jouleHeatingSource::jouleHeatingSource
|
||||
@ -59,7 +65,7 @@ Foam::fa::jouleHeatingSource::jouleHeatingSource
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::scopedName(typeName, "V_" + regionName_),
|
||||
suffixed(IOobject::scopedName(typeName, "V")),
|
||||
regionMesh().thisDb().time().timeName(),
|
||||
regionMesh().thisDb(),
|
||||
IOobject::MUST_READ,
|
||||
@ -68,8 +74,6 @@ Foam::fa::jouleHeatingSource::jouleHeatingSource
|
||||
),
|
||||
regionMesh()
|
||||
),
|
||||
scalarSigmaVsTPtr_(nullptr),
|
||||
tensorSigmaVsTPtr_(nullptr),
|
||||
curTimeIndex_(-1),
|
||||
nIter_(1),
|
||||
anisotropicElectricalConductivity_(false)
|
||||
@ -78,6 +82,8 @@ Foam::fa::jouleHeatingSource::jouleHeatingSource
|
||||
|
||||
fa::option::resetApplied();
|
||||
|
||||
read(dict);
|
||||
|
||||
if (anisotropicElectricalConductivity_)
|
||||
{
|
||||
Info<< " Using tensor electrical conductivity" << endl;
|
||||
@ -90,8 +96,6 @@ Foam::fa::jouleHeatingSource::jouleHeatingSource
|
||||
|
||||
initialiseSigma(coeffs_, scalarSigmaVsTPtr_);
|
||||
}
|
||||
|
||||
read(dict);
|
||||
}
|
||||
|
||||
|
||||
@ -105,12 +109,14 @@ void Foam::fa::jouleHeatingSource::addSup
|
||||
const label fieldi
|
||||
)
|
||||
{
|
||||
if (isActive())
|
||||
if (!isActive())
|
||||
{
|
||||
DebugInfo
|
||||
<< name() << ": applying source to "
|
||||
<< eqn.psi().name() << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
DebugInfo<< name() << ": applying source to " << eqn.psi().name() << endl;
|
||||
|
||||
{
|
||||
if (curTimeIndex_ != mesh().time().timeIndex())
|
||||
{
|
||||
for (label i = 0; i < nIter_; ++i)
|
||||
@ -118,8 +124,7 @@ void Foam::fa::jouleHeatingSource::addSup
|
||||
if (anisotropicElectricalConductivity_)
|
||||
{
|
||||
// Update sigma as a function of T if required
|
||||
const areaTensorField& sigma =
|
||||
updateSigma(tensorSigmaVsTPtr_);
|
||||
const auto& sigma = updateSigma(tensorSigmaVsTPtr_);
|
||||
|
||||
// Solve the electrical potential equation
|
||||
faScalarMatrix VEqn(fam::laplacian(h*sigma, V_));
|
||||
@ -129,8 +134,7 @@ void Foam::fa::jouleHeatingSource::addSup
|
||||
else
|
||||
{
|
||||
// Update sigma as a function of T if required
|
||||
const areaScalarField& sigma =
|
||||
updateSigma(scalarSigmaVsTPtr_);
|
||||
const auto& sigma = updateSigma(scalarSigmaVsTPtr_);
|
||||
|
||||
// Solve the electrical potential equation
|
||||
faScalarMatrix VEqn(fam::laplacian(h*sigma, V_));
|
||||
@ -145,7 +149,7 @@ void Foam::fa::jouleHeatingSource::addSup
|
||||
// Add the Joule heating contribution
|
||||
const word sigmaName
|
||||
(
|
||||
IOobject::scopedName(typeName, "sigma_" + regionName_)
|
||||
IOobject::scopedName(typeName, "sigma") + suffixHint()
|
||||
);
|
||||
|
||||
areaVectorField gradV("gradV", fac::grad(V_));
|
||||
@ -162,15 +166,13 @@ void Foam::fa::jouleHeatingSource::addSup
|
||||
|
||||
if (anisotropicElectricalConductivity_)
|
||||
{
|
||||
const auto& sigma =
|
||||
obr.lookupObject<areaTensorField>(sigmaName);
|
||||
const auto& sigma = obr.lookupObject<areaTensorField>(sigmaName);
|
||||
|
||||
tsource = (h*sigma & gradV) & gradV;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& sigma =
|
||||
obr.lookupObject<areaScalarField>(sigmaName);
|
||||
const auto& sigma = obr.lookupObject<areaScalarField>(sigmaName);
|
||||
|
||||
tsource = (h*sigma*gradV) & gradV;
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -33,16 +33,21 @@ template<class Type>
|
||||
void Foam::fa::jouleHeatingSource::initialiseSigma
|
||||
(
|
||||
const dictionary& dict,
|
||||
autoPtr<Function1<Type>>& sigmaVsTPtr
|
||||
autoPtr<Function1<Type>>& sigmaFunctionPtr
|
||||
)
|
||||
{
|
||||
typedef GeometricField<Type, faPatchField, areaMesh> FieldType;
|
||||
|
||||
const word sigmaName
|
||||
(
|
||||
IOobject::scopedName(typeName, "sigma") + suffixHint()
|
||||
);
|
||||
|
||||
auto& obr = regionMesh().thisDb();
|
||||
|
||||
IOobject io
|
||||
(
|
||||
IOobject::scopedName(typeName, "sigma_" + regionName_),
|
||||
sigmaName,
|
||||
obr.time().timeName(),
|
||||
obr,
|
||||
IOobject::NO_READ,
|
||||
@ -52,11 +57,11 @@ void Foam::fa::jouleHeatingSource::initialiseSigma
|
||||
|
||||
autoPtr<FieldType> tsigma;
|
||||
|
||||
if (dict.found("sigma"))
|
||||
{
|
||||
// Sigma to be defined using a Function1 type
|
||||
sigmaVsTPtr = Function1<Type>::New("sigma", dict, &mesh_);
|
||||
// Is sigma defined using a Function1 type?
|
||||
sigmaFunctionPtr = Function1<Type>::NewIfPresent("sigma", dict, &mesh_);
|
||||
|
||||
if (sigmaFunctionPtr)
|
||||
{
|
||||
tsigma.reset
|
||||
(
|
||||
new FieldType
|
||||
@ -89,31 +94,34 @@ template<class Type>
|
||||
const Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>&
|
||||
Foam::fa::jouleHeatingSource::updateSigma
|
||||
(
|
||||
const autoPtr<Function1<Type>>& sigmaVsTPtr
|
||||
const autoPtr<Function1<Type>>& sigmaFunctionPtr
|
||||
) const
|
||||
{
|
||||
typedef GeometricField<Type, faPatchField, areaMesh> FieldType;
|
||||
|
||||
const word sigmaName
|
||||
(
|
||||
IOobject::scopedName(typeName, "sigma") + suffixHint()
|
||||
);
|
||||
|
||||
const auto& obr = regionMesh().thisDb();
|
||||
|
||||
auto& sigma =
|
||||
obr.lookupObjectRef<FieldType>
|
||||
(
|
||||
IOobject::scopedName(typeName, "sigma_" + regionName_)
|
||||
);
|
||||
auto& sigma = obr.lookupObjectRef<FieldType>(sigmaName);
|
||||
|
||||
if (!sigmaVsTPtr)
|
||||
if (!sigmaFunctionPtr)
|
||||
{
|
||||
// Electrical conductivity field, sigma, was specified by the user
|
||||
return sigma;
|
||||
}
|
||||
|
||||
const auto& sigmaFunction = sigmaFunctionPtr();
|
||||
|
||||
const auto& T = obr.lookupObject<areaScalarField>(TName_);
|
||||
|
||||
// Internal field
|
||||
forAll(sigma, i)
|
||||
{
|
||||
sigma[i] = sigmaVsTPtr->value(T[i]);
|
||||
sigma[i] = sigmaFunction.value(T[i]);
|
||||
}
|
||||
|
||||
|
||||
@ -127,7 +135,7 @@ Foam::fa::jouleHeatingSource::updateSigma
|
||||
const scalarField& Tbf = T.boundaryField()[patchi];
|
||||
forAll(pf, facei)
|
||||
{
|
||||
pf[facei] = sigmaVsTPtr->value(Tbf[facei]);
|
||||
pf[facei] = sigmaFunction.value(Tbf[facei]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,7 +34,7 @@ SourceFiles
|
||||
ensightCase.C
|
||||
ensightCaseI.H
|
||||
ensightCaseOptions.C
|
||||
ensightCaseTemplates.C
|
||||
ensightCase.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -548,7 +548,7 @@ public:
|
||||
#include "ensightCaseI.H"
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ensightCaseTemplates.C"
|
||||
#include "ensightCase.txx"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -394,7 +394,7 @@ public:
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ensightFileTemplates.C"
|
||||
#include "ensightFile.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -31,7 +31,7 @@ Description
|
||||
|
||||
SourceFiles
|
||||
ensightOutput.C
|
||||
ensightOutputTemplates.C
|
||||
ensightOutput.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -557,7 +557,7 @@ bool writeFaceLocalField
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ensightOutputTemplates.C"
|
||||
#include "ensightOutput.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -38,7 +38,7 @@ Note
|
||||
|
||||
SourceFiles
|
||||
ensightOutputSurface.C
|
||||
ensightOutputSurfaceTemplates.C
|
||||
ensightOutputSurface.txx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -136,7 +136,7 @@ public:
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ensightOutputSurfaceTemplates.C"
|
||||
#include "ensightOutputSurface.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -42,8 +42,8 @@ Description
|
||||
|
||||
SourceFiles
|
||||
foamVtkFileWriter.C
|
||||
foamVtkFileWriter.txx
|
||||
foamVtkFileWriterI.H
|
||||
foamVtkFileWriterTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -350,7 +350,7 @@ public:
|
||||
#include "foamVtkFileWriterI.H"
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "foamVtkFileWriterTemplates.C"
|
||||
#include "foamVtkFileWriter.txx"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -64,13 +64,17 @@ namespace Foam
|
||||
// 2. natural sort (name)
|
||||
struct seriesLess
|
||||
{
|
||||
bool operator()(const fileNameInstant a, const fileNameInstant b) const
|
||||
template<class StringType>
|
||||
bool operator()
|
||||
(
|
||||
const Instant<StringType>& a,
|
||||
const Instant<StringType>& b
|
||||
) const
|
||||
{
|
||||
scalar val = compareOp<scalar>()(a.value(), b.value());
|
||||
if (val == 0)
|
||||
{
|
||||
return
|
||||
stringOps::natural_sort::compare(a.name(), b.name()) < 0;
|
||||
return stringOps::natural_sort::less(a.name(), b.name());
|
||||
}
|
||||
return val < 0;
|
||||
}
|
||||
@ -78,7 +82,7 @@ namespace Foam
|
||||
|
||||
|
||||
// Check if value is less than upper, with some tolerance.
|
||||
static inline bool lessThan(const scalar& val, const scalar& upper)
|
||||
static inline bool lessThan(scalar val, scalar upper)
|
||||
{
|
||||
return (val < upper && Foam::mag(val - upper) > ROOTVSMALL);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user