Compare commits

...

18 Commits

Author SHA1 Message Date
c0f56215ec ENH: AMI caching - addeduser-selectable stride 2025-10-23 20:06:28 +01:00
0ba3a91e0c WIP: removed initialisation to zero - not applicable to all use cases 2025-10-16 09:42:16 +01:00
af8bf54b3c WIP: small style changes 2025-10-14 10:39:48 +01:00
5012aa60c8 WIP: AMI cache - further updates - TO SQUASH 2025-10-13 17:36:13 +01:00
b9214f01c4 WIP: cyclicAMIFvPatchField - disable cacheNeighbourField when using AMI cache 2025-10-13 17:36:13 +01:00
2340bd0d74 TUT: mixerVesselAMI2D updated for MD24 cache weights and addressing 2025-10-13 17:36:13 +01:00
ae521bfca2 WIP: AMI caching - updates for parallel operation 2025-10-13 17:36:13 +01:00
a40ad0fa71 BUG: AMI local communicator allocated every step. Fixes #3372 2025-10-13 17:36:13 +01:00
6ba17c03b9 ENH: AMI - refactored caching 2025-10-13 17:36:13 +01:00
c34c720c6a ENH: FaceCellWave: enable through cyclicAMI 2025-10-13 17:36:13 +01:00
e7b9d57158 ENH: AMI - added caching of weights and addressing
Applicable to rotational cases:

- stores AMI weights and addressing on the first revolution
- cached evaluations performed on subsequent revolutions to reduce computational
  costs

Cached values are stored in angular bins, specified using the [optional]
`cacheSize` entry when defining the patch in the polyMesh/boundary file, e.g.

    AMI1
    {
        type            cyclicAMI;
        AMIMethod       faceAreaWeightAMI;
        neighbourPatch  AMI2;

        cacheSize       360; // New entry
        transform       rotational;
        rotationAxis    (0 0 1);
        rotationCentre  (0 0 0);
    }

Note that the transform must also be set to rotational; the additional
`rotationAxis` and `rotationCentre` entries are used to construct a local AMI
co-ordinate system to determine the rotation angle as the mesh moves.

360 bins are created in the example above, equating to a uniform bin width
of 1 degree.
2025-10-13 17:36:13 +01:00
09521d1304 ENH: add default "constant" name for fileOperations::findTimes()
- makes fileHandler calling resemble Time more closely

ENH: provide natural_sort less/greater functions

- more succinct than (compare < 0) or (compare > 0).
  The corresponding wrappers for UList renamed as list_less, etc
  but they were only used in unit tests

ENH: handle (-allRegions | -all-regions, ..) directly when retrieving args

- makes handling independent of aliasing order

STYLE: include <string_view> when including <string>

- the standard does not guarantee which headers (if any) actually
  include string_view
2025-10-13 17:36:13 +01:00
e02b4be7ca ENH: allow delayed construction of regionFaModel in volume bcs (#3419)
Ideally wish to delay construction of the finite-area mesh until
  updateCoeffs(), when it is actually needed.

  This helps avoid difficult to trace errors and avoids inadvertent
  parallel communication during construction from a dictionary.

  However, lazy evaluation fails at the later stage while attempting
  to load the corresponding initial fields, since the timeIndex has
  already advanced.

  Use the newly introduced regionModels::allowFaModels() switch
  to locally enable or disable lazy evaluation as needed.

  This allows selective disabling (eg, in post-processing utilities)
  where loading the volume field should not activate the associated
  regionFaModel and loading a finite-area mesh too (which may not
  exist or be defined at that point).
2025-10-13 17:36:13 +01:00
c7b5f1e3eb ENH: added clean up function remove0DirFields (RunFunctions)
- less typing than before and avoids relying on bash-specific behaviour
  (fixes #3448)

ENH: add -region support for cleanFaMesh and cleanPolyMesh

CONFIG: add bash completion help for -area-region

ENH: general improvements for regionProperties

- robustness and failsafe for foamListRegions, regionProperties
- additional global model switches for regionModels
2025-10-13 17:36:13 +01:00
ccb57c0499 ENH: increase some string_view coverage
- remove some stdFoam::span<char> handling, which was just a stop-gap
  measure
2025-10-13 17:36:12 +01:00
c83bdc1422 STYLE: surface/volume writing function objects
- further hide implementation (cxx ending)

STYLE: better distinction between code/templates for fileFormats/conversion

- for ensight and vtk, a large part of the code is header only.
  Make this easier to identify
2025-10-13 17:36:12 +01:00
22fd0b3e72 ENH: update globalIndex::mpiGather to use MPI intrinsic/user types
- add provisional support for selecting MPI_Gatherv
  when merging fields in the surface writers.
  Uses the 'gatherv' keyword [experimental]

BUG: gatherv/scatterv wrappers used the incorrect data type

- incorrectly checked against UPstream_basic_dataType trait instead of
  UPstream_dataType, which resulted in a count mismatch for
  user-defined types (eg, vector, tensor,...).

  This was not visibly active bug, since previous internal uses of
  gatherv were restricted to primitive types.

COMP: make UPstream dataType traits size(...) constexpr

- allows static asserts and/or compile-time selection
  of code based on size(1)
2025-10-13 17:36:12 +01:00
de91806a24 ENH: GAMGAgglomeration: increase repeatability. Fixes #3450 2025-10-13 17:36:12 +01:00
190 changed files with 4987 additions and 1339 deletions

View File

@ -200,7 +200,7 @@ void printTypeName()
template<class Type, bool UseTypeName = true> 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<< "========" << nl;
Info<< "type: "; 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 // Use element or component type (or byte-wise) for data type
using base = typename UPstream_dataType<Type>::base; using base = typename UPstream_dataType<Type>::base;
// The sizing factor is constexpr
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
Info<< " : "; Info<< " : ";
if constexpr (UseTypeName) if constexpr (UseTypeName)
{ {
@ -311,8 +314,7 @@ void printPstreamTraits(const std::string_view name = std::string_view())
Info<< " cmpt-type="; Info<< " cmpt-type=";
printDataTypeId(UPstream_dataType<Type>::datatype_id); printDataTypeId(UPstream_dataType<Type>::datatype_id);
Info<< " count=" << UPstream_dataType<Type>::size(1); Info<< " count=" << count << nl;
Info<< 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: // Main program:
@ -389,6 +409,8 @@ int main()
printPstreamTraits<const float>(); printPstreamTraits<const float>();
printPstreamTraits<floatVector>(); printPstreamTraits<floatVector>();
check_simple<floatVector>("vector<float>");
printPstreamTraits<scalar>(); printPstreamTraits<scalar>();
printPstreamTraits<double>(); printPstreamTraits<double>();
printPstreamTraits<doubleVector>(); printPstreamTraits<doubleVector>();

View File

@ -296,7 +296,7 @@ int main(int argc, char *argv[])
( (
strings, strings,
order, order,
stringOps::natural_sort::less<string>(strings) stringOps::natural_sort::list_less(strings)
); );
Info<< "natural sortedOrder: " << flatOutput(order) << endl; Info<< "natural sortedOrder: " << flatOutput(order) << endl;
} }
@ -321,7 +321,7 @@ int main(int argc, char *argv[])
/// sortable = hashed.toc(); /// sortable = hashed.toc();
/// sortable.sort /// sortable.sort
/// ( /// (
/// stringOps::natural_sort::less<string>(sortable) /// stringOps::natural_sort::list_less(sortable)
/// ); /// );
/// Info<< nl << "natural:" << sortable << endl; /// Info<< nl << "natural:" << sortable << endl;
@ -329,7 +329,7 @@ int main(int argc, char *argv[])
/// sortable = hashed.toc(); /// sortable = hashed.toc();
/// sortable.sort /// sortable.sort
/// ( /// (
/// stringOps::natural_sort::greater<string>(sortable) /// stringOps::natural_sort::list_greater(sortable)
/// ); /// );
/// Info<< nl << "natural:" << sortable << endl; /// Info<< nl << "natural:" << sortable << endl;
} }

View File

@ -59,11 +59,6 @@ int main(int argc, char *argv[])
<< " type: " << typeid(cstr).name() << " len:" << len << nl; << " type: " << typeid(cstr).name() << " len:" << len << nl;
Info<< " view: " << std::string_view(cstr) << 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;
} }
} }

View File

@ -1,4 +1,4 @@
mydebugSurfaceWriter.C mydebugSurfaceWriter.cxx
Test-surface-sampling.C Test-surface-sampling.cxx
EXE = $(FOAM_USER_APPBIN)/Test-surface-sampling EXE = $(FOAM_USER_APPBIN)/Test-surface-sampling

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2022-2023 OpenCFD Ltd. Copyright (C) 2022-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -83,12 +83,10 @@ template<> struct narrowType<SymmTensor<double>>
typedef SymmTensor<float> type; typedef SymmTensor<float> type;
}; };
// FIXME: Not sure why this one seems to be broken... template<> struct narrowType<Tensor<double>>
// {
// template<> struct narrowType<Tensor<double>> typedef Tensor<float> type;
// { };
// typedef Tensor<float> type;
// };
} // End namespace Foam } // End namespace Foam
@ -104,12 +102,18 @@ Foam::surfaceWriters::mydebugWriter::mergeField
{ {
addProfiling(merge, "debugWriter::merge-field"); addProfiling(merge, "debugWriter::merge-field");
// This is largely identical to surfaceWriter::mergeField() // Identical to surfaceWriter::mergeField()
// but with narrowing for communication // 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 // The narrowed type
typedef typename narrowType<Type>::type narrowedType; using narrowedType = typename narrowType<Type>::type;
// Ensure geometry is also merged // Ensure geometry is also merged
merge(); merge();
@ -130,14 +134,29 @@ Foam::surfaceWriters::mydebugWriter::mergeField
ConstPrecisionAdaptor<narrowedType, Type> input(fld); ConstPrecisionAdaptor<narrowedType, Type> input(fld);
PrecisionAdaptor<narrowedType, Type> output(allFld); PrecisionAdaptor<narrowedType, Type> output(allFld);
globIndex.gather if (gatherv_)
( {
input.cref(), // fld, globIndex.mpiGather
output.ref(), // allFld, (
UPstream::msgType(), input.cref(), // fld
commType_, output.ref(), // allFld
UPstream::worldComm 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 // Commit adapted content changes
input.commit(); input.commit();
@ -193,8 +212,19 @@ Foam::surfaceWriters::mydebugWriter::mydebugWriter
{ {
Info<< "Using debug surface writer (" Info<< "Using debug surface writer ("
<< (this->isPointData() ? "point" : "face") << " data):" << (this->isPointData() ? "point" : "face") << " data):"
<< " commsType=" << UPstream::commsTypeNames[commType_] << " commsType=";
<< " merge=" << Switch::name(enableMerge_)
if (UPstream::parRun())
{
if (gatherv_) Info<< "gatherv+";
Info<< UPstream::commsTypeNames[commType_];
}
else
{
Info<< "serial";
}
Info<< " merge=" << Switch::name(enableMerge_)
<< " write=" << Switch::name(enableWrite_) << " write=" << Switch::name(enableWrite_)
<< " narrow=" << Switch::name(narrowTransfer_) << " narrow=" << Switch::name(narrowTransfer_)
<< endl; << endl;

View File

@ -30,7 +30,8 @@ Group
grpPostProcessingUtilities grpPostProcessingUtilities
Description Description
List regions from constant/regionProperties. List volume regions from constant/regionProperties
or area regions from constant/finite-area/regionProperties
Usage Usage
\b foamListRegions [OPTION] \b foamListRegions [OPTION]
@ -72,6 +73,12 @@ int main(int argc, char *argv[])
"List constant/finite-area/regionProperties (if available)" "List constant/finite-area/regionProperties (if available)"
); );
argList::addBoolOption
(
"optional",
"A missing regionProperties is not treated as an error"
);
argList::addDryRunOption argList::addDryRunOption
( (
"Make reading optional and add verbosity" "Make reading optional and add verbosity"
@ -92,14 +99,20 @@ int main(int argc, char *argv[])
++optVerbose; ++optVerbose;
} }
// File is optional, not an error
const bool isOptional = args.found("optional");
// Use finite-area regions // Use finite-area regions
const bool doFiniteArea = args.found("finite-area"); 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); 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; readOpt = IOobjectOption::READ_IF_PRESENT;
} }
@ -116,58 +129,70 @@ int main(int argc, char *argv[])
if (doFiniteArea) if (doFiniteArea)
{ {
regionProps = regionProperties(runTime, faMeshPrefix, readOpt); 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 else
{ {
regionProps = regionProperties(runTime, readOpt); 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. // Some reporting...
wordList regionTypes; if (regionProps.empty())
if (args.size() > 1)
{ {
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; wordHashSet uniq;
label nTypes = 0;
for (label argi = 1; argi < args.size(); ++argi) for (label argi = 1; argi < args.size(); ++argi)
{ {
regionTypes[nTypes] = args[argi]; word regType(args[argi]);
const word& regType = regionTypes[nTypes];
if (uniq.insert(regType)) if (uniq.insert(regType))
{ {
if (regionProps.contains(regType)) if (regionProps.contains(regType))
{ {
++nTypes; if (!regionTypes.contains(regType))
{
regionTypes.push_back(std::move(regType));
}
} }
else else
{ {
@ -175,22 +200,22 @@ int main(int argc, char *argv[])
} }
} }
} }
regionTypes.resize(nTypes);
} }
else else
{ {
// Take all regions
regionTypes = regionProps.sortedToc(); regionTypes = regionProps.sortedToc();
} }
for (const word& regionType : regionTypes) for (const word& regionType : regionTypes)
{ {
const wordList& regionNames = regionProps[regionType]; if (const auto iter = regionProps.cfind(regionType); iter.good())
for (const word& regionName : regionNames)
{ {
Info<< regionName << nl; for (const word& regionName : iter.val())
{
Info<< regionName << nl;
}
} }
} }

View File

@ -418,8 +418,14 @@ int main(int argc, char *argv[])
// Allow explicit -constant, have zero from time range // Allow explicit -constant, have zero from time range
timeSelector::addOptions(true, false); // constant(true), zero(false) timeSelector::addOptions(true, false); // constant(true), zero(false)
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H" #include "setRootCase.H"
// ------------------------------------------------------------------------
// Configuration
const bool writeCellDist = args.found("cellDist"); const bool writeCellDist = args.found("cellDist");
// Most of these are ignored for dry-run (not triggered anywhere) // Most of these are ignored for dry-run (not triggered anywhere)

View File

@ -135,9 +135,14 @@ int main(int argc, char *argv[])
"Only reconstruct new times (i.e. that do not exist already)" "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 "setRootCase.H"
#include "createTime.H" #include "createTime.H"
// ------------------------------------------------------------------------
// Configuration
const bool doFields = !args.found("no-fields"); const bool doFields = !args.found("no-fields");
wordRes selectedFields; wordRes selectedFields;

View File

@ -780,11 +780,17 @@ int main(int argc, char *argv[])
#include "addAllRegionOptions.H" #include "addAllRegionOptions.H"
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H" #include "setRootCase.H"
#include "createTime.H" #include "createTime.H"
printWarning(); printWarning();
// ------------------------------------------------------------------------
// Configuration
const bool fullMatch = args.found("fullMatch"); const bool fullMatch = args.found("fullMatch");
const bool procMatch = args.found("procMatch"); const bool procMatch = args.found("procMatch");
const bool writeCellDist = args.found("cellDist"); const bool writeCellDist = args.found("cellDist");

View File

@ -1257,6 +1257,8 @@ int main(int argc, char *argv[])
true // Advanced option true // Advanced option
); );
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
//- Disable caching of times/processor dirs etc. Cause massive parallel //- Disable caching of times/processor dirs etc. Cause massive parallel
// problems when e.g decomposing. // problems when e.g decomposing.
@ -1269,6 +1271,7 @@ int main(int argc, char *argv[])
argList args(argc, argv); argList args(argc, argv);
// ------------------------------------------------------------------------
// As much as possible avoid synchronised operation. To be looked at more // As much as possible avoid synchronised operation. To be looked at more
// closely for the three scenarios: // closely for the three scenarios:

View File

@ -323,6 +323,9 @@ int main(int argc, char *argv[])
); );
argList::addOptionCompat("cellZones", {"cellZone", 1912}); argList::addOptionCompat("cellZones", {"cellZone", 1912});
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H" #include "setRootCase.H"
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -479,8 +479,14 @@ int main(int argc, char *argv[])
"Directory name for VTK output (default: 'VTK')" "Directory name for VTK output (default: 'VTK')"
); );
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H" #include "setRootCase.H"
// ------------------------------------------------------------------------
// Configuration
/// const int optVerbose = args.verbose(); /// const int optVerbose = args.verbose();
const bool decomposePoly = args.found("poly-decomp"); const bool decomposePoly = args.found("poly-decomp");
const bool doBoundary = !args.found("no-boundary"); const bool doBoundary = !args.found("no-boundary");

138
bin/foamCleanFaMesh Executable file
View 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"
#------------------------------------------------------------------------------

View File

@ -7,7 +7,7 @@
# \\/ M anipulation | # \\/ M anipulation |
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Copyright (C) 2011-2016 OpenFOAM Foundation # Copyright (C) 2011-2016 OpenFOAM Foundation
# Copyright (C) 2022 OpenCFD Ltd. # Copyright (C) 2022,2025 OpenCFD Ltd.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# License # License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later. # This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -27,9 +27,10 @@ usage() {
Usage: ${0##*/} [OPTION] Usage: ${0##*/} [OPTION]
options: options:
-case <dir> specify alternative case directory, default is the cwd -case <dir> case directory, default is the cwd
-region <name> specify alternative mesh region -region <name> mesh region
-help print the usage -dry-run | -n report actions but do not remove
-help print the usage
Remove the contents of the constant/polyMesh directory as per the Remove the contents of the constant/polyMesh directory as per the
Foam::polyMesh::removeFiles() method. Foam::polyMesh::removeFiles() method.
@ -38,58 +39,101 @@ USAGE
exit 1 exit 1
} }
unset caseDir regionName #------------------------------------------------------------------------------
# Parse options
unset caseDir regionName optDryRun
# Parse a single option
while [ "$#" -gt 0 ] while [ "$#" -gt 0 ]
do do
case "$1" in case "$1" in
-h | -help*) -h | -help*)
usage usage
;; ;;
-dry-run | -n)
optDryRun="(dry-run) "
;;
-case=*)
caseDir="${1#*=}"
;;
-case) -case)
caseDir="$2"
[ "$#" -ge 2 ] || usage "'$1' option requires an argument" [ "$#" -ge 2 ] || usage "'$1' option requires an argument"
cd "$2" 2>/dev/null || usage "directory does not exist: '$2'" cd "$2" 2>/dev/null || usage "directory does not exist: '$2'"
caseDir=$2 caseDir=$2
shift 2 shift
;; ;;
-region) -region)
[ "$#" -ge 2 ] || usage "'$1' option requires an argument" [ "$#" -ge 2 ] || usage "'$1' option requires an argument"
regionName=$2 regionName="$2"
shift 2 shift
;; ;;
*)
(*)
usage "unknown option/argument: '$*'" usage "unknown option/argument: '$*'"
;; ;;
esac esac
shift
done done
meshDir=polyMesh #------------------------------------------------------------------------------
if [ -n "$regionName" ]
then
meshDir="$regionName/$meshDir"
fi
# If -case was specified: insist upon 'constant/polyMesh' # Remove files (mesh itself, modifiers, snappyHexMesh ones) and subdirectories
if [ -n "$caseDir" ] # 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 then
if [ -d constant/"$meshDir" ] # [OK] has constant/<region>/polyMesh
then :
# Use constant/polyMesh
meshDir=constant/"$meshDir" elif [ -n "$caseDir" ]
else then
echo "Error: no 'constant/$meshDir' in $caseDir" 1>&2 # Specified -case, so no extra magic...
exit 1 echo "Error: no <$meshDir> in $caseDir" 1>&2
fi exit 1
else else
if [ -d constant/"$meshDir" ] # Try some other combinations
other="${meshDir#constant/}"
if [ -d "$other" ]
then then
# Use constant/polyMesh # Probably already within constant/
meshDir=constant/"$meshDir" meshDir="$other}"
elif [ -d "$meshDir" ]
then
# Likely already in constant/ - do not adjust anything
:
elif [ "${PWD##*/}" = polyMesh ] && [ -z "$regionName" ] elif [ "${PWD##*/}" = polyMesh ] && [ -z "$regionName" ]
then then
# Apparently already within polyMesh/ # Apparently already within polyMesh/
@ -98,31 +142,8 @@ else
fi fi
# Remove files (mesh itself, modifiers, snappyHexMesh ones) and subdirectories
# also remove .gz versions of the same files
echo "Cleaning ${caseDir:-.}/$meshDir" 1>&2 echo "Cleaning ${caseDir:-.}/$meshDir" 1>&2
for i in \ removeFiles "$meshDir"
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
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -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() 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 then
rm -rf constant/finite-area/faMesh [ -n "$region" ] && echo "Clearing $meshDir" 1>&2
rm -rf -- "$meshDir"
fi 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 then
if [ -e constant/faMesh/faMeshDefinition ] if [ -e "$meshDir"/faMeshDefinition ]
then then
# Old constant/faMesh location for faMeshDefinition still in use: # VERY OLD LOCATION
# - warn but don't remove anything
echo echo
echo "Warning: not removing constant/faMesh/" echo "WARNING: not removing $meshDir/"
echo " It contains a 'faMeshDefinition' file" echo " It contains a 'faMeshDefinition' file"
echo " Please relocate file(s) to system/ !!" echo " Please relocate file(s) to system/finite-area/ !!"
echo echo
else else
# Can remove constant/faMesh/ entirely (no faMeshDefinition) # Can remove constant/faMesh/ entirely (no faMeshDefinition)
rm -rf constant/faMesh echo "Clearing $meshDir" 1>&2
rm -rf -- "$meshDir"
fi fi
fi fi
} }
# ---------------
# Remove constant/polyMesh or constant/<region>/polyMesh
#
# Accepts following options:
# -region <name> The region name
# -- End of options
# ---------------
cleanPolyMesh() 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 then
if [ -e constant/polyMesh/blockMeshDict ] \ [ -n "$region" ] && echo "Clearing $meshDir" 1>&2
|| [ -e constant/polyMesh/blockMeshDict.m4 ]
if [ -e "$meshDir"/blockMeshDict ] \
|| [ -e "$meshDir"/blockMeshDict.m4 ]
then then
# Old constant/polyMesh location for blockMeshDict still in use: # VERY OLD LOCATION
# - warn but don't remove anything
echo echo
echo "Warning: not removing constant/polyMesh/" echo "WARNING: not removing $meshDir/"
echo " It contains a 'blockMeshDict' or 'blockMeshDict.m4' file" echo " It contains a 'blockMeshDict' or 'blockMeshDict.m4' file"
echo " Please relocate file(s) to system/ !!" echo " Please relocate file(s) to system/ !!"
echo echo
else else
# Can remove constant/polyMesh/ entirely (no blockMeshDict) # Can remove constant/polyMesh/ entirely (no blockMeshDict)
rm -rf constant/polyMesh rm -rf -- "$meshDir"
fi fi
fi fi
if [ -e system/blockMeshDict.m4 ] meshDir="system${region:+/}${region}"
if [ -e "$meshDir"/blockMeshDict.m4 ]
then then
rm -f system/blockMeshDict rm -f -- "$meshDir"/blockMeshDict
fi fi
} }
@ -212,7 +274,7 @@ cleanCase0()
removeCase() removeCase()
{ {
echo "Removing case ${1:-unknown}" echo "Removing case ${1:-unknown}"
[ "$#" -ge 1 ] && rm -rf "$1" [ "$#" -ge 1 ] && rm -rf -- "$1"
} }

View File

@ -517,9 +517,11 @@ cloneParallelCase()
} }
# ---------------
# If 0.orig/ exists, copy (overwrite) into 0/ [ie, serial case] # If 0.orig/ exists, copy (overwrite) into 0/ [ie, serial case]
# * -processor : copy into processor directories instead # * -processor : copy into processor directories instead
# * -all : copy into serial and processor directories # * -all : copy into serial and processor directories
# ---------------
restore0Dir() restore0Dir()
{ {
if [ ! -d 0.orig ] 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
}
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -140,6 +140,11 @@ _of_complete_()
# Could use "foamListTimes -withZero", but still doesn't address ranges # Could use "foamListTimes -withZero", but still doesn't address ranges
COMPREPLY=($(compgen -d -X '![-0-9]*' -- ${cur})) 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) -region)
# Or: $(find system -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed -e 's%.*/%%') # 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%^.*/%%') choices=$(\ls -d system/*/ 2>/dev/null | sed -e 's%/$%%; s%^.*/%%')

View File

@ -341,22 +341,6 @@ inline Ostream& operator<<(Ostream& os, std::string_view s)
return os; 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) Manipulators (without arguments)

View File

@ -343,11 +343,22 @@ void Foam::UPstream::mpiGatherv
} }
// Nothing further to do // 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 // Restrict to basic (or aliased) MPI types to avoid recalculating
// the list of counts/offsets. // 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 UPstream::mpi_gatherv
( (
sendData, sendData,
@ -356,7 +367,7 @@ void Foam::UPstream::mpiGatherv
recvCounts, recvCounts,
recvOffsets, recvOffsets,
UPstream_basic_dataType<Type>::datatype_id, UPstream_dataType<Type>::datatype_id,
communicator communicator
); );
} }
@ -364,7 +375,8 @@ void Foam::UPstream::mpiGatherv
{ {
static_assert 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 // 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 // Restrict to basic (or aliased) MPI types to avoid recalculating
// the list of counts/offsets. // 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 UPstream::mpi_scatterv
( (
sendData, sendData,
@ -405,7 +428,7 @@ void Foam::UPstream::mpiScatterv
recvData, recvData,
recvCount, recvCount,
UPstream_basic_dataType<Type>::datatype_id, UPstream_dataType<Type>::datatype_id,
communicator communicator
); );
} }
@ -413,7 +436,8 @@ void Foam::UPstream::mpiScatterv
{ {
static_assert static_assert
( (
stdFoam::dependent_false_v<Type>, "Only basic MPI data types" stdFoam::dependent_false_v<Type>,
"Only basic and user data types"
); );
} }
} }

View File

@ -354,7 +354,7 @@ struct UPstream_basic_dataType
UPstream_alias_dataType<base>::datatype_id; UPstream_alias_dataType<base>::datatype_id;
//- The size in terms of the number of underlying data elements //- 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) 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> template<> struct UPstream_basic_dataType<void> : UPstream_mpi_dataType<void>
{ {
using base = 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; UPstream_any_dataType<base>::datatype_id;
//- The size in terms of the number of base data elements //- 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) if constexpr (UPstream_any_dataType<T>::value)
{ {

View File

@ -95,10 +95,12 @@ Foam::tokenList Foam::ITstream::parse_chars
IOstreamOption streamOpt IOstreamOption streamOpt
) )
{ {
ISpanStream is(s, nbytes, streamOpt);
tokenList tokens; tokenList tokens;
parseStream(is, tokens); if (s && nbytes > 0) // extra safety
{
ISpanStream is(s, nbytes, streamOpt);
parseStream(is, tokens);
}
return tokens; return tokens;
} }
@ -107,10 +109,19 @@ Foam::tokenList Foam::ITstream::parse_chars
void Foam::ITstream::reset(const char* input, size_t nbytes) 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)); parseStream(is, static_cast<tokenList&>(*this));
ITstream::seek(0); // rewind() bypassing virtual 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) ITstream(streamOpt, name)
{ {
reset(input, strlen(input)); if (input)
{
reset(input, strlen(input));
}
} }

View File

@ -77,7 +77,8 @@ class ITstream
// but leave any excess capacity (ie, like reserve). // but leave any excess capacity (ie, like reserve).
void reserveCapacity(const label newCapacity); 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 static tokenList parse_chars
( (
const char* s, const char* s,
@ -87,6 +88,7 @@ class ITstream
//- Convert input sequence into a list of tokens, //- Convert input sequence into a list of tokens,
//- using the existing stream format. Rewinds the stream //- using the existing stream format. Rewinds the stream
// Includes nullptr guard
void reset(const char* input, size_t nbytes); void reset(const char* input, size_t nbytes);
//- Failsafe read-access to token at specified location //- Failsafe read-access to token at specified location
@ -175,32 +177,6 @@ public:
reset(s.data(), s.size()); 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 // Additional constructors
@ -255,17 +231,6 @@ public:
return parse_chars(input.cdata(), input.size(), streamOpt); 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 //- Create token list by parsing the input character sequence
//- until no good tokens remain. //- until no good tokens remain.
static tokenList parse static tokenList parse
@ -274,7 +239,14 @@ public:
IOstreamOption streamOpt = IOstreamOption() 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 //- Create token list by parsing the input character sequence
@ -288,28 +260,6 @@ public:
return parse_chars(s.data(), s.size(), streamOpt); 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 // Member Functions
@ -387,7 +337,7 @@ public:
label& tokenIndex() noexcept { return tokenIndex_; } label& tokenIndex() noexcept { return tokenIndex_; }
//- Set the token index (no checks). \return the previous value //- Set the token index (no checks). \return the previous value
label tokenIndex(const label num) noexcept label tokenIndex(label num) noexcept
{ {
label old(tokenIndex_); label old(tokenIndex_);
tokenIndex_ = num; tokenIndex_ = num;

View File

@ -123,20 +123,6 @@ public:
stream_type(static_cast<buffer_type*>(this)) 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 // Member Functions
@ -325,26 +311,6 @@ public:
ISpanStream(buffer.cdata(), buffer.size(), streamOpt) 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 // Member Functions
@ -402,20 +368,6 @@ public:
syncState(); 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 //- Rewind the stream, clearing any old errors
virtual void rewind() override virtual void rewind() override
{ {

View File

@ -38,6 +38,7 @@ Description
#include "DynamicList.H" #include "DynamicList.H"
#include <memory> #include <memory>
#include <string_view>
#include <string> #include <string>
#include <type_traits> #include <type_traits>

View File

@ -113,6 +113,7 @@ SeeAlso
#include "label.H" #include "label.H"
#include "scalar.H" #include "scalar.H"
#include "regExpFwd.H" #include "regExpFwd.H"
#include "Switch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -55,6 +55,8 @@ SourceFiles
#include "label.H" #include "label.H"
#include "word.H" #include "word.H"
#include <string_view>
#include <string> #include <string>
#include <iostream> #include <iostream>

View File

@ -40,6 +40,7 @@ SourceFiles
#include "Dictionary.H" #include "Dictionary.H"
#include "simpleRegIOobject.H" #include "simpleRegIOobject.H"
#include <string_view>
#include <string> #include <string>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -333,7 +333,7 @@ Foam::fileMonitor& Foam::fileOperation::monitor() const
void Foam::fileOperation::mergeTimes void Foam::fileOperation::mergeTimes
( (
const instantList& extraTimes, const UList<instant>& extraTimes,
const word& constantName, const word& constantName,
instantList& times instantList& times
) )

View File

@ -198,8 +198,10 @@ protected:
//- Merge two times //- Merge two times
static void mergeTimes static void mergeTimes
( (
const instantList& extraTimes, const UList<instant>& extraTimes,
//! The "constant" name
const word& constantName, const word& constantName,
//! [in,out] Updated with any extra times
instantList& times instantList& times
); );
@ -870,7 +872,13 @@ public:
) const; ) const;
//- Get sorted list of times //- 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. //- Find time instance where IOobject is located.
//- The name of the IOobject can be empty, in which case only the //- The name of the IOobject can be empty, in which case only the

View File

@ -748,7 +748,13 @@ public:
// Other // Other
//- Get sorted list of times //- 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. //- Find time instance where IOobject is located.
//- The name of the IOobject can be empty, in which case only the //- The name of the IOobject can be empty, in which case only the

View File

@ -11,7 +11,10 @@ License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later. This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
Description Description
Add multi-region command-line options: -allRegions, -regions, -region Add multi-region command-line options:
-allRegions | -all-regions
-regions
-region
Required Classes Required Classes
- Foam::argList - Foam::argList
@ -24,10 +27,10 @@ See Also
{ {
Foam::argList::addBoolOption Foam::argList::addBoolOption
( (
"all-regions", "allRegions",
"Use all regions in regionProperties" "Use all regions in regionProperties"
); );
Foam::argList::addOptionCompat("all-regions", { "allRegions", -2506 }); Foam::argList::addOptionCompat("allRegions", { "all-regions", 0 });
Foam::argList::addOption Foam::argList::addOption
( (

View File

@ -45,12 +45,19 @@ See Also
wordList regionNames; wordList regionNames;
{ {
// Local alias
auto& names = regionNames;
// Exit or fallback if nothing matches // Exit or fallback if nothing matches
constexpr bool exitOnNoMatches = true; 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 = names =
( (
@ -81,11 +88,11 @@ wordList regionNames;
{ {
select.uniq(); // Normally a no-op select.uniq(); // Normally a no-op
if (select.size() == 1 && select.front().isLiteral()) if (select.size() == 1 && select[0].isLiteral())
{ {
// Identical to -region NAME // Identical to -region NAME
names.resize(1); names.resize(1);
names.front() = select.front(); names[0] = select[0];
} }
else if (select.size()) else if (select.size())
{ {
@ -116,12 +123,12 @@ wordList regionNames;
} }
else else
{ {
InfoErr<< "... ignoring and using default region" InfoErr
<< "... ignoring and using default region"
<< nl << endl; << nl << endl;
// Arbitrary fallback, but can handle this further on
names.resize(1); names.resize(1);
names.front() = Foam::polyMesh::defaultRegion; names[0] = fallback;
} }
} }
else else
@ -160,7 +167,7 @@ wordList regionNames;
else else
{ {
names.resize(1); names.resize(1);
names.front() = Foam::polyMesh::defaultRegion; names[0] = fallback;
InfoErr InfoErr
<< "Warning: No regionProperties, " << "Warning: No regionProperties, "
@ -169,17 +176,30 @@ wordList regionNames;
} }
} }
} }
else if (args.found("region")) else
{ {
// Single region option or fallback
names.resize(1); 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()) if (names.empty())
{ {
names.resize(1); names.resize(1);
names.front() = Foam::polyMesh::defaultRegion; names[0] = fallback;
}
else if (names.size() == 1 && names[0].empty())
{
names[0] = fallback;
} }
} }

View File

@ -221,9 +221,14 @@ Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
auto tcoarseCellMap = tmp<labelField>::New(nFineCells, -1); auto tcoarseCellMap = tmp<labelField>::New(nFineCells, -1);
auto& coarseCellMap = tcoarseCellMap.ref(); 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; nCoarseCells = 0;
label celli; label celli;
for (label cellfi=0; cellfi<nFineCells; cellfi++) for (label cellfi=0; cellfi<nFineCells; cellfi++)
{ {
// Change cell ordering depending on direction for this level // 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[upperAddr[facei]] < 0
&& coarseCellMap[lowerAddr[facei]] < 0 && coarseCellMap[lowerAddr[facei]] < 0
&& faceWeights[facei] > maxFaceWeight && faceWeights[facei] > maxFaceWeight*(1.0 + tol)
) )
{ {
// Match found. Pick up all the necessary data // Match found. Pick up all the necessary data
@ -282,7 +287,7 @@ Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
{ {
label facei = cellFaces[faceOs]; label facei = cellFaces[faceOs];
if (faceWeights[facei] > clusterMaxFaceCoeff) if (faceWeights[facei] > clusterMaxFaceCoeff*(1.0 + tol))
{ {
clusterMatchFaceNo = facei; clusterMatchFaceNo = facei;
clusterMaxFaceCoeff = faceWeights[facei]; clusterMaxFaceCoeff = faceWeights[facei];

View File

@ -27,6 +27,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "globalIndex.H" #include "globalIndex.H"
#include <functional>
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
@ -696,159 +697,94 @@ void Foam::globalIndex::mpiGather
const UList<Type>& sendData, const UList<Type>& sendData,
OutputContainer& allData, OutputContainer& allData,
const label comm, const label comm,
UPstream::commsTypes commsType, [[maybe_unused]] UPstream::commsTypes commsType,
const int tag [[maybe_unused]] const int tag
) const ) const
{ {
if (!UPstream::parRun()) if (!UPstream::is_parallel(comm))
{ {
// Serial: direct copy // Serial: direct copy
allData = sendData; allData = sendData;
return; return;
} }
// MPI_Gatherv requires contiguous data, but a byte-wise transfer can if (UPstream::master(comm))
// 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 constexpr (is_contiguous_scalar<Type>::value) allData.resize_nocopy(offsets_.back()); // == totalSize()
{ }
dataMode = 'f'; else
nCmpts = static_cast<int>(sizeof(Type)/sizeof(scalar)); {
} allData.clear(); // zero-size on non-master
else if constexpr (is_contiguous_label<Type>::value) }
{
dataMode = 'i'; if constexpr (UPstream_dataType<Type>::value)
nCmpts = static_cast<int>(sizeof(Type)/sizeof(label)); {
} // Restrict to basic (or aliased) MPI types
else // - simplifies calculating counts/offsets
{ // and can call UPstream::mpiGatherv directly
dataMode = 'b';
nCmpts = static_cast<int>(sizeof(Type)); // 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)) 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)) recvCounts.resize(offsets_.size()-1);
{ recvOffsets.resize(offsets_.size());
// 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();
allData.resize_nocopy(globalAddr.totalSize()); // Copy offsets
std::copy(offsets_.begin(), offsets_.end(), recvOffsets.begin());
recvCounts.resize(nproc); // Calculate sizes. Currently without std::minus <functional>
recvOffsets.resize(nproc+1); std::transform
(
offsets_.begin()+1, offsets_.end(),
offsets_.begin(), recvCounts.begin(),
std::minus<>{}
);
for (label proci = 0; proci < nproc; ++proci) // FUTURE .. fix sizes and offsets by the element factor...
{ // if constexpr (UPstream_basic_dataType<Type>::size(1) > 1)
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));
}
} }
// Consistent information for everyone int sendSize = static_cast<int>(sendData.size());
UPstream::broadcast(&dataMode, 1, comm);
// Note we let MPI_Gatherv copy back the local data as well...
UPstream::mpiGatherv
(
sendData.cdata(),
sendSize,
allData.data(),
recvCounts,
recvOffsets,
comm
);
} }
else
// Dispatch
switch (dataMode)
{ {
case 'b': // Byte-wise // Regular (manual) gathering
{ globalIndex::gather
UPstream::mpiGatherv (
( offsets_, // needed on master only
sendData.cdata_bytes(), comm,
sendData.size_bytes(), UPstream::allProcs(comm), // All communicator ranks
allData.data_bytes(), sendData,
recvCounts, allData,
recvOffsets, tag,
comm commsType
); );
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
} }
} }

View File

@ -43,6 +43,9 @@ SourceFiles
#include "bool.H" #include "bool.H"
#include "stdFoam.H" #include "stdFoam.H"
#include <string_view>
#include <string>
// Avoid any pre-processor conflicts with enum names // Avoid any pre-processor conflicts with enum names
#undef FALSE #undef FALSE
#undef TRUE #undef TRUE

View File

@ -58,6 +58,9 @@ Description
#include <algorithm> // std::copy #include <algorithm> // std::copy
#include <utility> // std::initializer_list #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) // \return location one-past end of dest (ie, the next destination)
static inline char* stringCopy(char* dest, const char* src); 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. //- Copy string characters into dest as NUL-terminated string.
// Forces conversion of std::sub_match to string form // Forces conversion of std::sub_match to string form
// //
@ -133,9 +141,17 @@ public:
template<class StringType> template<class StringType>
inline explicit CStringList(const UList<StringType>& input); 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 //- Copy construct from a list of sub-string references
// Copies the input characters. // Copies the input characters.
explicit CStringList(const SubStrings& input); inline explicit CStringList(const SubStrings& input);
//- Destructor. Invokes clear() to free memory. //- Destructor. Invokes clear() to free memory.
@ -157,6 +173,9 @@ public:
//- Return the number of C-strings (ie, argc) //- Return the number of C-strings (ie, argc)
int size() const noexcept { return 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 //- The flattened character content, with interspersed nul-chars
const char* cdata_bytes() const noexcept { return data_; } const char* cdata_bytes() const noexcept { return data_; }

View File

@ -28,16 +28,6 @@ License
#include "CStringList.H" #include "CStringList.H"
#include "Ostream.H" #include "Ostream.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::CStringList::CStringList(const SubStrings& input)
:
CStringList()
{
resetContent(input);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Largely identical to resetContent() except with 'c-string' // Largely identical to resetContent() except with 'c-string'

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2024 OpenCFD Ltd. Copyright (C) 2016-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. 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) inline char* Foam::CStringList::stringCopy(char *dest, const std::string& src)
{ {
dest = std::copy_n(src.data(), src.size(), dest); 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 * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
inline Foam::CStringList::~CStringList() inline Foam::CStringList::~CStringList()
@ -100,6 +135,12 @@ inline Foam::CStringList::~CStringList()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline std::string_view Foam::CStringList::view() const
{
return std::string_view(data_, nbytes_);
}
inline void Foam::CStringList::clear() inline void Foam::CStringList::clear()
{ {
argc_ = 0; argc_ = 0;

View File

@ -37,6 +37,7 @@ Description
#include <regex> // For std::ssub_match #include <regex> // For std::ssub_match
#include <memory> #include <memory>
#include <string_view>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -69,6 +69,7 @@ SourceFiles
#define Foam_regExpCxx_H #define Foam_regExpCxx_H
#include <regex> #include <regex>
#include <string_view>
#include <string> #include <string>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -54,6 +54,7 @@ SourceFiles
#include "Hasher.H" #include "Hasher.H"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <string_view>
#include <string> #include <string>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2017 OpenCFD Ltd. Copyright (C) 2017-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -46,85 +46,106 @@ namespace Foam
namespace stringOps namespace stringOps
{ {
//- 'Natural' compare for C-strings //- 'Natural' compare for C-strings
// Uses algorithm and code from Jan-Marten Spit <jmspit@euronet.nl> // Uses algorithm and code from Jan-Marten Spit <jmspit@euronet.nl>
// //
// In the 'natural' comparison, strings are compared alphabetically // In the 'natural' comparison, strings are compared alphabetically
// and numerically. Thus 'file010.txt' sorts after 'file2.txt' // and numerically. Thus 'file010.txt' sorts after 'file2.txt'
// //
// \param s1 left string // \param s1 left string
// \param s2 right 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 // \return -1 when s1 < s2, 0 when s1 == s2, 1 when s1 > s2
int natstrcmp(const char* s1, const char* s2); static inline int compare
(
const std::string& s1,
//- Encapsulation of natural order sorting for algorithms const std::string& s2
struct natural_sort )
{ {
//- Natural compare for std::string return stringOps::natstrcmp(s1.data(), s2.data());
// \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());
}
//- 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 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 stringOps
} // End namespace Foam } // End namespace Foam

View File

@ -28,33 +28,45 @@ License
#include "Pstream.H" #include "Pstream.H"
#include "PstreamGlobals.H" #include "PstreamGlobals.H"
#include "UPstreamWrapping.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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
static inline bool is_basic_dataType(Foam::UPstream::dataTypes id) noexcept namespace
{
inline bool is_nonAggregate(Foam::UPstream::dataTypes id) noexcept
{ {
return return
( (
int(id) >= int(Foam::UPstream::dataTypes::Basic_begin) int(id) >= int(Foam::UPstream::dataTypes::Basic_begin)
&& int(id) < int(Foam::UPstream::dataTypes::Basic_end) && 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 // Local function to print some error information
inline void printErrorNonIntrinsic inline void printErrorNonIntrinsic
( (
const char* context, const char* context,
UPstream::dataTypes dataTypeId Foam::UPstream::dataTypes dataTypeId
) )
{ {
using namespace Foam;
FatalError FatalError
<< "Bad input for " << context << ": likely a programming problem\n" << "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; << Foam::endl;
} }
@ -214,19 +226,37 @@ void Foam::UPstream::mpi_gatherv
{ {
MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
if // Runtime assert that we are not using aggregated data types
( if (FOAM_UNLIKELY(!is_nonAggregate(dataTypeId)))
FOAM_UNLIKELY
(
!is_basic_dataType(dataTypeId)
)
)
{ {
FatalErrorInFunction; FatalErrorInFunction;
printErrorNonIntrinsic("MPI_Gatherv()", dataTypeId); printErrorNonIntrinsic("MPI_Gatherv()", dataTypeId);
FatalError << Foam::abort(FatalError); 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 PstreamDetail::gatherv
( (
@ -235,6 +265,48 @@ void Foam::UPstream::mpi_gatherv
datatype, communicator 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); MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
if // Runtime assert that we are not using aggregated data types
( if (FOAM_UNLIKELY(!is_nonAggregate(dataTypeId)))
FOAM_UNLIKELY
(
!is_basic_dataType(dataTypeId)
)
)
{ {
FatalErrorInFunction; FatalErrorInFunction;
printErrorNonIntrinsic("MPI_Scatterv()", dataTypeId); printErrorNonIntrinsic("MPI_Scatterv()", dataTypeId);

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2020,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -189,6 +189,23 @@ public:
template<class TrackingData> template<class TrackingData>
inline bool equal(const deltaData&, TrackingData& td) const; inline bool equal(const deltaData&, TrackingData& td) const;
//- Interpolate between two values (lerp). Returns true if
//- causes changes. Not sure if needs to be specialised between
//- face and cell and what index is needed...
template<class TrackingData>
inline bool interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const deltaData& f0,
const label i1,
const deltaData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
);
// Member Operators // Member Operators
@ -296,6 +313,17 @@ public:
template<> template<>
struct is_contiguous<LESModels::smoothDelta::deltaData> : std::true_type {}; struct is_contiguous<LESModels::smoothDelta::deltaData> : std::true_type {};
//- Interpolation - used in e.g. cyclicAMI interpolation
inline LESModels::smoothDelta::deltaData lerp
(
const LESModels::smoothDelta::deltaData& a,
const LESModels::smoothDelta::deltaData& b,
const scalar t
)
{
return LESModels::smoothDelta::deltaData(lerp(a.delta(), b.delta(), t));
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd. Copyright (C) 2019,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -191,6 +191,40 @@ inline bool Foam::LESModels::smoothDelta::deltaData::equal
} }
template<class TrackingData>
inline bool Foam::LESModels::smoothDelta::deltaData::interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const deltaData& f0,
const label i1,
const deltaData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
)
{
if (f0.valid(td) && f1.valid(td))
{
const deltaData w2(lerp(f0.delta(), f1.delta(), weight));
return update(w2, 1.0, tol, td);
}
else if (f0.valid(td))
{
return update(f0, 1.0, tol, td);
}
else if (f1.valid(td))
{
return update(f1, 1.0, tol, td);
}
else
{
return false;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::LESModels::smoothDelta::deltaData::operator== inline bool Foam::LESModels::smoothDelta::deltaData::operator==

View File

@ -16,6 +16,6 @@ starcd/STARCDMeshWriter.C
polyDualMesh/polyDualMesh.C polyDualMesh/polyDualMesh.C
vtk/output/foamVtkSurfaceFieldWriter.C vtk/output/foamVtkSurfaceFieldWriter.cxx
LIB = $(FOAM_LIBBIN)/libconversion LIB = $(FOAM_LIBBIN)/libconversion

View File

@ -98,7 +98,7 @@ bool writeAreaField
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "ensightOutputAreaFieldTemplates.C" #include "ensightOutputAreaField.txx"
#endif #endif
#endif #endif

View File

@ -177,7 +177,7 @@ bool writePointField
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "ensightOutputVolFieldTemplates.C" #include "ensightOutputVolField.txx"
#endif #endif
#endif #endif

View File

@ -39,7 +39,7 @@ Note
SourceFiles SourceFiles
foamVtkToolsI.H foamVtkToolsI.H
foamVtkToolsTemplates.C foamVtkTools.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -358,7 +358,7 @@ void Foam::vtk::Tools::remapTuple<Foam::symmTensor>(double data[])
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkToolsTemplates.C" #include "foamVtkTools.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ Note
SourceFiles SourceFiles
foamVtkVtuAdaptorI.H foamVtkVtuAdaptorI.H
foamVtkVtuAdaptorTemplates.C foamVtkVtuAdaptor.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -156,7 +156,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkVtuAdaptorTemplates.C" #include "foamVtkVtuAdaptor.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -32,7 +32,7 @@ Description
Caution, currently only works properly for indirect patches. Caution, currently only works properly for indirect patches.
SourceFiles SourceFiles
foamVtkGenericPatchGeoFieldsWriter.C foamVtkGenericPatchGeoFieldsWriter.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -117,7 +117,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkGenericPatchGeoFieldsWriter.C" #include "foamVtkGenericPatchGeoFieldsWriter.txx"
#endif #endif

View File

@ -44,7 +44,7 @@ See Also
Foam::vtk::internalMeshWriter Foam::vtk::internalMeshWriter
SourceFiles SourceFiles
foamVtkInternalWriterTemplates.C foamVtkInternalWriter.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -183,7 +183,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkInternalWriterTemplates.C" #include "foamVtkInternalWriter.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -43,7 +43,7 @@ See Also
Foam::vtk::patchMeshWriter Foam::vtk::patchMeshWriter
SourceFiles SourceFiles
foamVtkPatchWriterTemplates.C foamVtkPatchWriter.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -202,7 +202,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkPatchWriterTemplates.C" #include "foamVtkPatchWriter.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -47,7 +47,7 @@ Note
may be addressed using ghost points. may be addressed using ghost points.
SourceFiles SourceFiles
surfaceFieldWriter.C foamVtkSurfaceFieldWriter.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2020,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -242,6 +242,23 @@ public:
template<class TrackingData> template<class TrackingData>
inline bool equal(const directionInfo&, TrackingData& td) const; inline bool equal(const directionInfo&, TrackingData& td) const;
//- Interpolate between two values (lerp). Returns true if
//- causes changes. Not sure if needs to be specialised between
//- face and cell and what index is needed...
template<class TrackingData>
inline bool interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const directionInfo& f0,
const label i1,
const directionInfo& f1,
const scalar weight,
const scalar tol,
TrackingData& td
);
// Member Operators // Member Operators

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -287,6 +287,35 @@ inline bool Foam::directionInfo::equal
} }
template<class TrackingData>
inline bool Foam::directionInfo::interpolate
(
const polyMesh& mesh,
const point& pt,
const label i0,
const directionInfo& f0,
const label i1,
const directionInfo& f1,
const scalar weight,
const scalar tol,
TrackingData& td
)
{
if (f0.valid(td))
{
return updateFace(mesh, -1, f0, tol, td);
}
if (f1.valid(td))
{
return updateFace(mesh, -1, f1, tol, td);
}
else
{
return false;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::directionInfo::operator== inline bool Foam::directionInfo::operator==

View File

@ -186,6 +186,23 @@ public:
TrackingData& td TrackingData& td
); );
//- Interpolate between two values (lerp). Returns true if
//- causes changes. Not sure if needs to be specialised between
//- face and cell and what index is needed...
template<class TrackingData>
inline bool interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const wallNormalInfo& f0,
const label i1,
const wallNormalInfo& f1,
const scalar weight,
const scalar tol,
TrackingData& td
);
//- Test for equality, with TrackingData //- Test for equality, with TrackingData
template<class TrackingData> template<class TrackingData>
inline bool equal(const wallNormalInfo&, TrackingData& td) const; inline bool equal(const wallNormalInfo&, TrackingData& td) const;

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -191,6 +191,35 @@ inline bool Foam::wallNormalInfo::equal
} }
template<class TrackingData>
inline bool Foam::wallNormalInfo::interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const wallNormalInfo& f0,
const label i1,
const wallNormalInfo& f1,
const scalar weight,
const scalar tol,
TrackingData& td
)
{
if (f0.valid(td))
{
return update(f0, td);
}
if (f1.valid(td))
{
return update(f1, td);
}
else
{
return false;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::wallNormalInfo::operator== inline bool Foam::wallNormalInfo::operator==

View File

@ -197,6 +197,23 @@ public:
template<class TrackingData> template<class TrackingData>
inline bool equal(const refinementData&, TrackingData& td) const; inline bool equal(const refinementData&, TrackingData& td) const;
//- Interpolate between two values (lerp). Returns true if
//- causes changes. Not sure if needs to be specialised between
//- face and cell and what index is needed...
template<class TrackingData>
inline bool interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const refinementData& f0,
const label i1,
const refinementData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
);
// Member Operators // Member Operators

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -248,6 +248,35 @@ inline bool Foam::refinementData::equal
} }
template<class TrackingData>
inline bool Foam::refinementData::interpolate
(
const polyMesh& mesh,
const point& pt,
const label i0,
const refinementData& f0,
const label i1,
const refinementData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
)
{
if (f0.valid(td))
{
return updateFace(mesh, -1, f0, tol, td);
}
if (f1.valid(td))
{
return updateFace(mesh, -1, f1, tol, td);
}
else
{
return false;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::refinementData::operator== inline bool Foam::refinementData::operator==

View File

@ -229,6 +229,23 @@ public:
inline bool equal(const refinementDistanceData&, TrackingData&) inline bool equal(const refinementDistanceData&, TrackingData&)
const; const;
//- Interpolate between two values (lerp). Returns true if
//- causes changes. Not sure if needs to be specialised between
//- face and cell and what index is needed...
template<class TrackingData>
inline bool interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const refinementDistanceData& f0,
const label i1,
const refinementDistanceData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
);
// Member Operators // Member Operators

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2020,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -278,6 +278,35 @@ inline bool Foam::refinementDistanceData::equal
} }
template<class TrackingData>
inline bool Foam::refinementDistanceData::interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const refinementDistanceData& f0,
const label i1,
const refinementDistanceData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
)
{
if (f0.valid(td))
{
return update(pt, f0, tol, td);
}
if (f1.valid(td))
{
return update(pt, f1, tol, td);
}
else
{
return false;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::refinementDistanceData::operator== inline bool Foam::refinementDistanceData::operator==

View File

@ -34,7 +34,7 @@ SourceFiles
ensightCase.C ensightCase.C
ensightCaseI.H ensightCaseI.H
ensightCaseOptions.C ensightCaseOptions.C
ensightCaseTemplates.C ensightCase.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -548,7 +548,7 @@ public:
#include "ensightCaseI.H" #include "ensightCaseI.H"
#ifdef NoRepository #ifdef NoRepository
#include "ensightCaseTemplates.C" #include "ensightCase.txx"
#endif #endif
#endif #endif

View File

@ -394,7 +394,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "ensightFileTemplates.C" #include "ensightFile.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -31,7 +31,7 @@ Description
SourceFiles SourceFiles
ensightOutput.C ensightOutput.C
ensightOutputTemplates.C ensightOutput.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -557,7 +557,7 @@ bool writeFaceLocalField
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "ensightOutputTemplates.C" #include "ensightOutput.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -38,7 +38,7 @@ Note
SourceFiles SourceFiles
ensightOutputSurface.C ensightOutputSurface.C
ensightOutputSurfaceTemplates.C ensightOutputSurface.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -136,7 +136,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "ensightOutputSurfaceTemplates.C" #include "ensightOutputSurface.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -42,8 +42,8 @@ Description
SourceFiles SourceFiles
foamVtkFileWriter.C foamVtkFileWriter.C
foamVtkFileWriter.txx
foamVtkFileWriterI.H foamVtkFileWriterI.H
foamVtkFileWriterTemplates.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -350,7 +350,7 @@ public:
#include "foamVtkFileWriterI.H" #include "foamVtkFileWriterI.H"
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkFileWriterTemplates.C" #include "foamVtkFileWriter.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2018-2023 OpenCFD Ltd. Copyright (C) 2018-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -64,13 +64,17 @@ namespace Foam
// 2. natural sort (name) // 2. natural sort (name)
struct seriesLess 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()); scalar val = compareOp<scalar>()(a.value(), b.value());
if (val == 0) if (val == 0)
{ {
return return stringOps::natural_sort::less(a.name(), b.name());
stringOps::natural_sort::compare(a.name(), b.name()) < 0;
} }
return val < 0; return val < 0;
} }
@ -78,7 +82,7 @@ namespace Foam
// Check if value is less than upper, with some tolerance. // 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); return (val < upper && Foam::mag(val - upper) > ROOTVSMALL);
} }

View File

@ -34,7 +34,8 @@ Description
SourceFiles SourceFiles
foamVtkFormatter.C foamVtkFormatter.C
foamVtkFormatterTemplates.C foamVtkFormatter.txx
foamVtkFormatterI.H
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -560,7 +561,7 @@ inline uint64_t sizeofData(label count)
#include "foamVtkFormatterI.H" #include "foamVtkFormatterI.H"
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkFormatterTemplates.C" #include "foamVtkFormatter.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -38,7 +38,8 @@ Description
SourceFiles SourceFiles
foamVtkOutput.C foamVtkOutput.C
foamVtkOutputTemplates.C foamVtkOutput.txx
foamVtkOutputI.H
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -352,7 +353,7 @@ namespace legacy
#include "foamVtkOutputI.H" #include "foamVtkOutputI.H"
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkOutputTemplates.C" #include "foamVtkOutput.txx"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -358,7 +358,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "vtkUnstructuredReaderTemplates.C" #include "vtkUnstructuredReader.txx"
#endif #endif

View File

@ -42,7 +42,7 @@ Note
SourceFiles SourceFiles
foamVtkPolyWriter.C foamVtkPolyWriter.C
foamVtkPolyWriterTemplates.C foamVtkPolyWriter.txx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -253,7 +253,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "foamVtkPolyWriterTemplates.C" #include "foamVtkPolyWriter.txx"
#endif #endif

View File

@ -12,7 +12,9 @@ License
Description Description
Add multi-region command-line options: Add multi-region command-line options:
-all-area-regions, -area-regions, -area-region -allAreas | -all-area-regions
-area-regions
-area-region
Required Classes Required Classes
- Foam::argList - Foam::argList
@ -25,9 +27,10 @@ See Also
{ {
Foam::argList::addBoolOption Foam::argList::addBoolOption
( (
"all-area-regions", "allAreas",
"Use all regions in finite-area regionProperties" "Use all regions in finite-area regionProperties"
); );
Foam::argList::addOptionCompat("allAreas", { "all-area-regions", 0 });
Foam::argList::addOption Foam::argList::addOption
( (
@ -41,8 +44,11 @@ See Also
( (
"area-region", "area-region",
"name", "name",
"Specify area-mesh region. Eg, -region shell" "Specify area-mesh region. Eg, -area-region shell"
); );
// TBD:
//? Foam::argList::addOptionCompat("area-region", { "areaRegion", 0 });
} }

View File

@ -15,7 +15,7 @@ Description
(-all-area-regions | -area-regions | -area-region) (-all-area-regions | -area-regions | -area-region)
Priority Priority
1. -all-area-regions 1. -all-area-regions (-allAreas)
2. -area-regions = specify multiple area regions to select, 2. -area-regions = specify multiple area regions to select,
or a single area region or a single area region
3. -area-region = specify a single area region 3. -area-region = specify a single area region
@ -46,12 +46,19 @@ See Also
wordList areaRegionNames; wordList areaRegionNames;
{ {
// Local alias
auto& names = areaRegionNames;
// Exit or fallback if nothing matches // Exit or fallback if nothing matches
constexpr bool exitOnNoMatches = false; constexpr bool exitOnNoMatches = false;
if (args.found("all-area-regions")) // Local aliases
auto& names = areaRegionNames;
const auto& fallback = Foam::polyMesh::defaultRegion;
if
(
// Handle both here (independent of which is an alias)
args.found("all-area-regions")
|| args.found("allAreas")
)
{ {
names = names =
( (
@ -78,16 +85,20 @@ wordList areaRegionNames;
else if else if
( (
wordRes select; wordRes select;
args.readListIfPresent<wordRe>("area-regions", select) (
// Handle both here (independent of which is an alias)
args.readListIfPresent<wordRe>("area-regions", select)
|| args.readListIfPresent<wordRe>("areaRegions", select)
)
) )
{ {
select.uniq(); // Normally a no-op select.uniq(); // Normally a no-op
if (select.size() == 1 && select.front().isLiteral()) if (select.size() == 1 && select[0].isLiteral())
{ {
// Identical to -area-region NAME // Identical to -area-region NAME
names.resize(1); names.resize(1);
names.front() = select.front(); names[0] = select[0];
} }
else if (select.size()) else if (select.size())
{ {
@ -119,12 +130,12 @@ wordList areaRegionNames;
} }
else else
{ {
InfoErr<< "... ignoring and using default region" InfoErr
<< "... ignoring and using default region"
<< nl << endl; << nl << endl;
// Arbitrary fallback, but can handle this further on
names.resize(1); names.resize(1);
names.front() = Foam::polyMesh::defaultRegion; names[0] = fallback;
} }
} }
else else
@ -162,7 +173,7 @@ wordList areaRegionNames;
else else
{ {
names.resize(1); names.resize(1);
names.front() = Foam::polyMesh::defaultRegion; names[0] = fallback;
InfoErr InfoErr
<< "Warning: No finite-area regionProperties, " << "Warning: No finite-area regionProperties, "
@ -171,17 +182,32 @@ wordList areaRegionNames;
} }
} }
} }
else if (args.found("area-region")) else
{ {
// Single region option or fallback
names.resize(1); names.resize(1);
names.front() = args.get<word>("area-region"); auto& name = names[0];
if
(
// Handle both here (independent of which is an alias)
!args.readIfPresent("area-region", name)
&& !args.readIfPresent("areaRegion", name)
)
{
name = fallback;
}
} }
// Fallback to defaultRegion // Final sanity checks and/or fallback
if (names.empty()) if (names.empty())
{ {
names.resize(1); names.resize(1);
names.front() = Foam::polyMesh::defaultRegion; names[0] = fallback;
}
else if (names.size() == 1 && names[0].empty())
{
names[0] = fallback;
} }
} }

View File

@ -227,9 +227,15 @@ bool Foam::cyclicACMIFvPatchField<Type>::all_ready() const
recvRequests_.start(), recvRequests_.start(),
recvRequests_.size() recvRequests_.size()
) )
&& UPstream::finishedRequests
(
recvRequests1_.start(),
recvRequests1_.size()
)
) )
{ {
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
++done; ++done;
} }
@ -240,9 +246,15 @@ bool Foam::cyclicACMIFvPatchField<Type>::all_ready() const
sendRequests_.start(), sendRequests_.start(),
sendRequests_.size() sendRequests_.size()
) )
&& UPstream::finishedRequests
(
sendRequests1_.start(),
sendRequests1_.size()
)
) )
{ {
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
++done; ++done;
} }
@ -260,9 +272,15 @@ bool Foam::cyclicACMIFvPatchField<Type>::ready() const
recvRequests_.start(), recvRequests_.start(),
recvRequests_.size() recvRequests_.size()
) )
&& UPstream::finishedRequests
(
recvRequests1_.start(),
recvRequests1_.size()
)
) )
{ {
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
if if
( (
@ -271,9 +289,15 @@ bool Foam::cyclicACMIFvPatchField<Type>::ready() const
sendRequests_.start(), sendRequests_.start(),
sendRequests_.size() sendRequests_.size()
) )
&& UPstream::finishedRequests
(
sendRequests1_.start(),
sendRequests1_.size()
)
) )
{ {
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
} }
return true; return true;
@ -483,7 +507,7 @@ void Foam::cyclicACMIFvPatchField<Type>::initEvaluate
const Field<Type> pnf(this->primitiveField(), nbrFaceCells); const Field<Type> pnf(this->primitiveField(), nbrFaceCells);
// Assert that all receives are known to have finished // Assert that all receives are known to have finished
if (!recvRequests_.empty()) if (!recvRequests_.empty() || !recvRequests1_.empty())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Outstanding recv request(s) on patch " << "Outstanding recv request(s) on patch "
@ -494,14 +518,20 @@ void Foam::cyclicACMIFvPatchField<Type>::initEvaluate
// Assume that sends are also OK // Assume that sends are also OK
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
cyclicACMIPatch_.initInterpolate cyclicACMIPatch_.initInterpolate
( (
pnf, pnf,
sendRequests_, sendRequests_,
sendBufs_,
recvRequests_, recvRequests_,
recvBufs_ sendBufs_,
recvBufs_,
sendRequests1_,
recvRequests1_,
sendBufs1_,
recvBufs1_
); );
} }
} }
@ -547,12 +577,15 @@ void Foam::cyclicACMIFvPatchField<Type>::evaluate
( (
Field<Type>::null(), // Not used for distributed Field<Type>::null(), // Not used for distributed
recvRequests_, recvRequests_,
recvBufs_ recvBufs_,
recvRequests1_,
recvBufs1_
).ptr() ).ptr()
); );
// Receive requests all handled by last function call // Receive requests all handled by last function call
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
if (doTransform()) if (doTransform())
{ {
@ -608,7 +641,7 @@ void Foam::cyclicACMIFvPatchField<Type>::initInterfaceMatrixUpdate
transformCoupleField(pnf, cmpt); transformCoupleField(pnf, cmpt);
// Assert that all receives are known to have finished // Assert that all receives are known to have finished
if (!recvRequests_.empty()) if (!recvRequests_.empty() || !recvRequests1_.empty())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Outstanding recv request(s) on patch " << "Outstanding recv request(s) on patch "
@ -619,14 +652,20 @@ void Foam::cyclicACMIFvPatchField<Type>::initInterfaceMatrixUpdate
// Assume that sends are also OK // Assume that sends are also OK
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
cyclicACMIPatch_.initInterpolate cyclicACMIPatch_.initInterpolate
( (
pnf, pnf,
sendRequests_, sendRequests_,
scalarSendBufs_,
recvRequests_, recvRequests_,
scalarRecvBufs_ scalarSendBufs_,
scalarRecvBufs_,
sendRequests1_,
recvRequests1_,
scalarSendBufs1_,
scalarRecvBufs1_
); );
} }
@ -681,11 +720,14 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
( (
solveScalarField::null(), // Not used for distributed solveScalarField::null(), // Not used for distributed
recvRequests_, recvRequests_,
scalarRecvBufs_ scalarRecvBufs_,
recvRequests1_,
scalarRecvBufs1_
); );
// Receive requests all handled by last function call // Receive requests all handled by last function call
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
} }
else else
{ {
@ -738,7 +780,7 @@ void Foam::cyclicACMIFvPatchField<Type>::initInterfaceMatrixUpdate
transformCoupleField(pnf); transformCoupleField(pnf);
// Assert that all receives are known to have finished // Assert that all receives are known to have finished
if (!recvRequests_.empty()) if (!recvRequests_.empty() || !recvRequests1_.empty())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Outstanding recv request(s) on patch " << "Outstanding recv request(s) on patch "
@ -749,14 +791,20 @@ void Foam::cyclicACMIFvPatchField<Type>::initInterfaceMatrixUpdate
// Assume that sends are also OK // Assume that sends are also OK
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
cyclicACMIPatch_.initInterpolate cyclicACMIPatch_.initInterpolate
( (
pnf, pnf,
sendRequests_, sendRequests_,
sendBufs_,
recvRequests_, recvRequests_,
recvBufs_ sendBufs_,
recvBufs_,
sendRequests1_,
recvRequests1_,
sendBufs1_,
recvBufs1_
); );
} }
@ -798,11 +846,14 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
( (
Field<Type>::null(), // Not used for distributed Field<Type>::null(), // Not used for distributed
recvRequests_, recvRequests_,
recvBufs_ recvBufs_,
recvRequests1_,
recvBufs1_
); );
// Receive requests all handled by last function call // Receive requests all handled by last function call
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
} }
else else
{ {

View File

@ -102,6 +102,28 @@ class cyclicACMIFvPatchField
//- Scalar receive buffers //- Scalar receive buffers
mutable PtrList<List<solveScalar>> scalarRecvBufs_; mutable PtrList<List<solveScalar>> scalarRecvBufs_;
// Only used for AMI caching
//- Current range of send requests (non-blocking)
mutable labelRange sendRequests1_;
//- Current range of recv requests (non-blocking)
mutable labelRange recvRequests1_;
//- Send buffers
mutable PtrList<List<Type>> sendBufs1_;
//- Receive buffers_
mutable PtrList<List<Type>> recvBufs1_;
//- Scalar send buffers
mutable PtrList<List<solveScalar>> scalarSendBufs1_;
//- Scalar receive buffers
mutable PtrList<List<solveScalar>> scalarRecvBufs1_;
//- Neighbour coupled internal cell data //- Neighbour coupled internal cell data
mutable autoPtr<Field<Type>> patchNeighbourFieldPtr_; mutable autoPtr<Field<Type>> patchNeighbourFieldPtr_;

View File

@ -207,9 +207,15 @@ bool Foam::cyclicAMIFvPatchField<Type>::all_ready() const
recvRequests_.start(), recvRequests_.start(),
recvRequests_.size() recvRequests_.size()
) )
&& UPstream::finishedRequests
(
recvRequests1_.start(),
recvRequests1_.size()
)
) )
{ {
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
++done; ++done;
} }
@ -220,9 +226,15 @@ bool Foam::cyclicAMIFvPatchField<Type>::all_ready() const
sendRequests_.start(), sendRequests_.start(),
sendRequests_.size() sendRequests_.size()
) )
&& UPstream::finishedRequests
(
sendRequests1_.start(),
sendRequests1_.size()
)
) )
{ {
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
++done; ++done;
} }
@ -240,9 +252,15 @@ bool Foam::cyclicAMIFvPatchField<Type>::ready() const
recvRequests_.start(), recvRequests_.start(),
recvRequests_.size() recvRequests_.size()
) )
&& UPstream::finishedRequests
(
recvRequests1_.start(),
recvRequests1_.size()
)
) )
{ {
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
if if
( (
@ -251,9 +269,15 @@ bool Foam::cyclicAMIFvPatchField<Type>::ready() const
sendRequests_.start(), sendRequests_.start(),
sendRequests_.size() sendRequests_.size()
) )
&& UPstream::finishedRequests
(
sendRequests1_.start(),
sendRequests1_.size()
)
) )
{ {
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
} }
return true; return true;
@ -319,9 +343,18 @@ Foam::cyclicAMIFvPatchField<Type>::getNeighbourField
template<class Type> template<class Type>
bool Foam::cyclicAMIFvPatchField<Type>::cacheNeighbourField() bool Foam::cyclicAMIFvPatchField<Type>::cacheNeighbourField() const
{ {
return (FieldBase::localBoundaryConsistency() != 0); // const auto& AMI = this->ownerAMI();
// if (AMI.cacheActive())
// {
// return false;
// }
// else
{
return (FieldBase::localBoundaryConsistency() != 0);
}
} }
@ -350,11 +383,12 @@ Foam::cyclicAMIFvPatchField<Type>::getPatchNeighbourField
} }
const auto& fvp = this->patch(); const auto& fvp = this->patch();
const auto& mesh = fvp.boundaryMesh().mesh();
if if
( (
patchNeighbourFieldPtr_ patchNeighbourFieldPtr_
&& !fvp.boundaryMesh().mesh().upToDatePoints(this->internalField()) && !mesh.upToDatePoints(this->internalField())
) )
{ {
//DebugPout //DebugPout
@ -418,7 +452,8 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::tmp<Foam::Field<Type>>
Foam::cyclicAMIFvPatchField<Type>::patchNeighbourField() const Foam::cyclicAMIFvPatchField<Type>::patchNeighbourField() const
{ {
return this->getPatchNeighbourField(true); // checkCommunicator = true // checkCommunicator = true
return this->getPatchNeighbourField(true);
} }
@ -491,7 +526,7 @@ void Foam::cyclicAMIFvPatchField<Type>::initEvaluate
const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch();
// Assert that all receives are known to have finished // Assert that all receives are known to have finished
if (!recvRequests_.empty()) if (!recvRequests_.empty() || !recvRequests1_.empty())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Outstanding recv request(s) on patch " << "Outstanding recv request(s) on patch "
@ -502,14 +537,20 @@ void Foam::cyclicAMIFvPatchField<Type>::initEvaluate
// Assume that sends are also OK // Assume that sends are also OK
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
cpp.initInterpolate cpp.initInterpolate
( (
pnf, pnf,
sendRequests_, sendRequests_,
sendBufs_,
recvRequests_, recvRequests_,
recvBufs_ sendBufs_,
recvBufs_,
sendRequests1_,
recvRequests1_,
sendBufs1_,
recvBufs1_
); );
} }
} }
@ -562,12 +603,15 @@ void Foam::cyclicAMIFvPatchField<Type>::evaluate
Field<Type>::null(), // Not used for distributed Field<Type>::null(), // Not used for distributed
recvRequests_, recvRequests_,
recvBufs_, recvBufs_,
recvRequests1_,
recvBufs1_,
defaultValues defaultValues
).ptr() ).ptr()
); );
// Receive requests all handled by last function call // Receive requests all handled by last function call
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
if (doTransform()) if (doTransform())
{ {
@ -618,7 +662,7 @@ void Foam::cyclicAMIFvPatchField<Type>::initInterfaceMatrixUpdate
const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch();
// Assert that all receives are known to have finished // Assert that all receives are known to have finished
if (!recvRequests_.empty()) if (!recvRequests_.empty() || !recvRequests1_.empty())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Outstanding recv request(s) on patch " << "Outstanding recv request(s) on patch "
@ -629,14 +673,20 @@ void Foam::cyclicAMIFvPatchField<Type>::initInterfaceMatrixUpdate
// Assume that sends are also OK // Assume that sends are also OK
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
cpp.initInterpolate cpp.initInterpolate
( (
pnf, pnf,
sendRequests_, sendRequests_,
scalarSendBufs_,
recvRequests_, recvRequests_,
scalarRecvBufs_ scalarSendBufs_,
scalarRecvBufs_,
sendRequests1_,
recvRequests1_,
scalarSendBufs1_,
scalarRecvBufs1_
); );
} }
@ -691,11 +741,14 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
solveScalarField::null(), // Not used for distributed solveScalarField::null(), // Not used for distributed
recvRequests_, recvRequests_,
scalarRecvBufs_, scalarRecvBufs_,
recvRequests1_,
scalarRecvBufs1_,
defaultValues defaultValues
); );
// Receive requests all handled by last function call // Receive requests all handled by last function call
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
} }
else else
{ {
@ -757,7 +810,7 @@ void Foam::cyclicAMIFvPatchField<Type>::initInterfaceMatrixUpdate
const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch(); const cyclicAMIPolyPatch& cpp = cyclicAMIPatch_.cyclicAMIPatch();
// Assert that all receives are known to have finished // Assert that all receives are known to have finished
if (!recvRequests_.empty()) if (!recvRequests_.empty() || !recvRequests1_.empty())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Outstanding recv request(s) on patch " << "Outstanding recv request(s) on patch "
@ -768,14 +821,20 @@ void Foam::cyclicAMIFvPatchField<Type>::initInterfaceMatrixUpdate
// Assume that sends are also OK // Assume that sends are also OK
sendRequests_.clear(); sendRequests_.clear();
sendRequests1_.clear();
cpp.initInterpolate cpp.initInterpolate
( (
pnf, pnf,
sendRequests_, sendRequests_,
sendBufs_,
recvRequests_, recvRequests_,
recvBufs_ sendBufs_,
recvBufs_,
sendRequests1_,
recvRequests1_,
sendBufs1_,
recvBufs1_
); );
} }
@ -829,11 +888,14 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
Field<Type>::null(), // Not used for distributed Field<Type>::null(), // Not used for distributed
recvRequests_, recvRequests_,
recvBufs_, recvBufs_,
recvRequests1_,
recvBufs1_,
defaultValues defaultValues
); );
// Receive requests all handled by last function call // Receive requests all handled by last function call
recvRequests_.clear(); recvRequests_.clear();
recvRequests1_.clear();
} }
else else
{ {
@ -918,7 +980,7 @@ void Foam::cyclicAMIFvPatchField<Type>::manipulateMatrix
} }
// Set internalCoeffs and boundaryCoeffs in the assembly matrix // Set internalCoeffs and boundaryCoeffs in the assembly matrix
// on clyclicAMI patches to be used in the individual matrix by // on cyclicAMI patches to be used in the individual matrix by
// matrix.flux() // matrix.flux()
if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name())) if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name()))
{ {

View File

@ -113,6 +113,28 @@ class cyclicAMIFvPatchField
//- Scalar receive buffers //- Scalar receive buffers
mutable PtrList<List<solveScalar>> scalarRecvBufs_; mutable PtrList<List<solveScalar>> scalarRecvBufs_;
// Only used for AMI caching
//- Current range of send requests (non-blocking)
mutable labelRange sendRequests1_;
//- Current range of recv requests (non-blocking)
mutable labelRange recvRequests1_;
//- Send buffers
mutable PtrList<List<Type>> sendBufs1_;
//- Receive buffers_
mutable PtrList<List<Type>> recvBufs1_;
//- Scalar send buffers
mutable PtrList<List<solveScalar>> scalarSendBufs1_;
//- Scalar receive buffers
mutable PtrList<List<solveScalar>> scalarRecvBufs1_;
//- Neighbour coupled internal cell data //- Neighbour coupled internal cell data
mutable autoPtr<Field<Type>> patchNeighbourFieldPtr_; mutable autoPtr<Field<Type>> patchNeighbourFieldPtr_;
@ -134,7 +156,7 @@ class cyclicAMIFvPatchField
virtual bool all_ready() const; virtual bool all_ready() const;
//- Use neighbour field caching //- Use neighbour field caching
static bool cacheNeighbourField(); bool cacheNeighbourField() const;
//- Return neighbour coupled internal cell data //- Return neighbour coupled internal cell data
tmp<Field<Type>> getNeighbourField(const UList<Type>&) const; tmp<Field<Type>> getNeighbourField(const UList<Type>&) const;

View File

@ -209,6 +209,23 @@ public:
template<class TrackingData> template<class TrackingData>
inline bool equal(const smoothData&, TrackingData& td) const; inline bool equal(const smoothData&, TrackingData& td) const;
//- Interpolate between two values (lerp). Returns true if
//- causes changes. Not sure if needs to be specialised between
//- face and cell and what index is needed...
template<class TrackingData>
inline bool interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const smoothData& f0,
const label i1,
const smoothData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
);
// Member Operators // Member Operators

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation Copyright (C) 2011-2013 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020,2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -191,6 +191,45 @@ inline bool Foam::smoothData::equal
} }
template<class TrackingData>
inline bool Foam::smoothData::interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const smoothData& f0,
const label i1,
const smoothData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
)
{
// TBD. What to interpolate? Do we have a position? cell/face centre?
if (!valid(td))
{
if (f0.valid(td))
{
operator=(f0);
}
else
{
operator=(f1);
}
}
else if (f0.valid(td))
{
operator=(f0);
}
else
{
operator=(f1);
}
return true;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::smoothData::operator== inline bool Foam::smoothData::operator==

View File

@ -207,6 +207,23 @@ public:
template<class TrackingData> template<class TrackingData>
inline bool equal(const sweepData&, TrackingData& td) const; inline bool equal(const sweepData&, TrackingData& td) const;
//- Interpolate between two values (lerp). Returns true if
//- causes changes. Not sure if needs to be specialised between
//- face and cell and what index is needed...
template<class TrackingData>
inline bool interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const sweepData& f0,
const label i1,
const sweepData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
);
// Member Operators // Member Operators

View File

@ -210,6 +210,45 @@ inline bool Foam::sweepData::equal
} }
template<class TrackingData>
inline bool Foam::sweepData::interpolate
(
const polyMesh&,
const point& pt,
const label i0,
const sweepData& f0,
const label i1,
const sweepData& f1,
const scalar weight,
const scalar tol,
TrackingData& td
)
{
// TBD. What to interpolate? Do we have a position? cell/face centre?
if (!valid(td))
{
if (f0.valid(td))
{
operator=(f0);
}
else
{
operator=(f1);
}
}
else if (f0.valid(td))
{
operator=(f0);
}
else
{
operator=(f1);
}
return true;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::sweepData::operator== inline bool Foam::sweepData::operator==

Some files were not shown because too many files have changed in this diff Show More