Compare commits
13 Commits
temp-probe
...
rpmbuild-2
| Author | SHA1 | Date | |
|---|---|---|---|
| ecff1d2339 | |||
| 0bb5c6e0b3 | |||
| e17d8c92d7 | |||
| b147078b30 | |||
| ecd61f0e68 | |||
| c423ebecc1 | |||
| 8fe025cb8e | |||
| 313b1f71f1 | |||
| 61cd298928 | |||
| 286de9dde9 | |||
| bd5021e31c | |||
| 1fc9313c97 | |||
| aff5c3b680 |
@ -1,2 +1,2 @@
|
||||
api=2306
|
||||
patch=0
|
||||
patch=240625
|
||||
|
||||
14
doc/Build.md
14
doc/Build.md
@ -1,23 +1,23 @@
|
||||
## Getting the code
|
||||
|
||||
Links to all code packs are available on https://dl.openfoam.com. For OpenFOAM-v2212:
|
||||
Links to all code packs are available on https://dl.openfoam.com. For OpenFOAM-v2306:
|
||||
|
||||
- https://dl.openfoam.com/source/latest/
|
||||
- Source: https://dl.openfoam.com/source/v2212/OpenFOAM-v2212.tgz
|
||||
- ThirdParty: https://dl.openfoam.com/source/v2212/ThirdParty-v2212.tgz
|
||||
- Source: https://dl.openfoam.com/source/v2306/OpenFOAM-v2306.tgz
|
||||
- ThirdParty: https://dl.openfoam.com/source/v2306/ThirdParty-v2306.tgz
|
||||
|
||||
## OpenFOAM® Quick Build Guide
|
||||
|
||||
Prior to building, ensure that the [system requirements][link openfoam-require]
|
||||
are satisfied (including any special [cross-compiling][wiki-cross-compile]
|
||||
considerations), and source the correct OpenFOAM environment.
|
||||
For example, for the OpenFOAM-v2212 version:
|
||||
For example, for the OpenFOAM-v2306 version:
|
||||
```
|
||||
source <installation path>/OpenFOAM-v2212/etc/bashrc
|
||||
source <installation path>/OpenFOAM-v2306/etc/bashrc
|
||||
```
|
||||
e.g. if installed under the `~/openfoam` directory
|
||||
```
|
||||
source ~/openfoam/OpenFOAM-v2212/etc/bashrc
|
||||
source ~/openfoam/OpenFOAM-v2306/etc/bashrc
|
||||
```
|
||||
|
||||
|
||||
@ -157,4 +157,4 @@ More details in the [ThirdParty build guide][link third-build].
|
||||
[wiki-config]: https://develop.openfoam.com/Development/openfoam/-/wikis/configuring
|
||||
|
||||
---
|
||||
Copyright 2019-2022 OpenCFD Ltd
|
||||
Copyright 2019-2023 OpenCFD Ltd
|
||||
|
||||
@ -24,6 +24,7 @@ $(fileOps)/fileOperation/fileOperationRanks.C
|
||||
$(fileOps)/fileOperation/fileOperationInitialise.C
|
||||
$(fileOps)/dummyFileOperation/dummyFileOperation.C
|
||||
$(fileOps)/uncollatedFileOperation/uncollatedFileOperation.C
|
||||
$(fileOps)/uncollatedFileOperation/hostUncollatedFileOperation.C
|
||||
$(fileOps)/masterUncollatedFileOperation/masterUncollatedFileOperation.C
|
||||
$(fileOps)/collatedFileOperation/collatedFileOperation.C
|
||||
$(fileOps)/collatedFileOperation/hostCollatedFileOperation.C
|
||||
|
||||
@ -176,10 +176,11 @@ makeBoundary
|
||||
new SlicedPatchField<Type>
|
||||
(
|
||||
p,
|
||||
DimensionedField<Type, GeoMesh>::null(),
|
||||
bField[patchi]
|
||||
DimensionedField<Type, GeoMesh>::null()
|
||||
)
|
||||
);
|
||||
|
||||
bf[patchi].UList<Type>::shallowCopy(bField[patchi]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -538,6 +538,10 @@ inline Foam::Tensor<Cmpt> Foam::Tensor<Cmpt>::inv2D
|
||||
|
||||
|
||||
template<class Cmpt>
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround for gcc (11+) that fails to handle tensor dot vector
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
inline Foam::Tensor<Cmpt>
|
||||
Foam::Tensor<Cmpt>::inner(const Tensor<Cmpt>& t2) const
|
||||
{
|
||||
@ -561,6 +565,10 @@ Foam::Tensor<Cmpt>::inner(const Tensor<Cmpt>& t2) const
|
||||
|
||||
|
||||
template<class Cmpt>
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround for gcc (11+) that fails to handle tensor dot vector
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
inline Foam::Tensor<Cmpt>
|
||||
Foam::Tensor<Cmpt>::schur(const Tensor<Cmpt>& t2) const
|
||||
{
|
||||
@ -1103,6 +1111,10 @@ operator&(const Tensor<Cmpt>& t1, const Tensor<Cmpt>& t2)
|
||||
|
||||
//- Inner-product of a SphericalTensor and a Tensor
|
||||
template<class Cmpt>
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround for gcc (11+) that fails to handle tensor dot vector
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
inline Tensor<Cmpt>
|
||||
operator&(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
|
||||
{
|
||||
@ -1117,6 +1129,10 @@ operator&(const SphericalTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
|
||||
|
||||
//- Inner-product of a Tensor and a SphericalTensor
|
||||
template<class Cmpt>
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround for gcc (11+) that fails to handle tensor dot vector
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
inline Tensor<Cmpt>
|
||||
operator&(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
|
||||
{
|
||||
@ -1131,6 +1147,10 @@ operator&(const Tensor<Cmpt>& t1, const SphericalTensor<Cmpt>& st2)
|
||||
|
||||
//- Inner-product of a SymmTensor and a Tensor
|
||||
template<class Cmpt>
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround for gcc (11+) that fails to handle tensor dot vector
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
inline Tensor<Cmpt>
|
||||
operator&(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
|
||||
{
|
||||
@ -1153,6 +1173,10 @@ operator&(const SymmTensor<Cmpt>& st1, const Tensor<Cmpt>& t2)
|
||||
|
||||
//- Inner-product of a Tensor and a SymmTensor
|
||||
template<class Cmpt>
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround for gcc (11+) that fails to handle tensor dot vector
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
inline Tensor<Cmpt>
|
||||
operator&(const Tensor<Cmpt>& t1, const SymmTensor<Cmpt>& st2)
|
||||
{
|
||||
@ -1193,6 +1217,10 @@ operator&(const Tensor<Cmpt>& t, const Vector<Cmpt>& v)
|
||||
|
||||
//- Inner-product of a Vector and a Tensor
|
||||
template<class Cmpt>
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround for gcc (11+) that fails to handle tensor dot vector
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
inline Vector<Cmpt>
|
||||
operator&(const Vector<Cmpt>& v, const Tensor<Cmpt>& t)
|
||||
{
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -122,7 +122,8 @@ std::string Foam::fileFormats::NASCore::nextNasField
|
||||
(
|
||||
const std::string& str,
|
||||
std::string::size_type& pos,
|
||||
std::string::size_type len
|
||||
const std::string::size_type width,
|
||||
const bool free_format
|
||||
)
|
||||
{
|
||||
const auto beg = pos;
|
||||
@ -130,15 +131,23 @@ std::string Foam::fileFormats::NASCore::nextNasField
|
||||
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
pos = beg + len; // Continue after field width
|
||||
if (free_format)
|
||||
{
|
||||
// Nothing left
|
||||
pos = str.size();
|
||||
return str.substr(beg);
|
||||
}
|
||||
|
||||
// Fixed format - continue after field width
|
||||
pos = beg + width;
|
||||
return str.substr(beg, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (end - beg); // Efffective width
|
||||
pos = end + 1; // Continue after comma
|
||||
// Free format - continue after comma
|
||||
pos = end + 1;
|
||||
return str.substr(beg, (end - beg));
|
||||
}
|
||||
|
||||
return str.substr(beg, len);
|
||||
}
|
||||
|
||||
|
||||
@ -235,8 +244,8 @@ void Foam::fileFormats::NASCore::writeCoord
|
||||
// 2 ID : point ID - requires starting index of 1
|
||||
// 3 CP : coordinate system ID (blank)
|
||||
// 4 X1 : point x coordinate
|
||||
// 5 X2 : point x coordinate
|
||||
// 6 X3 : point x coordinate
|
||||
// 5 X2 : point y coordinate
|
||||
// 6 X3 : point z coordinate
|
||||
// 7 CD : coordinate system for displacements (blank)
|
||||
// 8 PS : single point constraints (blank)
|
||||
// 9 SEID : super-element ID
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -47,7 +47,6 @@ SourceFiles
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace fileFormats
|
||||
{
|
||||
|
||||
@ -73,18 +72,18 @@ public:
|
||||
//- Output load format
|
||||
enum loadFormat
|
||||
{
|
||||
PLOAD2,
|
||||
PLOAD4
|
||||
PLOAD2, //!< Face load (eg, pressure)
|
||||
PLOAD4 //!< Vertex load
|
||||
};
|
||||
|
||||
//- Selection names for the NASTRAN file field formats
|
||||
//- Selection names for the NASTRAN load formats
|
||||
static const Enum<loadFormat> loadFormatNames;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
NASCore() = default;
|
||||
NASCore() noexcept = default;
|
||||
|
||||
|
||||
// Public Static Member Functions
|
||||
@ -92,18 +91,20 @@ public:
|
||||
//- Extract numbers from things like "-2.358-8" (same as "-2.358e-8")
|
||||
static scalar readNasScalar(const std::string& str);
|
||||
|
||||
//- A string::substr() to handle fixed-format and free-format NASTRAN.
|
||||
// Returns the substr to the next comma (if found) or the given length
|
||||
//
|
||||
// \param str The string to extract from
|
||||
// \param pos On input, the position of the first character of the
|
||||
// substring. On output, advances to the next position to use.
|
||||
// \param len The fixed-format length to use if a comma is not found.
|
||||
//- A std::string::substr() variant to handle fixed-format and
|
||||
//- free-format NASTRAN.
|
||||
// Returns the substr until the next comma (if found)
|
||||
// or the given fixed width
|
||||
static std::string nextNasField
|
||||
(
|
||||
//! The string to extract from
|
||||
const std::string& str,
|
||||
//! [in,out] The parse position within \p str
|
||||
std::string::size_type& pos,
|
||||
std::string::size_type len
|
||||
//! The fixed-format width to use (if comma is not found)
|
||||
const std::string::size_type width,
|
||||
//! The input is known to be free-format
|
||||
const bool free_format = false
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@ Foam::functionObjects::thermoCoupleProbes::thermoCoupleProbes
|
||||
}
|
||||
else
|
||||
{
|
||||
Ttc_ = prober().sample(thermo_.T());
|
||||
Ttc_ = probes::sample(thermo_.T());
|
||||
}
|
||||
|
||||
// Note: can only create the solver once all samples have been found
|
||||
@ -89,7 +89,7 @@ Foam::functionObjects::thermoCoupleProbes::thermoCoupleProbes
|
||||
|
||||
Foam::label Foam::functionObjects::thermoCoupleProbes::nEqns() const
|
||||
{
|
||||
return prober().size();
|
||||
return this->size();
|
||||
}
|
||||
|
||||
|
||||
@ -108,21 +108,19 @@ void Foam::functionObjects::thermoCoupleProbes::derivatives
|
||||
scalarField Cpc(y.size(), Zero);
|
||||
scalarField kappac(y.size(), Zero);
|
||||
|
||||
const auto& p = prober();
|
||||
|
||||
if (radiationFieldName_ != "none")
|
||||
{
|
||||
G = p.sample(mesh_.lookupObject<volScalarField>(radiationFieldName_));
|
||||
G = sample(mesh_.lookupObject<volScalarField>(radiationFieldName_));
|
||||
}
|
||||
|
||||
Tc = p.sample(thermo_.T());
|
||||
Tc = probes::sample(thermo_.T());
|
||||
|
||||
Uc = mag(p.sample(mesh_.lookupObject<volVectorField>(UName_)));
|
||||
Uc = mag(this->sample(mesh_.lookupObject<volVectorField>(UName_)));
|
||||
|
||||
rhoc = p.sample(thermo_.rho()());
|
||||
kappac = p.sample(thermo_.kappa()());
|
||||
muc = p.sample(thermo_.mu()());
|
||||
Cpc = p.sample(thermo_.Cp()());
|
||||
rhoc = this->sample(thermo_.rho()());
|
||||
kappac = this->sample(thermo_.kappa()());
|
||||
muc = this->sample(thermo_.mu()());
|
||||
Cpc = this->sample(thermo_.Cp()());
|
||||
|
||||
scalarField Re(rhoc*Uc*d_/muc);
|
||||
scalarField Pr(Cpc*muc/kappac);
|
||||
@ -165,7 +163,7 @@ void Foam::functionObjects::thermoCoupleProbes::jacobian
|
||||
|
||||
bool Foam::functionObjects::thermoCoupleProbes::write()
|
||||
{
|
||||
if (!prober().empty())
|
||||
if (!pointField::empty())
|
||||
{
|
||||
(void) prepare(ACTION_WRITE);
|
||||
|
||||
@ -184,7 +182,7 @@ bool Foam::functionObjects::thermoCoupleProbes::write()
|
||||
|
||||
bool Foam::functionObjects::thermoCoupleProbes::execute()
|
||||
{
|
||||
if (!prober().empty())
|
||||
if (!pointField::empty())
|
||||
{
|
||||
scalar dt = mesh_.time().deltaTValue();
|
||||
scalar t = mesh_.time().value();
|
||||
|
||||
@ -42,8 +42,7 @@ void Foam::functionObjects::thermoCoupleProbes::writeValues
|
||||
|
||||
os << setw(w) << timeValue;
|
||||
|
||||
const pointField& probes = prober().probeLocations();
|
||||
forAll(probes, probei)
|
||||
forAll(*this, probei)
|
||||
{
|
||||
// if (includeOutOfBounds_ || processor_[probei] != -1)
|
||||
{
|
||||
|
||||
@ -96,7 +96,7 @@ Foam::ConeInjection<CloudType>::ConeInjection
|
||||
this->coeffDict().subDict("sizeDistribution"), owner.rndGen()
|
||||
)
|
||||
),
|
||||
nInjected_(this->parcelsAddedTotal()),
|
||||
nInjected_(Pstream::master() ? this->parcelsAddedTotal() : 0),
|
||||
injectorOrder_(identity(positionAxis_.size())),
|
||||
tanVec1_(),
|
||||
tanVec2_()
|
||||
@ -233,7 +233,7 @@ Foam::label Foam::ConeInjection<CloudType>::parcelsToInject
|
||||
const label targetParcels =
|
||||
ceil(positionAxis_.size()*parcelsPerInjector_*volumeFraction);
|
||||
|
||||
return targetParcels - nInjected_;
|
||||
return targetParcels - returnReduce(nInjected_, sumOp<label>());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1387,6 +1387,7 @@ Foam::label Foam::snappyRefineDriver::refinementInterfaceRefine
|
||||
(
|
||||
face2i != facei
|
||||
&& surfaceIndex[face2i] != -1
|
||||
&& cutter.faceLevel(face2i) > cLevel
|
||||
)
|
||||
{
|
||||
// Get outwards pointing normal
|
||||
|
||||
@ -614,6 +614,12 @@ void Foam::advancingFrontAMI::write(Ostream& os) const
|
||||
faceAreaIntersect::triangulationModeNames_[faceAreaIntersect::tmMesh],
|
||||
faceAreaIntersect::triangulationModeNames_[triMode_]
|
||||
);
|
||||
os.writeEntryIfDifferent<word>
|
||||
(
|
||||
"areaNormalisationMode",
|
||||
areaNormalisationModeNames_[areaNormalisationMode::project],
|
||||
areaNormalisationModeNames_[areaNormalisationMode_]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -383,8 +383,8 @@ void Foam::cyclicAMIPolyPatch::resetAMI(const UList<point>& points) const
|
||||
}
|
||||
|
||||
const cyclicAMIPolyPatch& nbr = neighbPatch();
|
||||
pointField srcPoints(localPoints());
|
||||
pointField nbrPoints(nbr.localPoints());
|
||||
const pointField srcPoints(points, meshPoints());
|
||||
pointField nbrPoints(points, nbr.meshPoints());
|
||||
|
||||
Info<< "AMI: Creating AMI for source:" << name()
|
||||
<< " and target:" << nbr.name() << endl;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2017 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -62,13 +62,17 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
|
||||
while (is.good())
|
||||
{
|
||||
string::size_type linei = 0; // parsing position within current line
|
||||
string line;
|
||||
is.getLine(line);
|
||||
|
||||
if (line.empty() || line[0] == '$')
|
||||
if (line.empty())
|
||||
{
|
||||
continue; // Skip empty or comment
|
||||
continue; // Ignore empty
|
||||
}
|
||||
else if (line[0] == '$')
|
||||
{
|
||||
// Ignore comment
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if character 72 is continuation
|
||||
@ -94,41 +98,69 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
}
|
||||
|
||||
|
||||
// Parsing position within current line
|
||||
std::string::size_type linei = 0;
|
||||
|
||||
// Is free format if line contains a comma
|
||||
const bool freeFormat = line.contains(',');
|
||||
|
||||
// First word (column 0-8)
|
||||
const word cmd(word::validate(nextNasField(line, linei, 8)));
|
||||
|
||||
if (cmd == "CBEAM" || cmd == "CROD")
|
||||
{
|
||||
// discard elementId (8-16)
|
||||
(void) nextNasField(line, linei, 8); // 8-16
|
||||
// discard groupId (16-24)
|
||||
(void) nextNasField(line, linei, 8); // 16-24
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : group id
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
|
||||
label a = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
label b = readLabel(nextNasField(line, linei, 8)); // 32-40
|
||||
// discard elementId
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
// discard groupId
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
|
||||
dynEdges.append(edge(a,b));
|
||||
label a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
dynEdges.emplace_back(a,b);
|
||||
}
|
||||
else if (cmd == "PLOTEL")
|
||||
{
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : vertex
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
|
||||
// discard elementId (8-16)
|
||||
(void) nextNasField(line, linei, 8); // 8-16
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
|
||||
label a = readLabel(nextNasField(line, linei, 8)); // 16-24
|
||||
label b = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
label a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
dynEdges.append(edge(a,b));
|
||||
dynEdges.emplace_back(a,b);
|
||||
}
|
||||
else if (cmd == "GRID")
|
||||
{
|
||||
label index = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
(void) nextNasField(line, linei, 8); // 16-24
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8)); // 24-32
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8)); // 32-40
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8)); // 40-48
|
||||
// Fixed (short) format:
|
||||
// 8-16 : point id
|
||||
// 16-24 : coordinate system (unsupported)
|
||||
// 24-32 : point x coordinate
|
||||
// 32-40 : point y coordinate
|
||||
// 40-48 : point z coordinate
|
||||
// 48-56 : displacement coordinate system (optional, unsupported)
|
||||
// 56-64 : single point constraints (optional, unsupported)
|
||||
// 64-70 : super-element id (optional, unsupported)
|
||||
|
||||
pointId.append(index);
|
||||
dynPoints.append(point(x, y, z));
|
||||
label index = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
pointId.push_back(index);
|
||||
dynPoints.emplace_back(x, y, z);
|
||||
}
|
||||
else if (cmd == "GRID*")
|
||||
{
|
||||
@ -138,6 +170,8 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
// GRID* 126 0 -5.55999875E+02 -5.68730474E+02
|
||||
// * 2.14897901E+02
|
||||
|
||||
// Cannot be long format and free format at the same time!
|
||||
|
||||
label index = readLabel(nextNasField(line, linei, 16)); // 8-24
|
||||
(void) nextNasField(line, linei, 16); // 24-40
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
|
||||
@ -157,8 +191,8 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
(void) nextNasField(line, linei, 8); // 0-8
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 16)); // 8-16
|
||||
|
||||
pointId.append(index);
|
||||
dynPoints.append(point(x, y, z));
|
||||
pointId.push_back(index);
|
||||
dynPoints.emplace_back(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2013-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2019-202i3 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -38,24 +38,22 @@ namespace Foam
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
const filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::filmModelType&
|
||||
filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::
|
||||
filmModel() const
|
||||
filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::filmModel() const
|
||||
{
|
||||
HashTable<const filmModelType*> models
|
||||
= db().time().lookupClass<filmModelType>();
|
||||
const auto models = db().time().lookupClass<filmModelType>();
|
||||
|
||||
DynamicList<word> modelNames(models.size());
|
||||
forAllConstIters(models, iter)
|
||||
{
|
||||
if (iter()->regionMesh().name() == filmRegionName_)
|
||||
const auto& model = *(iter.val());
|
||||
const word& modelName = model.regionMesh().name();
|
||||
|
||||
if (modelName == filmRegionName_)
|
||||
{
|
||||
return *iter();
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
DynamicList<word> modelNames;
|
||||
forAllConstIters(models, iter)
|
||||
{
|
||||
modelNames.append(iter()->regionMesh().name());
|
||||
modelNames.push_back(modelName);
|
||||
}
|
||||
|
||||
FatalErrorInFunction
|
||||
@ -69,24 +67,22 @@ filmModel() const
|
||||
|
||||
const filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::
|
||||
pyrolysisModelType&
|
||||
filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::
|
||||
pyrModel() const
|
||||
filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::pyrModel() const
|
||||
{
|
||||
HashTable<const pyrolysisModelType*> models =
|
||||
db().time().lookupClass<pyrolysisModelType>();
|
||||
const auto models = db().time().lookupClass<pyrolysisModelType>();
|
||||
|
||||
DynamicList<word> modelNames(models.size());
|
||||
forAllConstIters(models, iter)
|
||||
{
|
||||
if (iter()->regionMesh().name() == pyrolysisRegionName_)
|
||||
const auto& model = *(iter.val());
|
||||
const word& modelName = model.regionMesh().name();
|
||||
|
||||
if (modelName == pyrolysisRegionName_)
|
||||
{
|
||||
return *iter();
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
DynamicList<word> modelNames;
|
||||
forAllConstIters(models, iter)
|
||||
{
|
||||
modelNames.append(iter()->regionMesh().name());
|
||||
modelNames.push_back(modelName);
|
||||
}
|
||||
|
||||
FatalErrorInFunction
|
||||
@ -233,13 +229,9 @@ void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::rmap
|
||||
{
|
||||
mixedFvPatchScalarField::rmap(ptf, addr);
|
||||
|
||||
const filmPyrolysisRadiativeCoupledMixedFvPatchScalarField& tiptf =
|
||||
refCast
|
||||
<
|
||||
const filmPyrolysisRadiativeCoupledMixedFvPatchScalarField
|
||||
>(ptf);
|
||||
const auto& fpptf = refCast<const myType>(ptf);
|
||||
|
||||
temperatureCoupledBase::rmap(tiptf, addr);
|
||||
temperatureCoupledBase::rmap(fpptf, addr);
|
||||
}
|
||||
|
||||
|
||||
@ -251,8 +243,7 @@ void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::updateCoeffs()
|
||||
}
|
||||
|
||||
// Get the coupling information from the mappedPatchBase
|
||||
const mappedPatchBase& mpp =
|
||||
refCast<const mappedPatchBase>(patch().patch());
|
||||
const auto& mpp = refCast<const mappedPatchBase>(patch().patch());
|
||||
|
||||
const label patchi = patch().index();
|
||||
const label nbrPatchi = mpp.samplePolyPatch().index();
|
||||
@ -264,10 +255,7 @@ void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::updateCoeffs()
|
||||
scalarField intFld(patchInternalField());
|
||||
|
||||
const auto& nbrField =
|
||||
refCast
|
||||
<
|
||||
const filmPyrolysisRadiativeCoupledMixedFvPatchScalarField
|
||||
>
|
||||
refCast<const myType>
|
||||
(
|
||||
nbrPatch.lookupPatchField<volScalarField>(TnbrName_)
|
||||
);
|
||||
@ -285,7 +273,7 @@ void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::updateCoeffs()
|
||||
scalarField KDeltaNbr(nbrK*nbrPatch.deltaCoeffs());
|
||||
mpp.distribute(KDeltaNbr);
|
||||
|
||||
scalarField myKDelta(K*patch().deltaCoeffs());
|
||||
const scalarField myKDelta(K*patch().deltaCoeffs());
|
||||
|
||||
scalarList Tfilm(patch().size(), Zero);
|
||||
scalarList htcwfilm(patch().size(), Zero);
|
||||
@ -298,22 +286,78 @@ void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::updateCoeffs()
|
||||
scalarField qr(patch().size(), Zero);
|
||||
|
||||
label coupledPatchi = -1;
|
||||
label filmPatchi = -1;
|
||||
if (pyrolysisRegionName_ == mesh.name())
|
||||
{
|
||||
// Working on the pyrolysis mesh
|
||||
|
||||
coupledPatchi = patchi;
|
||||
if (qrName_ != "none")
|
||||
{
|
||||
qr = nbrPatch.lookupPatchField<volScalarField>(qrName_);
|
||||
mpp.distribute(qr);
|
||||
}
|
||||
|
||||
filmPatchi = pyrolysis.nbrCoupledPatchID(film, coupledPatchi);
|
||||
|
||||
const scalarField htcw(film.htcw().h()().boundaryField()[filmPatchi]);
|
||||
|
||||
// Obtain htcw
|
||||
htcwfilm =
|
||||
pyrolysis.mapRegionPatchField
|
||||
(
|
||||
film,
|
||||
coupledPatchi,
|
||||
filmPatchi,
|
||||
htcw,
|
||||
true
|
||||
);
|
||||
|
||||
// Obtain Tfilm at the boundary through Ts.
|
||||
// NOTE: Tf is not good as at the boundary it will retrieve Tp
|
||||
const scalarField Ts(film.Ts().boundaryField()[filmPatchi]);
|
||||
Tfilm =
|
||||
pyrolysis.mapRegionPatchField
|
||||
(
|
||||
film,
|
||||
coupledPatchi,
|
||||
filmPatchi,
|
||||
Ts,
|
||||
true
|
||||
);
|
||||
|
||||
// Obtain delta
|
||||
filmDelta =
|
||||
pyrolysis.mapRegionPatchField<scalar>
|
||||
(
|
||||
film,
|
||||
"deltaf",
|
||||
coupledPatchi,
|
||||
true
|
||||
);
|
||||
}
|
||||
else if (pyrolysis.primaryMesh().name() == mesh.name())
|
||||
{
|
||||
// Working on the primary mesh
|
||||
|
||||
coupledPatchi = nbrPatch.index();
|
||||
if (qrName_ != "none")
|
||||
{
|
||||
qr = patch().lookupPatchField<volScalarField>(qrName_);
|
||||
}
|
||||
|
||||
filmPatchi = pyrolysis.nbrCoupledPatchID(film, coupledPatchi);
|
||||
|
||||
htcwfilm = film.htcw().h()().boundaryField()[filmPatchi];
|
||||
film.toPrimary(filmPatchi, htcwfilm);
|
||||
|
||||
// Obtain Tfilm at the boundary through Ts.
|
||||
// NOTE: Tf is not good as at the boundary it will retrieve Tp
|
||||
Tfilm = film.Ts().boundaryField()[filmPatchi];
|
||||
film.toPrimary(filmPatchi, Tfilm);
|
||||
|
||||
filmDelta = film.delta().boundaryField()[filmPatchi];
|
||||
film.toPrimary(filmPatchi, filmDelta);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -323,39 +367,8 @@ void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::updateCoeffs()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
const label filmPatchi = pyrolysis.nbrCoupledPatchID(film, coupledPatchi);
|
||||
|
||||
const scalarField htcw(film.htcw().h()().boundaryField()[filmPatchi]);
|
||||
|
||||
// Obtain htcw
|
||||
htcwfilm =
|
||||
pyrolysis.mapRegionPatchField
|
||||
(
|
||||
film,
|
||||
coupledPatchi,
|
||||
filmPatchi,
|
||||
htcw,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
// Obtain Tfilm at the boundary through Ts.
|
||||
// NOTE: Tf is not good as at the boundary it will retrieve Tp
|
||||
Tfilm = film.Ts().boundaryField()[filmPatchi];
|
||||
film.toPrimary(filmPatchi, Tfilm);
|
||||
|
||||
// Obtain delta
|
||||
filmDelta =
|
||||
pyrolysis.mapRegionPatchField<scalar>
|
||||
(
|
||||
film,
|
||||
"deltaf",
|
||||
coupledPatchi,
|
||||
true
|
||||
);
|
||||
|
||||
// Estimate wetness of the film (1: wet , 0: dry)
|
||||
scalarField ratio
|
||||
const scalarField ratio
|
||||
(
|
||||
min
|
||||
(
|
||||
@ -368,14 +381,11 @@ void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::updateCoeffs()
|
||||
)
|
||||
);
|
||||
|
||||
scalarField qConv(ratio*htcwfilm*(Tfilm - Tp)*convectiveScaling_);
|
||||
|
||||
scalarField qRad((1.0 - ratio)*qr);
|
||||
|
||||
scalarField alpha(KDeltaNbr - (qRad + qConv)/Tp);
|
||||
const scalarField qConv(ratio*htcwfilm*(Tfilm - Tp)*convectiveScaling_);
|
||||
const scalarField qRad((1.0 - ratio)*qr);
|
||||
const scalarField alpha(KDeltaNbr - (qRad + qConv)/Tp);
|
||||
|
||||
valueFraction() = alpha/(alpha + (1.0 - ratio)*myKDelta);
|
||||
|
||||
refValue() = ratio*Tfilm + (1.0 - ratio)*(KDeltaNbr*nbrIntFld)/alpha;
|
||||
|
||||
mixedFvPatchScalarField::updateCoeffs();
|
||||
|
||||
@ -110,6 +110,8 @@ public:
|
||||
typedef Foam::regionModels::pyrolysisModels::pyrolysisModel
|
||||
pyrolysisModelType;
|
||||
|
||||
typedef filmPyrolysisRadiativeCoupledMixedFvPatchScalarField myType;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
probes/pointProbers/pointProberBase.C
|
||||
probes/pointProbers/internalPointProber.C
|
||||
probes/pointProbers/patchPointProber.C
|
||||
probes/probes.C
|
||||
probes/patchProbes.C
|
||||
|
||||
|
||||
@ -834,15 +834,15 @@ Foam::meshToMesh::mapTgtToSrc
|
||||
label srcPatchi = srcPatchID_[i];
|
||||
label tgtPatchi = tgtPatchID_[i];
|
||||
|
||||
if (!srcPatchFields.set(tgtPatchi))
|
||||
if (!srcPatchFields.set(srcPatchi))
|
||||
{
|
||||
srcPatchFields.set
|
||||
(
|
||||
srcPatchi,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
tgtBfld[srcPatchi],
|
||||
srcMesh.boundary()[tgtPatchi],
|
||||
tgtBfld[tgtPatchi],
|
||||
srcMesh.boundary()[srcPatchi],
|
||||
DimensionedField<Type, volMesh>::null(),
|
||||
directFvPatchFieldMapper
|
||||
(
|
||||
|
||||
@ -1,328 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "ProbesBase.H"
|
||||
#include "IOmanip.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Prober>
|
||||
void Foam::ProbesBase<Prober>::createProbeFiles(const wordList& fieldNames)
|
||||
{
|
||||
// Open new output streams
|
||||
|
||||
bool needsNewFiles = false;
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
if (!probeFilePtrs_.found(fieldName))
|
||||
{
|
||||
needsNewFiles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsNewFiles && Pstream::master())
|
||||
{
|
||||
DebugInfo
|
||||
<< "Probing fields: " << fieldNames << nl
|
||||
<< "Probing locations: " << prober_.probeLocations() << nl
|
||||
<< endl;
|
||||
|
||||
// Put in undecomposed case
|
||||
// (Note: gives problems for distributed data running)
|
||||
|
||||
fileName probeDir
|
||||
(
|
||||
mesh_.time().globalPath()
|
||||
/ functionObject::outputPrefix
|
||||
/ name()/mesh_.regionName()
|
||||
// Use startTime as the instance for output files
|
||||
/ mesh_.time().timeName(mesh_.time().startTime().value())
|
||||
);
|
||||
probeDir.clean(); // Remove unneeded ".."
|
||||
|
||||
// Create directory if needed
|
||||
Foam::mkDir(probeDir);
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
if (probeFilePtrs_.found(fieldName))
|
||||
{
|
||||
// Safety
|
||||
continue;
|
||||
}
|
||||
|
||||
auto osPtr = autoPtr<OFstream>::New(probeDir/fieldName);
|
||||
auto& os = *osPtr;
|
||||
|
||||
probeFilePtrs_.insert(fieldName, osPtr);
|
||||
|
||||
DebugInfo<< "open probe stream: " << os.name() << endl;
|
||||
|
||||
const unsigned int width(IOstream::defaultPrecision() + 7);
|
||||
|
||||
const pointField& probeLocs = prober_.probeLocations();
|
||||
const labelList& processors = prober_.processors();
|
||||
const labelList& patchIDList = prober_.patchIDList();
|
||||
const pointField& oldPoints = prober_.oldPoints();
|
||||
|
||||
forAll(probeLocs, probei)
|
||||
{
|
||||
os << "# Probe " << probei << ' ' << probeLocs[probei];
|
||||
|
||||
if (processors[probei] == -1)
|
||||
{
|
||||
os << " # Not Found";
|
||||
}
|
||||
else if (probei < patchIDList.size())
|
||||
{
|
||||
const label patchi = patchIDList[probei];
|
||||
if (patchi != -1)
|
||||
{
|
||||
const polyBoundaryMesh& bm = mesh_.boundaryMesh();
|
||||
if
|
||||
(
|
||||
patchi < bm.nNonProcessor()
|
||||
|| processors[probei] == Pstream::myProcNo()
|
||||
)
|
||||
{
|
||||
os << " at patch " << bm[patchi].name();
|
||||
}
|
||||
os << " with a distance of "
|
||||
<< mag(probeLocs[probei]-oldPoints[probei])
|
||||
<< " m to the original point "
|
||||
<< oldPoints[probei];
|
||||
}
|
||||
}
|
||||
|
||||
os << nl;
|
||||
}
|
||||
|
||||
os << '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
<< "Probe";
|
||||
|
||||
forAll(probeLocs, probei)
|
||||
{
|
||||
if (prober_.includeOutOfBounds() || processors[probei] != -1)
|
||||
{
|
||||
os << ' ' << setw(width) << probei;
|
||||
}
|
||||
}
|
||||
os << nl;
|
||||
|
||||
os << '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
<< "Time" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Prober>
|
||||
Foam::label Foam::ProbesBase<Prober>::prepare(unsigned request)
|
||||
{
|
||||
// Prefilter on selection
|
||||
HashTable<wordHashSet> selected =
|
||||
(
|
||||
loadFromFiles_
|
||||
? IOobjectList(mesh_, mesh_.time().timeName()).classes(fieldSelection_)
|
||||
: mesh_.classes(fieldSelection_)
|
||||
);
|
||||
|
||||
// Classify and count fields
|
||||
label nFields = 0;
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(InputType, Target) \
|
||||
{ \
|
||||
Target.clear(); /* Remove old values */ \
|
||||
const auto iter = selected.cfind(InputType::typeName); \
|
||||
if (iter.good()) \
|
||||
{ \
|
||||
/* Add new (current) values */ \
|
||||
Target.append(iter.val().sortedToc()); \
|
||||
nFields += Target.size(); \
|
||||
} \
|
||||
}
|
||||
|
||||
doLocalCode(volScalarField, scalarFields_);
|
||||
doLocalCode(volVectorField, vectorFields_)
|
||||
doLocalCode(volSphericalTensorField, sphericalTensorFields_);
|
||||
doLocalCode(volSymmTensorField, symmTensorFields_);
|
||||
doLocalCode(volTensorField, tensorFields_);
|
||||
|
||||
doLocalCode(surfaceScalarField, surfaceScalarFields_);
|
||||
doLocalCode(surfaceVectorField, surfaceVectorFields_);
|
||||
doLocalCode(surfaceSphericalTensorField, surfaceSphericalTensorFields_);
|
||||
doLocalCode(surfaceSymmTensorField, surfaceSymmTensorFields_);
|
||||
doLocalCode(surfaceTensorField, surfaceTensorFields_);
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
|
||||
|
||||
// Adjust file streams
|
||||
if (Pstream::master())
|
||||
{
|
||||
wordHashSet currentFields(2*nFields);
|
||||
currentFields.insert(scalarFields_);
|
||||
currentFields.insert(vectorFields_);
|
||||
currentFields.insert(sphericalTensorFields_);
|
||||
currentFields.insert(symmTensorFields_);
|
||||
currentFields.insert(tensorFields_);
|
||||
|
||||
currentFields.insert(surfaceScalarFields_);
|
||||
currentFields.insert(surfaceVectorFields_);
|
||||
currentFields.insert(surfaceSphericalTensorFields_);
|
||||
currentFields.insert(surfaceSymmTensorFields_);
|
||||
currentFields.insert(surfaceTensorFields_);
|
||||
|
||||
DebugInfo
|
||||
<< "Probing fields: " << currentFields << nl
|
||||
<< "Probing locations: " << prober_.probeLocations() << nl
|
||||
<< endl;
|
||||
|
||||
// Close streams for fields that no longer exist
|
||||
forAllIters(probeFilePtrs_, iter)
|
||||
{
|
||||
if (!currentFields.erase(iter.key()))
|
||||
{
|
||||
DebugInfo<< "close probe stream: " << iter()->name() << endl;
|
||||
|
||||
probeFilePtrs_.remove(iter);
|
||||
}
|
||||
}
|
||||
|
||||
if ((request & ACTION_WRITE) && !currentFields.empty())
|
||||
{
|
||||
createProbeFiles(currentFields.sortedToc());
|
||||
}
|
||||
}
|
||||
|
||||
return nFields;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Prober>
|
||||
Foam::ProbesBase<Prober>::ProbesBase
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict,
|
||||
const bool loadFromFiles,
|
||||
const bool readFields
|
||||
)
|
||||
:
|
||||
functionObjects::fvMeshFunctionObject(name, runTime, dict),
|
||||
prober_(mesh_, dict),
|
||||
loadFromFiles_(loadFromFiles),
|
||||
verbose_(false),
|
||||
onExecute_(false),
|
||||
fieldSelection_()
|
||||
{
|
||||
if (readFields)
|
||||
{
|
||||
read(dict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Prober>
|
||||
bool Foam::ProbesBase<Prober>::verbose(const bool on) noexcept
|
||||
{
|
||||
bool old(verbose_);
|
||||
verbose_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
template<class Prober>
|
||||
bool Foam::ProbesBase<Prober>::read(const dictionary& dict)
|
||||
{
|
||||
dict.readEntry("fields", fieldSelection_);
|
||||
|
||||
verbose_ = dict.getOrDefault("verbose", false);
|
||||
onExecute_ = dict.getOrDefault("sampleOnExecute", false);
|
||||
|
||||
// Close old (ununsed) streams
|
||||
prepare(ACTION_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Prober>
|
||||
bool Foam::ProbesBase<Prober>::performAction(unsigned request)
|
||||
{
|
||||
if (!prober_.empty() && request && prepare(request))
|
||||
{
|
||||
performAction(scalarFields_, request);
|
||||
performAction(vectorFields_, request);
|
||||
performAction(sphericalTensorFields_, request);
|
||||
performAction(symmTensorFields_, request);
|
||||
performAction(tensorFields_, request);
|
||||
|
||||
performAction(surfaceScalarFields_, request);
|
||||
performAction(surfaceVectorFields_, request);
|
||||
performAction(surfaceSphericalTensorFields_, request);
|
||||
performAction(surfaceSymmTensorFields_, request);
|
||||
performAction(surfaceTensorFields_, request);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Prober>
|
||||
bool Foam::ProbesBase<Prober>::execute()
|
||||
{
|
||||
if (onExecute_)
|
||||
{
|
||||
return performAction(ACTION_ALL & ~ACTION_WRITE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Prober>
|
||||
bool Foam::ProbesBase<Prober>::write()
|
||||
{
|
||||
return performAction(ACTION_ALL);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,239 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::ProbesBase
|
||||
|
||||
Description
|
||||
Base class for sampling fields at specified locations and writing to file.
|
||||
The locations are specified and determined in the derived class. The
|
||||
sampling is done using the specified point prober class.
|
||||
|
||||
SourceFiles
|
||||
ProbesBase.C
|
||||
ProbesBaseTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_ProbesBase_H
|
||||
#define Foam_ProbesBase_H
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "polyMesh.H"
|
||||
#include "HashPtrTable.H"
|
||||
#include "OFstream.H"
|
||||
#include "volFieldsFwd.H"
|
||||
#include "surfaceFieldsFwd.H"
|
||||
#include "pointProberBase.H"
|
||||
#include "IOobjectList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class ProbesBase Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Prober>
|
||||
class ProbesBase
|
||||
:
|
||||
public functionObjects::fvMeshFunctionObject
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The specified point prober
|
||||
Prober prober_;
|
||||
|
||||
|
||||
// Protected Classes
|
||||
|
||||
//- Grouping of field names by GeometricField type
|
||||
template<class GeoField>
|
||||
struct fieldGroup : public DynamicList<word> {};
|
||||
|
||||
|
||||
// Data Types
|
||||
|
||||
//- Local control for sampling actions
|
||||
enum sampleActionType : unsigned
|
||||
{
|
||||
ACTION_NONE = 0,
|
||||
ACTION_WRITE = 0x1,
|
||||
ACTION_STORE = 0x2,
|
||||
ACTION_ALL = 0xF
|
||||
};
|
||||
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Load fields from files (not from objectRegistry)
|
||||
bool loadFromFiles_;
|
||||
|
||||
//- Output verbosity
|
||||
bool verbose_;
|
||||
|
||||
//- Perform sample actions on execute as well
|
||||
bool onExecute_;
|
||||
|
||||
//- Requested names of fields to probe
|
||||
wordRes fieldSelection_;
|
||||
|
||||
|
||||
// Calculated
|
||||
|
||||
//- Current list of field names selected for sampling
|
||||
DynamicList<word> selectedFieldNames_;
|
||||
|
||||
//- Categorized scalar/vector/tensor volume fields
|
||||
fieldGroup<volScalarField> scalarFields_;
|
||||
fieldGroup<volVectorField> vectorFields_;
|
||||
fieldGroup<volSphericalTensorField> sphericalTensorFields_;
|
||||
fieldGroup<volSymmTensorField> symmTensorFields_;
|
||||
fieldGroup<volTensorField> tensorFields_;
|
||||
|
||||
//- Categorized scalar/vector/tensor surface fields
|
||||
fieldGroup<surfaceScalarField> surfaceScalarFields_;
|
||||
fieldGroup<surfaceVectorField> surfaceVectorFields_;
|
||||
fieldGroup<surfaceSphericalTensorField> surfaceSphericalTensorFields_;
|
||||
fieldGroup<surfaceSymmTensorField> surfaceSymmTensorFields_;
|
||||
fieldGroup<surfaceTensorField> surfaceTensorFields_;
|
||||
|
||||
//- Current open files (non-empty on master only)
|
||||
HashPtrTable<OFstream> probeFilePtrs_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Classify field types, close/open file streams
|
||||
// \return number of fields to sample
|
||||
label prepare(unsigned request);
|
||||
|
||||
//- Get from registry or load from disk
|
||||
template<class GeoField>
|
||||
tmp<GeoField> getOrLoadField(const word& fieldName) const;
|
||||
|
||||
//- Store results: min/max/average/size
|
||||
template<class Type>
|
||||
void storeResults(const word& fieldName, const Field<Type>& values);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Create new streams as required
|
||||
void createProbeFiles(const wordList& fieldNames);
|
||||
|
||||
//- Write field values
|
||||
template<class Type>
|
||||
void writeValues
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
);
|
||||
|
||||
//- Sample and store/write all applicable sampled fields
|
||||
template<class GeoField>
|
||||
void performAction
|
||||
(
|
||||
const fieldGroup<GeoField>& fieldNames, /* must be sorted */
|
||||
unsigned request
|
||||
);
|
||||
|
||||
//- Perform sampling action with store/write
|
||||
bool performAction(unsigned request);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
ProbesBase
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict,
|
||||
const bool loadFromFiles = false,
|
||||
const bool readFields = true
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~ProbesBase() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Enable/disable verbose output
|
||||
// \return old value
|
||||
bool verbose(const bool on) noexcept;
|
||||
|
||||
//- Return names of fields to probe
|
||||
virtual const wordRes& fieldNames() const noexcept
|
||||
{
|
||||
return fieldSelection_;
|
||||
}
|
||||
|
||||
//- Return const reference to the point prober
|
||||
const Prober& prober() const noexcept { return prober_; }
|
||||
|
||||
//- Read the settings from the dictionary
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
//- Sample and store result if the sampleOnExecute is enabled.
|
||||
virtual bool execute();
|
||||
|
||||
//- Sample and write
|
||||
virtual bool write();
|
||||
|
||||
//- Update for changes of mesh due to readUpdate
|
||||
virtual void readUpdate(const polyMesh::readUpdateState state)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ProbesBase.C"
|
||||
#include "ProbesBaseTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2025 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,6 +27,11 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "patchProbes.H"
|
||||
#include "volFields.H"
|
||||
#include "IOmanip.H"
|
||||
#include "mappedPatchBase.H"
|
||||
#include "treeBoundBox.H"
|
||||
#include "treeDataFace.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -34,6 +39,7 @@ License
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(patchProbes, 0);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
functionObject,
|
||||
@ -42,6 +48,179 @@ namespace Foam
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::patchProbes::findElements(const fvMesh& mesh)
|
||||
{
|
||||
(void)mesh.tetBasePtIs();
|
||||
|
||||
const polyBoundaryMesh& bm = mesh.boundaryMesh();
|
||||
|
||||
// All the info for nearest. Construct to miss
|
||||
List<mappedPatchBase::nearInfo> nearest(this->size());
|
||||
|
||||
const labelList patchIDs(bm.patchSet(patchNames_).sortedToc());
|
||||
|
||||
label nFaces = 0;
|
||||
forAll(patchIDs, i)
|
||||
{
|
||||
nFaces += bm[patchIDs[i]].size();
|
||||
}
|
||||
|
||||
if (nFaces > 0)
|
||||
{
|
||||
// Collect mesh faces and bounding box
|
||||
labelList bndFaces(nFaces);
|
||||
treeBoundBox overallBb;
|
||||
|
||||
nFaces = 0;
|
||||
forAll(patchIDs, i)
|
||||
{
|
||||
const polyPatch& pp = bm[patchIDs[i]];
|
||||
forAll(pp, i)
|
||||
{
|
||||
bndFaces[nFaces++] = pp.start()+i;
|
||||
const face& f = pp[i];
|
||||
|
||||
// Without reduction.
|
||||
overallBb.add(pp.points(), f);
|
||||
}
|
||||
}
|
||||
|
||||
Random rndGen(123456);
|
||||
overallBb.inflate(rndGen, 1e-4, ROOTVSMALL);
|
||||
|
||||
|
||||
const indexedOctree<treeDataFace> boundaryTree
|
||||
(
|
||||
treeDataFace(mesh, bndFaces), // patch faces only
|
||||
|
||||
overallBb, // overall search domain
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
);
|
||||
|
||||
forAll(probeLocations(), probei)
|
||||
{
|
||||
const auto& treeData = boundaryTree.shapes();
|
||||
const point sample = probeLocations()[probei];
|
||||
|
||||
pointIndexHit info = boundaryTree.findNearest
|
||||
(
|
||||
sample,
|
||||
Foam::sqr(boundaryTree.bb().mag())
|
||||
);
|
||||
|
||||
if (!info.hit())
|
||||
{
|
||||
info = boundaryTree.findNearest(sample, Foam::sqr(GREAT));
|
||||
}
|
||||
|
||||
const label facei = treeData.objectIndex(info.index());
|
||||
|
||||
const label patchi = bm.whichPatch(facei);
|
||||
|
||||
if (isA<emptyPolyPatch>(bm[patchi]))
|
||||
{
|
||||
WarningInFunction
|
||||
<< " The sample point: " << sample
|
||||
<< " belongs to " << patchi
|
||||
<< " which is an empty patch. This is not permitted. "
|
||||
<< " This sample will not be included "
|
||||
<< endl;
|
||||
}
|
||||
else if (info.hit())
|
||||
{
|
||||
// Note: do we store the face centre or the actual nearest?
|
||||
// We interpolate using the faceI only though (no
|
||||
// interpolation) so it does not actually matter much, just for
|
||||
// the location written to the header.
|
||||
|
||||
//const point& facePt = mesh.faceCentres()[faceI];
|
||||
const point& facePt = info.point();
|
||||
|
||||
mappedPatchBase::nearInfo sampleInfo;
|
||||
|
||||
sampleInfo.first() = pointIndexHit(true, facePt, facei);
|
||||
|
||||
sampleInfo.second().first() = facePt.distSqr(sample);
|
||||
sampleInfo.second().second() = Pstream::myProcNo();
|
||||
|
||||
nearest[probei] = sampleInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find nearest - globally consistent
|
||||
Pstream::listCombineReduce(nearest, mappedPatchBase::nearestEqOp());
|
||||
|
||||
oldPoints_.resize(this->size());
|
||||
|
||||
// Update actual probe locations and store old ones
|
||||
forAll(nearest, samplei)
|
||||
{
|
||||
oldPoints_[samplei] = operator[](samplei);
|
||||
operator[](samplei) = nearest[samplei].first().point();
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << nl;
|
||||
forAll(nearest, samplei)
|
||||
{
|
||||
label proci = nearest[samplei].second().second();
|
||||
label locali = nearest[samplei].first().index();
|
||||
|
||||
Info<< " " << samplei << " coord:"<< operator[](samplei)
|
||||
<< " found on processor:" << proci
|
||||
<< " in local face:" << locali
|
||||
<< " with location:" << nearest[samplei].first().point()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract any local faces to sample:
|
||||
// - operator[] : actual point to sample (=nearest point on patch)
|
||||
// - oldPoints_ : original provided point (might be anywhere in the mesh)
|
||||
// - elementList_ : cells, not used
|
||||
// - faceList_ : faces (now patch faces)
|
||||
// - patchIDList_ : patch corresponding to faceList
|
||||
// - processor_ : processor
|
||||
elementList_.resize_nocopy(nearest.size());
|
||||
elementList_ = -1;
|
||||
|
||||
faceList_.resize_nocopy(nearest.size());
|
||||
faceList_ = -1;
|
||||
|
||||
processor_.resize_nocopy(nearest.size());
|
||||
processor_ = -1;
|
||||
|
||||
patchIDList_.resize_nocopy(nearest.size());
|
||||
patchIDList_ = -1;
|
||||
|
||||
forAll(nearest, sampleI)
|
||||
{
|
||||
processor_[sampleI] = nearest[sampleI].second().second();
|
||||
|
||||
if (nearest[sampleI].second().second() == Pstream::myProcNo())
|
||||
{
|
||||
// Store the face to sample
|
||||
faceList_[sampleI] = nearest[sampleI].first().index();
|
||||
const label facei = faceList_[sampleI];
|
||||
if (facei != -1)
|
||||
{
|
||||
processor_[sampleI] = Pstream::myProcNo();
|
||||
patchIDList_[sampleI] = bm.whichPatch(facei);
|
||||
}
|
||||
}
|
||||
reduce(processor_[sampleI], maxOp<label>());
|
||||
reduce(patchIDList_[sampleI], maxOp<label>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::patchProbes::patchProbes
|
||||
@ -53,14 +232,7 @@ Foam::patchProbes::patchProbes
|
||||
const bool readFields
|
||||
)
|
||||
:
|
||||
Base
|
||||
(
|
||||
name,
|
||||
runTime,
|
||||
dict,
|
||||
loadFromFiles,
|
||||
readFields
|
||||
)
|
||||
probes(name, runTime, dict, loadFromFiles, false)
|
||||
{
|
||||
if (readFields)
|
||||
{
|
||||
@ -71,14 +243,53 @@ Foam::patchProbes::patchProbes
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::patchProbes::read(const dictionary& dict)
|
||||
bool Foam::patchProbes::performAction(unsigned request)
|
||||
{
|
||||
if (!(ProbesBase::read(dict) && prober_.read(dict)))
|
||||
if (!pointField::empty() && request && prepare(request))
|
||||
{
|
||||
return false;
|
||||
performAction(scalarFields_, request);
|
||||
performAction(vectorFields_, request);
|
||||
performAction(sphericalTensorFields_, request);
|
||||
performAction(symmTensorFields_, request);
|
||||
performAction(tensorFields_, request);
|
||||
|
||||
performAction(surfaceScalarFields_, request);
|
||||
performAction(surfaceVectorFields_, request);
|
||||
performAction(surfaceSphericalTensorFields_, request);
|
||||
performAction(surfaceSymmTensorFields_, request);
|
||||
performAction(surfaceTensorFields_, request);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::patchProbes::execute()
|
||||
{
|
||||
if (onExecute_)
|
||||
{
|
||||
return performAction(ACTION_ALL & ~ACTION_WRITE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::patchProbes::write()
|
||||
{
|
||||
return performAction(ACTION_ALL);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::patchProbes::read(const dictionary& dict)
|
||||
{
|
||||
if (!dict.readIfPresent("patches", patchNames_))
|
||||
{
|
||||
patchNames_.resize(1);
|
||||
patchNames_.first() = dict.get<word>("patch");
|
||||
}
|
||||
|
||||
return probes::read(dict);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2025 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,71 +28,52 @@ Class
|
||||
Foam::patchProbes
|
||||
|
||||
Description
|
||||
Probes the specified points on specified patches. The points get snapped
|
||||
onto the nearest point on the nearest face of the specified patch, and the
|
||||
sampling is actioned on the snapped locations.
|
||||
Set of locations to sample at patches
|
||||
|
||||
Usage
|
||||
Minimal example by using \c system/controlDict.functions:
|
||||
Call write() to sample and write files.
|
||||
- find nearest location on nearest face
|
||||
- update *this with location (so header contains 'snapped' locations
|
||||
- use *this as the sampling location
|
||||
|
||||
Example of function object specification:
|
||||
\verbatim
|
||||
patchProbes
|
||||
{
|
||||
// Mandatory entries
|
||||
type patchProbes;
|
||||
libs (sampling);
|
||||
|
||||
fields (<wordRes>);
|
||||
probeLocations (<vectorList>);
|
||||
patches (<wordRes>); // or patch <word>;
|
||||
// Name of the directory for probe data
|
||||
name patchProbes;
|
||||
|
||||
// Optional entries
|
||||
verbose <bool>;
|
||||
sampleOnExecute <bool>;
|
||||
fixedLocations <bool>;
|
||||
includeOutOfBounds <bool>;
|
||||
interpolationScheme <word>;
|
||||
// Patches to sample (wildcards allowed)
|
||||
patches (".*inl.*");
|
||||
|
||||
...
|
||||
// Write at same frequency as fields
|
||||
writeControl writeTime;
|
||||
writeInterval 1;
|
||||
|
||||
// Fields to be probed
|
||||
fields (p U);
|
||||
|
||||
// Locations to probe. These get snapped onto the nearest point
|
||||
// on the selected patches
|
||||
probeLocations
|
||||
(
|
||||
( -100 0 0.01 ) // at inlet
|
||||
);
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
type | Type name: patchProbes | word | yes | -
|
||||
libs | Library name: sampling | word | yes | -
|
||||
fields | Names of the fields to be probed | wordRes | yes | -
|
||||
probeLocations | Locations of the probes | vectorField | yes | -
|
||||
patches | Patches to sample (wildcards allowed) | wordRes | yes | -
|
||||
verbose | Enable/disable verbose output | bool | no | false
|
||||
sampleOnExecute | Sample on execution and store results | bool | no <!--
|
||||
--> | false
|
||||
fixedLocations | Do not recalculate cells if mesh moves | bool | no | true
|
||||
includeOutOfBounds | Include out-of-bounds locations | bool | no | true
|
||||
interpolationScheme | Scheme to obtain values at the points | word <!--
|
||||
--> | no | cell
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link fvMeshFunctionObject.H \endlink
|
||||
- \link ProbesBase.H \endlink
|
||||
- \link patchPointProber.H \endlink
|
||||
- \link pointProberBase.H \endlink
|
||||
|
||||
Note
|
||||
- The \c includeOutOfBounds filters out points that haven't been found.
|
||||
Default is to include them (with value \c -VGREAT).
|
||||
|
||||
SourceFiles
|
||||
patchProbes.C
|
||||
patchProbesTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_patchProbes_H
|
||||
#define Foam_patchProbes_H
|
||||
|
||||
#include "ProbesBase.H"
|
||||
#include "patchPointProber.H"
|
||||
#include "probes.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -100,17 +81,57 @@ namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class patchProbes Declaration
|
||||
Class patchProbes Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class patchProbes
|
||||
:
|
||||
public ProbesBase<patchPointProber>
|
||||
public probes
|
||||
{
|
||||
// Private Data
|
||||
protected:
|
||||
|
||||
//- Use simpler synonym for the base type
|
||||
using Base = ProbesBase<patchPointProber>;
|
||||
// Protected Data
|
||||
|
||||
//- Patches to sample
|
||||
wordRes patchNames_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Find elements containing patchProbes
|
||||
virtual void findElements(const fvMesh& mesh); // override
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Write field values
|
||||
template<class Type>
|
||||
void writeValues
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
);
|
||||
|
||||
//- Sample and store/write applicable volume/surface fields
|
||||
template<class GeoField>
|
||||
void performAction
|
||||
(
|
||||
const fieldGroup<GeoField>& fieldNames, /* must be sorted */
|
||||
unsigned request
|
||||
);
|
||||
|
||||
//- Perform sampling action with store/write
|
||||
bool performAction(unsigned request);
|
||||
|
||||
|
||||
//- No copy construct
|
||||
patchProbes(const patchProbes&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const patchProbes&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
@ -121,7 +142,7 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from name, Time and dictionary
|
||||
//- Construct from Time and dictionary
|
||||
patchProbes
|
||||
(
|
||||
const word& name,
|
||||
@ -131,26 +152,54 @@ public:
|
||||
const bool readFields = true
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~patchProbes() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Bring Base::prober into this class's public scope.
|
||||
using Base::prober;
|
||||
//- Sample and store result if the sampleOnExecute is enabled.
|
||||
virtual bool execute();
|
||||
|
||||
//- Read the settings from the dictionary
|
||||
//- Sample and write
|
||||
virtual bool write();
|
||||
|
||||
//- Read
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
|
||||
// Sampling
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const VolumeField<Type>&) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const SurfaceField<Type>&) const;
|
||||
|
||||
//- Sample a single field on all sample locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sampleSurfaceField(const word& fieldName) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "patchProbesTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,15 +26,70 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "patchPointProber.H"
|
||||
#include "patchProbes.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "IOmanip.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::patchProbes::writeValues
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
const unsigned int w = IOstream::defaultPrecision() + 7;
|
||||
OFstream& os = *probeFilePtrs_[fieldName];
|
||||
|
||||
os << setw(w) << timeValue;
|
||||
|
||||
for (const auto& v : values)
|
||||
{
|
||||
os << ' ' << setw(w) << v;
|
||||
}
|
||||
os << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class GeoField>
|
||||
void Foam::patchProbes::performAction
|
||||
(
|
||||
const fieldGroup<GeoField>& fieldNames,
|
||||
unsigned request
|
||||
)
|
||||
{
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
tmp<GeoField> tfield = getOrLoadField<GeoField>(fieldName);
|
||||
|
||||
if (tfield)
|
||||
{
|
||||
const auto& field = tfield();
|
||||
const scalar timeValue = field.time().timeOutputValue();
|
||||
|
||||
Field<typename GeoField::value_type> values(sample(field));
|
||||
|
||||
this->storeResults(fieldName, values);
|
||||
if (request & ACTION_WRITE)
|
||||
{
|
||||
this->writeValues(fieldName, values, timeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchPointProber::sample(const VolumeField<Type>& vField) const
|
||||
Foam::patchProbes::sample(const VolumeField<Type>& vField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
@ -63,7 +119,7 @@ Foam::patchPointProber::sample(const VolumeField<Type>& vField) const
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchPointProber::sample(const SurfaceField<Type>& sField) const
|
||||
Foam::patchProbes::sample(const SurfaceField<Type>& sField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
@ -93,7 +149,7 @@ Foam::patchPointProber::sample(const SurfaceField<Type>& sField) const
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchPointProber::sample(const word& fieldName) const
|
||||
Foam::patchProbes::sample(const word& fieldName) const
|
||||
{
|
||||
return sample(mesh_.lookupObject<VolumeField<Type>>(fieldName));
|
||||
}
|
||||
@ -101,7 +157,7 @@ Foam::patchPointProber::sample(const word& fieldName) const
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::patchPointProber::sampleSurfaceField(const word& fieldName) const
|
||||
Foam::patchProbes::sampleSurfaceField(const word& fieldName) const
|
||||
{
|
||||
return sample(mesh_.lookupObject<SurfaceField<Type>>(fieldName));
|
||||
}
|
||||
@ -1,186 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "internalPointProber.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(internalPointProber, 0);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::internalPointProber::findElements(const fvMesh& mesh)
|
||||
{
|
||||
DebugInfo<< "internalPointProber: resetting sample locations" << endl;
|
||||
|
||||
elementList_.resize_nocopy(pointField::size());
|
||||
faceList_.resize_nocopy(pointField::size());
|
||||
processor_.resize_nocopy(pointField::size());
|
||||
processor_ = -1;
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
const point& location = (*this)[probei];
|
||||
|
||||
const label celli = mesh.findCell(location);
|
||||
|
||||
elementList_[probei] = celli;
|
||||
|
||||
if (celli != -1)
|
||||
{
|
||||
const labelList& cellFaces = mesh.cells()[celli];
|
||||
const vector& cellCentre = mesh.cellCentres()[celli];
|
||||
scalar minDistance = GREAT;
|
||||
label minFaceID = -1;
|
||||
forAll(cellFaces, i)
|
||||
{
|
||||
label facei = cellFaces[i];
|
||||
vector dist = mesh.faceCentres()[facei] - cellCentre;
|
||||
if (mag(dist) < minDistance)
|
||||
{
|
||||
minDistance = mag(dist);
|
||||
minFaceID = facei;
|
||||
}
|
||||
}
|
||||
faceList_[probei] = minFaceID;
|
||||
}
|
||||
else
|
||||
{
|
||||
faceList_[probei] = -1;
|
||||
}
|
||||
|
||||
if (debug && (elementList_[probei] != -1 || faceList_[probei] != -1))
|
||||
{
|
||||
Pout<< "internalPointProber : found point " << location
|
||||
<< " in cell " << elementList_[probei]
|
||||
<< " and face " << faceList_[probei] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if all probes have been found.
|
||||
forAll(elementList_, probei)
|
||||
{
|
||||
const point& location = operator[](probei);
|
||||
label celli = elementList_[probei];
|
||||
label facei = faceList_[probei];
|
||||
|
||||
processor_[probei] = (celli != -1 ? Pstream::myProcNo() : -1);
|
||||
|
||||
// Check at least one processor with cell.
|
||||
reduce(celli, maxOp<label>());
|
||||
reduce(facei, maxOp<label>());
|
||||
reduce(processor_[probei], maxOp<label>());
|
||||
|
||||
if (celli == -1)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Did not find location " << location
|
||||
<< " in any cell. Skipping location." << endl;
|
||||
}
|
||||
}
|
||||
else if (facei == -1)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Did not find location " << location
|
||||
<< " in any face. Skipping location." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure location not on two domains.
|
||||
if (elementList_[probei] != -1 && elementList_[probei] != celli)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Location " << location
|
||||
<< " seems to be on multiple domains:"
|
||||
<< " cell " << elementList_[probei]
|
||||
<< " on my domain " << Pstream::myProcNo()
|
||||
<< " and cell " << celli << " on some other domain."
|
||||
<< nl
|
||||
<< "This might happen if the probe location is on"
|
||||
<< " a processor patch. Change the location slightly"
|
||||
<< " to prevent this." << endl;
|
||||
}
|
||||
|
||||
if (faceList_[probei] != -1 && faceList_[probei] != facei)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Location " << location
|
||||
<< " seems to be on multiple domains:"
|
||||
<< " cell " << faceList_[probei]
|
||||
<< " on my domain " << Pstream::myProcNo()
|
||||
<< " and face " << facei << " on some other domain."
|
||||
<< nl
|
||||
<< "This might happen if the probe location is on"
|
||||
<< " a processor patch. Change the location slightly"
|
||||
<< " to prevent this." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::internalPointProber::internalPointProber
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
pointProberBase(mesh, dict)
|
||||
{
|
||||
read(dict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::internalPointProber::read(const dictionary& dict)
|
||||
{
|
||||
if (!pointProberBase::read(dict))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialise cells to sample from supplied locations
|
||||
findElements(mesh_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,140 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::internalPointProber
|
||||
|
||||
Description
|
||||
A utility class for probing field values at specified point locations
|
||||
within an \c fvMesh.
|
||||
|
||||
The \c internalPointProber stores a list of 3D point coordinates and
|
||||
determines the corresponding mesh elements (cells or faces) that contain
|
||||
these points. It provides methods to sample volume or surface fields at
|
||||
the stored locations, with support for fixed or mesh-moving point
|
||||
coordinates.
|
||||
|
||||
Features include:
|
||||
- Reading probe locations and settings from a dictionary
|
||||
- Support for fixed or moving locations (for dynamic mesh cases)
|
||||
- Optional inclusion of points that lie outside of the mesh domain
|
||||
- Selection of interpolation/sampling schemes for fixed locations
|
||||
- Sampling of volume and surface fields by name or by direct reference
|
||||
- Automatic update of element mapping when the mesh changes or moves
|
||||
|
||||
SourceFiles
|
||||
internalPointProber.C
|
||||
internalPointProberTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_internalPointProber_H
|
||||
#define Foam_internalPointProber_H
|
||||
|
||||
#include "pointProberBase.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class internalPointProber Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class internalPointProber
|
||||
:
|
||||
public pointProberBase
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Find cells and faces containing probes
|
||||
virtual void findElements(const fvMesh& mesh);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("internalPointProber");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
internalPointProber
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~internalPointProber() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Sampling
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const VolumeField<Type>&) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const SurfaceField<Type>&) const;
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sampleSurfaceField(const word& fieldName) const;
|
||||
|
||||
|
||||
// I-O
|
||||
|
||||
//- Read the settings dictionary
|
||||
virtual bool read(const dictionary&);
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "internalPointProberTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,120 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "internalPointProber.H"
|
||||
#include "interpolation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::internalPointProber::sample(const VolumeField<Type>& vField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
if (fixedLocations_)
|
||||
{
|
||||
autoPtr<interpolation<Type>> interpPtr
|
||||
(
|
||||
interpolation<Type>::New(samplePointScheme_, vField)
|
||||
);
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (elementList_[probei] >= 0)
|
||||
{
|
||||
const vector& position = operator[](probei);
|
||||
|
||||
values[probei] = interpPtr().interpolate
|
||||
(
|
||||
position,
|
||||
elementList_[probei],
|
||||
-1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (elementList_[probei] >= 0)
|
||||
{
|
||||
values[probei] = vField[elementList_[probei]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::listCombineReduce(values, isNotEqOp<Type>());
|
||||
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::internalPointProber::sample(const SurfaceField<Type>& sField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (faceList_[probei] >= 0)
|
||||
{
|
||||
values[probei] = sField[faceList_[probei]];
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::listCombineReduce(values, isNotEqOp<Type>());
|
||||
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::internalPointProber::sample(const word& fieldName) const
|
||||
{
|
||||
return sample(mesh_.lookupObject<VolumeField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::internalPointProber::sampleSurfaceField(const word& fieldName) const
|
||||
{
|
||||
return sample(mesh_.lookupObject<SurfaceField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,251 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "patchPointProber.H"
|
||||
#include "mappedPatchBase.H"
|
||||
#include "treeBoundBox.H"
|
||||
#include "treeDataFace.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(patchPointProber, 0);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::patchPointProber::findElements(const fvMesh& mesh)
|
||||
{
|
||||
(void)mesh.tetBasePtIs();
|
||||
|
||||
const polyBoundaryMesh& bm = mesh.boundaryMesh();
|
||||
|
||||
// All the info for nearest. Construct to miss
|
||||
List<mappedPatchBase::nearInfo> nearest(this->size());
|
||||
|
||||
patchIDs_ = bm.patchSet(patchNames_).sortedToc();
|
||||
|
||||
label nFaces = 0;
|
||||
forAll(patchIDs_, i)
|
||||
{
|
||||
nFaces += bm[patchIDs_[i]].size();
|
||||
}
|
||||
|
||||
if (nFaces > 0)
|
||||
{
|
||||
// Collect mesh faces and bounding box
|
||||
labelList bndFaces(nFaces);
|
||||
treeBoundBox overallBb;
|
||||
|
||||
nFaces = 0;
|
||||
forAll(patchIDs_, i)
|
||||
{
|
||||
const polyPatch& pp = bm[patchIDs_[i]];
|
||||
forAll(pp, i)
|
||||
{
|
||||
bndFaces[nFaces++] = pp.start()+i;
|
||||
const face& f = pp[i];
|
||||
|
||||
// Without reduction.
|
||||
overallBb.add(pp.points(), f);
|
||||
}
|
||||
}
|
||||
|
||||
Random rndGen(123456);
|
||||
overallBb.inflate(rndGen, 1e-4, ROOTVSMALL);
|
||||
|
||||
|
||||
const indexedOctree<treeDataFace> boundaryTree
|
||||
(
|
||||
treeDataFace(mesh, bndFaces), // patch faces only
|
||||
|
||||
overallBb, // overall search domain
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
);
|
||||
|
||||
forAll(probeLocations(), probei)
|
||||
{
|
||||
const auto& treeData = boundaryTree.shapes();
|
||||
const point sample = probeLocations()[probei];
|
||||
|
||||
pointIndexHit info = boundaryTree.findNearest
|
||||
(
|
||||
sample,
|
||||
Foam::sqr(boundaryTree.bb().mag())
|
||||
);
|
||||
|
||||
if (!info.hit())
|
||||
{
|
||||
info = boundaryTree.findNearest(sample, Foam::sqr(GREAT));
|
||||
}
|
||||
|
||||
const label facei = treeData.objectIndex(info.index());
|
||||
|
||||
const label patchi = bm.whichPatch(facei);
|
||||
|
||||
if (isA<emptyPolyPatch>(bm[patchi]))
|
||||
{
|
||||
WarningInFunction
|
||||
<< " The sample point: " << sample
|
||||
<< " belongs to " << patchi
|
||||
<< " which is an empty patch. This is not permitted. "
|
||||
<< " This sample will not be included "
|
||||
<< endl;
|
||||
}
|
||||
else if (info.hit())
|
||||
{
|
||||
// Note: do we store the face centre or the actual nearest?
|
||||
// We interpolate using the faceI only though (no
|
||||
// interpolation) so it does not actually matter much, just for
|
||||
// the location written to the header.
|
||||
|
||||
//const point& facePt = mesh.faceCentres()[faceI];
|
||||
const point& facePt = info.point();
|
||||
|
||||
mappedPatchBase::nearInfo sampleInfo;
|
||||
|
||||
sampleInfo.first() = pointIndexHit(true, facePt, facei);
|
||||
|
||||
sampleInfo.second().first() = facePt.distSqr(sample);
|
||||
sampleInfo.second().second() = Pstream::myProcNo();
|
||||
|
||||
nearest[probei] = sampleInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find nearest - globally consistent
|
||||
Pstream::listCombineReduce(nearest, mappedPatchBase::nearestEqOp());
|
||||
|
||||
oldPoints_.resize(this->size());
|
||||
|
||||
// Update actual probe locations and store old ones
|
||||
forAll(nearest, samplei)
|
||||
{
|
||||
oldPoints_[samplei] = operator[](samplei);
|
||||
operator[](samplei) = nearest[samplei].first().point();
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << nl;
|
||||
forAll(nearest, samplei)
|
||||
{
|
||||
label proci = nearest[samplei].second().second();
|
||||
label locali = nearest[samplei].first().index();
|
||||
|
||||
Info<< " " << samplei << " coord:"<< operator[](samplei)
|
||||
<< " found on processor:" << proci
|
||||
<< " in local face:" << locali
|
||||
<< " with location:" << nearest[samplei].first().point()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract any local faces to sample:
|
||||
// - operator[] : actual point to sample (=nearest point on patch)
|
||||
// - oldPoints_ : original provided point (might be anywhere in the mesh)
|
||||
// - elementList_ : cells, not used
|
||||
// - faceList_ : faces (now patch faces)
|
||||
// - patchIDList_ : patch corresponding to faceList
|
||||
// - processor_ : processor
|
||||
elementList_.resize_nocopy(nearest.size());
|
||||
elementList_ = -1;
|
||||
|
||||
faceList_.resize_nocopy(nearest.size());
|
||||
faceList_ = -1;
|
||||
|
||||
processor_.resize_nocopy(nearest.size());
|
||||
processor_ = -1;
|
||||
|
||||
patchIDList_.resize_nocopy(nearest.size());
|
||||
patchIDList_ = -1;
|
||||
|
||||
forAll(nearest, sampleI)
|
||||
{
|
||||
processor_[sampleI] = nearest[sampleI].second().second();
|
||||
|
||||
if (nearest[sampleI].second().second() == Pstream::myProcNo())
|
||||
{
|
||||
// Store the face to sample
|
||||
faceList_[sampleI] = nearest[sampleI].first().index();
|
||||
const label facei = faceList_[sampleI];
|
||||
if (facei != -1)
|
||||
{
|
||||
processor_[sampleI] = Pstream::myProcNo();
|
||||
patchIDList_[sampleI] = bm.whichPatch(facei);
|
||||
}
|
||||
}
|
||||
reduce(processor_[sampleI], maxOp<label>());
|
||||
reduce(patchIDList_[sampleI], maxOp<label>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::patchPointProber::patchPointProber
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
pointProberBase(mesh, dict)
|
||||
{
|
||||
read(dict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::patchPointProber::read(const dictionary& dict)
|
||||
{
|
||||
if (!pointProberBase::read(dict))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dict.readIfPresent("patches", patchNames_))
|
||||
{
|
||||
patchNames_.resize(1);
|
||||
patchNames_.first() = dict.get<word>("patch");
|
||||
}
|
||||
|
||||
// Initialise cells to sample from supplied locations
|
||||
findElements(mesh_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,152 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::patchPointProber
|
||||
|
||||
Description
|
||||
Utility class for probing specified points on user-selected boundary
|
||||
patches. The input points are projected onto the nearest point of the
|
||||
nearest face on the specified patch, ensuring sampling occurs at valid
|
||||
patch locations.
|
||||
|
||||
The patchPointProber enables sampling of both volume and surface fields
|
||||
at these snapped locations. Patch selection is controlled via patch names or
|
||||
indices, and the class provides runtime selection and dictionary-driven
|
||||
configuration.
|
||||
|
||||
Typical usage involves specifying patch names and probe locations in a
|
||||
dictionary, after which the class manages the mapping and sampling
|
||||
operations.
|
||||
|
||||
SourceFiles
|
||||
patchPointProber.C
|
||||
patchPointProberTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_patchPointProber_H
|
||||
#define Foam_patchPointProber_H
|
||||
|
||||
#include "pointProberBase.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class patchPointProber Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class patchPointProber
|
||||
:
|
||||
public pointProberBase
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Names of the patches to sample
|
||||
wordRes patchNames_;
|
||||
|
||||
//- Index of the patches to sample
|
||||
labelList patchIDs_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Find elements containing patchPointProber
|
||||
virtual void findElements(const fvMesh& mesh);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("patchPointProber");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
patchPointProber
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~patchPointProber() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return the index of the patches to sample
|
||||
const labelList& patchIDs() const noexcept { return patchIDs_; }
|
||||
|
||||
|
||||
// Sampling
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const VolumeField<Type>&) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const SurfaceField<Type>&) const;
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sampleSurfaceField(const word& fieldName) const;
|
||||
|
||||
|
||||
// I-O
|
||||
|
||||
//- Read the settings dictionary
|
||||
virtual bool read(const dictionary&);
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "patchPointProberTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,182 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "pointProberBase.H"
|
||||
#include "mapPolyMesh.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(pointProberBase, 0);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointProberBase::pointProberBase
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
pointField(),
|
||||
mesh_(mesh),
|
||||
samplePointScheme_("cell")
|
||||
{
|
||||
read(dict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::pointProberBase::read(const dictionary& dict)
|
||||
{
|
||||
dict.readEntry("probeLocations", static_cast<pointField&>(*this));
|
||||
|
||||
fixedLocations_ = dict.getOrDefault<bool>("fixedLocations", true);
|
||||
includeOutOfBounds_ = dict.getOrDefault<bool>("includeOutOfBounds", true);
|
||||
|
||||
if (dict.readIfPresent("interpolationScheme", samplePointScheme_))
|
||||
{
|
||||
if (!fixedLocations_ && samplePointScheme_ != "cell")
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Only cell interpolation can be applied when "
|
||||
<< "not using fixedLocations. InterpolationScheme "
|
||||
<< "entry will be ignored"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::pointProberBase::updateMesh(const mapPolyMesh& mpm)
|
||||
{
|
||||
DebugInfo<< "probes: updateMesh" << endl;
|
||||
|
||||
if (&mpm.mesh() != &mesh_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fixedLocations_)
|
||||
{
|
||||
this->findElements(mesh_);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugInfo<< "probes: remapping sample locations" << endl;
|
||||
|
||||
// 1. Update cells
|
||||
{
|
||||
DynamicList<label> elems(elementList_.size());
|
||||
|
||||
const labelList& reverseMap = mpm.reverseCellMap();
|
||||
forAll(elementList_, i)
|
||||
{
|
||||
label celli = elementList_[i];
|
||||
if (celli != -1)
|
||||
{
|
||||
label newCelli = reverseMap[celli];
|
||||
if (newCelli == -1)
|
||||
{
|
||||
// cell removed
|
||||
}
|
||||
else if (newCelli < -1)
|
||||
{
|
||||
// cell merged
|
||||
elems.append(-newCelli - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// valid new cell
|
||||
elems.append(newCelli);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep -1 elements so the size stays the same
|
||||
elems.append(-1);
|
||||
}
|
||||
}
|
||||
|
||||
elementList_.transfer(elems);
|
||||
}
|
||||
|
||||
// 2. Update faces
|
||||
{
|
||||
DynamicList<label> elems(faceList_.size());
|
||||
|
||||
const labelList& reverseMap = mpm.reverseFaceMap();
|
||||
for (const label facei : faceList_)
|
||||
{
|
||||
if (facei != -1)
|
||||
{
|
||||
label newFacei = reverseMap[facei];
|
||||
if (newFacei == -1)
|
||||
{
|
||||
// face removed
|
||||
}
|
||||
else if (newFacei < -1)
|
||||
{
|
||||
// face merged
|
||||
elems.append(-newFacei - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// valid new face
|
||||
elems.append(newFacei);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep -1 elements
|
||||
elems.append(-1);
|
||||
}
|
||||
}
|
||||
|
||||
faceList_.transfer(elems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::pointProberBase::movePoints(const polyMesh& mesh)
|
||||
{
|
||||
DebugInfo<< "probes: movePoints" << endl;
|
||||
|
||||
if (fixedLocations_ && &mesh == &mesh_)
|
||||
{
|
||||
this->findElements(mesh_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,213 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::patchPointProber
|
||||
|
||||
Description
|
||||
Base class for sampling fields at specified internal and boundary locations.
|
||||
|
||||
SourceFiles
|
||||
pointProberBase.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_pointProberBase_H
|
||||
#define Foam_pointProberBase_H
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "pointField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class pointProberBase Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class pointProberBase
|
||||
:
|
||||
public pointField
|
||||
{
|
||||
protected:
|
||||
|
||||
template<class T>
|
||||
struct isNotEqOp
|
||||
{
|
||||
void operator()(T& x, const T& y) const
|
||||
{
|
||||
const T unsetVal(-VGREAT*pTraits<T>::one);
|
||||
|
||||
if (x != unsetVal)
|
||||
{
|
||||
// Keep x.
|
||||
|
||||
// Note: should check for y != unsetVal but multiple sample cells
|
||||
// already handled in read().
|
||||
}
|
||||
else
|
||||
{
|
||||
// x is not set. y might be.
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Const reference to the mesh
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Fixed locations (default: true)
|
||||
// Note: set to false for moving mesh calculations where locations
|
||||
// should move with the mesh
|
||||
bool fixedLocations_;
|
||||
|
||||
//- Include probes that were not found (default: true)
|
||||
bool includeOutOfBounds_;
|
||||
|
||||
//- Interpolation/sample scheme to obtain values at the points
|
||||
// Note: only possible when fixedLocations_ is true
|
||||
word samplePointScheme_;
|
||||
|
||||
|
||||
// Calculated
|
||||
|
||||
//- Cells to be probed (obtained from the locations)
|
||||
labelList elementList_;
|
||||
|
||||
//- Faces to be probed
|
||||
labelList faceList_;
|
||||
|
||||
//- Processor holding the cell or face (-1 if point not found
|
||||
//- on any processor)
|
||||
labelList processor_;
|
||||
|
||||
//- Patch IDs on which the new probes are located
|
||||
labelList patchIDList_;
|
||||
|
||||
//- Original probes location
|
||||
pointField oldPoints_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Find cells and faces containing probes
|
||||
virtual void findElements(const fvMesh& mesh) = 0;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("pointProberBase");
|
||||
|
||||
|
||||
// Generated Methods
|
||||
|
||||
//- No copy construct
|
||||
pointProberBase(const pointProberBase&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const pointProberBase&) = delete;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
pointProberBase
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~pointProberBase() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return true if no probe locations
|
||||
bool empty() const { return pointField::empty(); }
|
||||
|
||||
//- Return true if fixed locations
|
||||
bool fixedLocations() const { return fixedLocations_; }
|
||||
|
||||
//- Return true if include out of bounds probes
|
||||
bool includeOutOfBounds() const { return includeOutOfBounds_; }
|
||||
|
||||
//- Return the interpolation scheme to obtain values at the points
|
||||
// Note: only possible when fixedLocations_ is true
|
||||
const word& samplePointScheme() const { return samplePointScheme_; }
|
||||
|
||||
//- Return const reference to the probe locations
|
||||
const pointField& probeLocations() const { return *this; }
|
||||
|
||||
//- Return the location of probe i
|
||||
const point& probe(const label i) const { return operator[](i); }
|
||||
|
||||
//- Cells to be probed (obtained from the locations)
|
||||
const labelList& elements() const { return elementList_; }
|
||||
|
||||
//- Return const reference to the faces to be probed
|
||||
const labelList& faces() const { return faceList_; }
|
||||
|
||||
//- Return const reference to the processor list
|
||||
const labelList& processors() const { return processor_; }
|
||||
|
||||
//- Return const reference to the patch ID list
|
||||
const labelList& patchIDList() const noexcept { return patchIDList_; }
|
||||
|
||||
//- Return const reference to the original probe locations
|
||||
const pointField& oldPoints() const noexcept { return oldPoints_; }
|
||||
|
||||
|
||||
// I-O
|
||||
|
||||
//- Read the settings dictionary
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
//- Update for changes of mesh
|
||||
virtual void updateMesh(const mapPolyMesh&);
|
||||
|
||||
//- Update for changes of mesh
|
||||
virtual void movePoints(const polyMesh&);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2025 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,6 +27,12 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "probes.H"
|
||||
#include "dictionary.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "Time.H"
|
||||
#include "IOmanip.H"
|
||||
#include "mapPolyMesh.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -34,6 +40,7 @@ License
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(probes, 0);
|
||||
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
functionObject,
|
||||
@ -42,6 +49,318 @@ namespace Foam
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::probes::createProbeFiles(const wordList& fieldNames)
|
||||
{
|
||||
// Open new output streams
|
||||
|
||||
bool needsNewFiles = false;
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
if (!probeFilePtrs_.found(fieldName))
|
||||
{
|
||||
needsNewFiles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsNewFiles && Pstream::master())
|
||||
{
|
||||
DebugInfo
|
||||
<< "Probing fields: " << fieldNames << nl
|
||||
<< "Probing locations: " << *this << nl
|
||||
<< endl;
|
||||
|
||||
// Put in undecomposed case
|
||||
// (Note: gives problems for distributed data running)
|
||||
|
||||
fileName probeDir
|
||||
(
|
||||
mesh_.time().globalPath()
|
||||
/ functionObject::outputPrefix
|
||||
/ name()/mesh_.regionName()
|
||||
// Use startTime as the instance for output files
|
||||
/ mesh_.time().timeName(mesh_.time().startTime().value())
|
||||
);
|
||||
probeDir.clean(); // Remove unneeded ".."
|
||||
|
||||
// Create directory if needed
|
||||
Foam::mkDir(probeDir);
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
if (probeFilePtrs_.found(fieldName))
|
||||
{
|
||||
// Safety
|
||||
continue;
|
||||
}
|
||||
|
||||
auto osPtr = autoPtr<OFstream>::New(probeDir/fieldName);
|
||||
auto& os = *osPtr;
|
||||
|
||||
probeFilePtrs_.insert(fieldName, osPtr);
|
||||
|
||||
DebugInfo<< "open probe stream: " << os.name() << endl;
|
||||
|
||||
const unsigned int width(IOstream::defaultPrecision() + 7);
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
os << "# Probe " << probei << ' ' << operator[](probei);
|
||||
|
||||
if (processor_[probei] == -1)
|
||||
{
|
||||
os << " # Not Found";
|
||||
}
|
||||
// Only for patchProbes
|
||||
else if (probei < patchIDList_.size())
|
||||
{
|
||||
const label patchi = patchIDList_[probei];
|
||||
if (patchi != -1)
|
||||
{
|
||||
const polyBoundaryMesh& bm = mesh_.boundaryMesh();
|
||||
if
|
||||
(
|
||||
patchi < bm.nNonProcessor()
|
||||
|| processor_[probei] == Pstream::myProcNo()
|
||||
)
|
||||
{
|
||||
os << " at patch " << bm[patchi].name();
|
||||
}
|
||||
os << " with a distance of "
|
||||
<< mag(operator[](probei)-oldPoints_[probei])
|
||||
<< " m to the original point "
|
||||
<< oldPoints_[probei];
|
||||
}
|
||||
}
|
||||
|
||||
os << nl;
|
||||
}
|
||||
|
||||
os << '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
<< "Probe";
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (includeOutOfBounds_ || processor_[probei] != -1)
|
||||
{
|
||||
os << ' ' << setw(width) << probei;
|
||||
}
|
||||
}
|
||||
os << nl;
|
||||
|
||||
os << '#' << setw(IOstream::defaultPrecision() + 6)
|
||||
<< "Time" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::probes::findElements(const fvMesh& mesh)
|
||||
{
|
||||
DebugInfo<< "probes: resetting sample locations" << endl;
|
||||
|
||||
elementList_.resize_nocopy(pointField::size());
|
||||
faceList_.resize_nocopy(pointField::size());
|
||||
processor_.resize_nocopy(pointField::size());
|
||||
processor_ = -1;
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
const point& location = (*this)[probei];
|
||||
|
||||
const label celli = mesh.findCell(location);
|
||||
|
||||
elementList_[probei] = celli;
|
||||
|
||||
if (celli != -1)
|
||||
{
|
||||
const labelList& cellFaces = mesh.cells()[celli];
|
||||
const vector& cellCentre = mesh.cellCentres()[celli];
|
||||
scalar minDistance = GREAT;
|
||||
label minFaceID = -1;
|
||||
forAll(cellFaces, i)
|
||||
{
|
||||
label facei = cellFaces[i];
|
||||
vector dist = mesh.faceCentres()[facei] - cellCentre;
|
||||
if (mag(dist) < minDistance)
|
||||
{
|
||||
minDistance = mag(dist);
|
||||
minFaceID = facei;
|
||||
}
|
||||
}
|
||||
faceList_[probei] = minFaceID;
|
||||
}
|
||||
else
|
||||
{
|
||||
faceList_[probei] = -1;
|
||||
}
|
||||
|
||||
if (debug && (elementList_[probei] != -1 || faceList_[probei] != -1))
|
||||
{
|
||||
Pout<< "probes : found point " << location
|
||||
<< " in cell " << elementList_[probei]
|
||||
<< " and face " << faceList_[probei] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if all probes have been found.
|
||||
forAll(elementList_, probei)
|
||||
{
|
||||
const point& location = operator[](probei);
|
||||
label celli = elementList_[probei];
|
||||
label facei = faceList_[probei];
|
||||
|
||||
processor_[probei] = (celli != -1 ? Pstream::myProcNo() : -1);
|
||||
|
||||
// Check at least one processor with cell.
|
||||
reduce(celli, maxOp<label>());
|
||||
reduce(facei, maxOp<label>());
|
||||
reduce(processor_[probei], maxOp<label>());
|
||||
|
||||
if (celli == -1)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Did not find location " << location
|
||||
<< " in any cell. Skipping location." << endl;
|
||||
}
|
||||
}
|
||||
else if (facei == -1)
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Did not find location " << location
|
||||
<< " in any face. Skipping location." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure location not on two domains.
|
||||
if (elementList_[probei] != -1 && elementList_[probei] != celli)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Location " << location
|
||||
<< " seems to be on multiple domains:"
|
||||
<< " cell " << elementList_[probei]
|
||||
<< " on my domain " << Pstream::myProcNo()
|
||||
<< " and cell " << celli << " on some other domain."
|
||||
<< nl
|
||||
<< "This might happen if the probe location is on"
|
||||
<< " a processor patch. Change the location slightly"
|
||||
<< " to prevent this." << endl;
|
||||
}
|
||||
|
||||
if (faceList_[probei] != -1 && faceList_[probei] != facei)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Location " << location
|
||||
<< " seems to be on multiple domains:"
|
||||
<< " cell " << faceList_[probei]
|
||||
<< " on my domain " << Pstream::myProcNo()
|
||||
<< " and face " << facei << " on some other domain."
|
||||
<< nl
|
||||
<< "This might happen if the probe location is on"
|
||||
<< " a processor patch. Change the location slightly"
|
||||
<< " to prevent this." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::probes::prepare(unsigned request)
|
||||
{
|
||||
// Prefilter on selection
|
||||
HashTable<wordHashSet> selected =
|
||||
(
|
||||
loadFromFiles_
|
||||
? IOobjectList(mesh_, mesh_.time().timeName()).classes(fieldSelection_)
|
||||
: mesh_.classes(fieldSelection_)
|
||||
);
|
||||
|
||||
// Classify and count fields
|
||||
label nFields = 0;
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(InputType, Target) \
|
||||
{ \
|
||||
Target.clear(); /* Remove old values */ \
|
||||
const auto iter = selected.cfind(InputType::typeName); \
|
||||
if (iter.good()) \
|
||||
{ \
|
||||
/* Add new (current) values */ \
|
||||
Target.append(iter.val().sortedToc()); \
|
||||
nFields += Target.size(); \
|
||||
} \
|
||||
}
|
||||
|
||||
doLocalCode(volScalarField, scalarFields_);
|
||||
doLocalCode(volVectorField, vectorFields_)
|
||||
doLocalCode(volSphericalTensorField, sphericalTensorFields_);
|
||||
doLocalCode(volSymmTensorField, symmTensorFields_);
|
||||
doLocalCode(volTensorField, tensorFields_);
|
||||
|
||||
doLocalCode(surfaceScalarField, surfaceScalarFields_);
|
||||
doLocalCode(surfaceVectorField, surfaceVectorFields_);
|
||||
doLocalCode(surfaceSphericalTensorField, surfaceSphericalTensorFields_);
|
||||
doLocalCode(surfaceSymmTensorField, surfaceSymmTensorFields_);
|
||||
doLocalCode(surfaceTensorField, surfaceTensorFields_);
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
|
||||
|
||||
// Adjust file streams
|
||||
if (Pstream::master())
|
||||
{
|
||||
wordHashSet currentFields(2*nFields);
|
||||
currentFields.insert(scalarFields_);
|
||||
currentFields.insert(vectorFields_);
|
||||
currentFields.insert(sphericalTensorFields_);
|
||||
currentFields.insert(symmTensorFields_);
|
||||
currentFields.insert(tensorFields_);
|
||||
|
||||
currentFields.insert(surfaceScalarFields_);
|
||||
currentFields.insert(surfaceVectorFields_);
|
||||
currentFields.insert(surfaceSphericalTensorFields_);
|
||||
currentFields.insert(surfaceSymmTensorFields_);
|
||||
currentFields.insert(surfaceTensorFields_);
|
||||
|
||||
DebugInfo
|
||||
<< "Probing fields: " << currentFields << nl
|
||||
<< "Probing locations: " << *this << nl
|
||||
<< endl;
|
||||
|
||||
// Close streams for fields that no longer exist
|
||||
forAllIters(probeFilePtrs_, iter)
|
||||
{
|
||||
if (!currentFields.erase(iter.key()))
|
||||
{
|
||||
DebugInfo<< "close probe stream: " << iter()->name() << endl;
|
||||
|
||||
probeFilePtrs_.remove(iter);
|
||||
}
|
||||
}
|
||||
|
||||
if ((request & ACTION_WRITE) && !currentFields.empty())
|
||||
{
|
||||
createProbeFiles(currentFields.sortedToc());
|
||||
}
|
||||
}
|
||||
|
||||
return nFields;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::probes::probes
|
||||
@ -53,14 +372,15 @@ Foam::probes::probes
|
||||
const bool readFields
|
||||
)
|
||||
:
|
||||
Base
|
||||
(
|
||||
name,
|
||||
runTime,
|
||||
dict,
|
||||
loadFromFiles,
|
||||
readFields
|
||||
)
|
||||
functionObjects::fvMeshFunctionObject(name, runTime, dict),
|
||||
pointField(),
|
||||
loadFromFiles_(loadFromFiles),
|
||||
fixedLocations_(true),
|
||||
includeOutOfBounds_(true),
|
||||
verbose_(false),
|
||||
onExecute_(false),
|
||||
fieldSelection_(),
|
||||
samplePointScheme_("cell")
|
||||
{
|
||||
if (readFields)
|
||||
{
|
||||
@ -71,14 +391,184 @@ Foam::probes::probes
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::probes::verbose(const bool on) noexcept
|
||||
{
|
||||
bool old(verbose_);
|
||||
verbose_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::read(const dictionary& dict)
|
||||
{
|
||||
if (!(ProbesBase::read(dict) && prober_.read(dict)))
|
||||
dict.readEntry("probeLocations", static_cast<pointField&>(*this));
|
||||
dict.readEntry("fields", fieldSelection_);
|
||||
|
||||
dict.readIfPresent("fixedLocations", fixedLocations_);
|
||||
dict.readIfPresent("includeOutOfBounds", includeOutOfBounds_);
|
||||
|
||||
verbose_ = dict.getOrDefault("verbose", false);
|
||||
onExecute_ = dict.getOrDefault("sampleOnExecute", false);
|
||||
|
||||
if (dict.readIfPresent("interpolationScheme", samplePointScheme_))
|
||||
{
|
||||
return false;
|
||||
if (!fixedLocations_ && samplePointScheme_ != "cell")
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Only cell interpolation can be applied when "
|
||||
<< "not using fixedLocations. InterpolationScheme "
|
||||
<< "entry will be ignored"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise cells to sample from supplied locations
|
||||
findElements(mesh_);
|
||||
|
||||
// Close old (ununsed) streams
|
||||
prepare(ACTION_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::performAction(unsigned request)
|
||||
{
|
||||
if (!pointField::empty() && request && prepare(request))
|
||||
{
|
||||
performAction(scalarFields_, request);
|
||||
performAction(vectorFields_, request);
|
||||
performAction(sphericalTensorFields_, request);
|
||||
performAction(symmTensorFields_, request);
|
||||
performAction(tensorFields_, request);
|
||||
|
||||
performAction(surfaceScalarFields_, request);
|
||||
performAction(surfaceVectorFields_, request);
|
||||
performAction(surfaceSphericalTensorFields_, request);
|
||||
performAction(surfaceSymmTensorFields_, request);
|
||||
performAction(surfaceTensorFields_, request);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::execute()
|
||||
{
|
||||
if (onExecute_)
|
||||
{
|
||||
return performAction(ACTION_ALL & ~ACTION_WRITE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::probes::write()
|
||||
{
|
||||
return performAction(ACTION_ALL);
|
||||
}
|
||||
|
||||
|
||||
void Foam::probes::updateMesh(const mapPolyMesh& mpm)
|
||||
{
|
||||
DebugInfo<< "probes: updateMesh" << endl;
|
||||
|
||||
if (&mpm.mesh() != &mesh_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fixedLocations_)
|
||||
{
|
||||
findElements(mesh_);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugInfo<< "probes: remapping sample locations" << endl;
|
||||
|
||||
// 1. Update cells
|
||||
{
|
||||
DynamicList<label> elems(elementList_.size());
|
||||
|
||||
const labelList& reverseMap = mpm.reverseCellMap();
|
||||
forAll(elementList_, i)
|
||||
{
|
||||
label celli = elementList_[i];
|
||||
if (celli != -1)
|
||||
{
|
||||
label newCelli = reverseMap[celli];
|
||||
if (newCelli == -1)
|
||||
{
|
||||
// cell removed
|
||||
}
|
||||
else if (newCelli < -1)
|
||||
{
|
||||
// cell merged
|
||||
elems.append(-newCelli - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// valid new cell
|
||||
elems.append(newCelli);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep -1 elements so the size stays the same
|
||||
elems.append(-1);
|
||||
}
|
||||
}
|
||||
|
||||
elementList_.transfer(elems);
|
||||
}
|
||||
|
||||
// 2. Update faces
|
||||
{
|
||||
DynamicList<label> elems(faceList_.size());
|
||||
|
||||
const labelList& reverseMap = mpm.reverseFaceMap();
|
||||
for (const label facei : faceList_)
|
||||
{
|
||||
if (facei != -1)
|
||||
{
|
||||
label newFacei = reverseMap[facei];
|
||||
if (newFacei == -1)
|
||||
{
|
||||
// face removed
|
||||
}
|
||||
else if (newFacei < -1)
|
||||
{
|
||||
// face merged
|
||||
elems.append(-newFacei - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// valid new face
|
||||
elems.append(newFacei);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep -1 elements
|
||||
elems.append(-1);
|
||||
}
|
||||
}
|
||||
|
||||
faceList_.transfer(elems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::probes::movePoints(const polyMesh& mesh)
|
||||
{
|
||||
DebugInfo<< "probes: movePoints" << endl;
|
||||
|
||||
if (fixedLocations_ && &mesh == &mesh_)
|
||||
{
|
||||
findElements(mesh_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2025 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -31,88 +31,237 @@ Group
|
||||
grpUtilitiesFunctionObjects
|
||||
|
||||
Description
|
||||
Function object to sample fields at specified internal-mesh locations and
|
||||
write to file.
|
||||
Set of locations to sample.
|
||||
|
||||
Usage
|
||||
Minimal example by using \c system/controlDict.functions:
|
||||
Call write() to sample and write files.
|
||||
|
||||
Example of function object specification:
|
||||
\verbatim
|
||||
probes
|
||||
{
|
||||
// Mandatory entries
|
||||
type probes;
|
||||
libs (sampling);
|
||||
|
||||
fields (<wordRes>);
|
||||
probeLocations (<vectorList>);
|
||||
// Name of the directory for probe data
|
||||
name probes;
|
||||
|
||||
// Optional entries
|
||||
verbose <bool>;
|
||||
sampleOnExecute <bool>;
|
||||
fixedLocations <bool>;
|
||||
includeOutOfBounds <bool>;
|
||||
interpolationScheme <word>;
|
||||
// Write at same frequency as fields
|
||||
writeControl outputTime;
|
||||
writeInterval 1;
|
||||
|
||||
// Inherited entries
|
||||
...
|
||||
// Fields to be probed
|
||||
fields (U "p.*");
|
||||
|
||||
// Optional: do not recalculate cells if mesh moves
|
||||
fixedLocations false;
|
||||
|
||||
// Optional: interpolation scheme to use (default is cell)
|
||||
interpolationScheme cellPoint;
|
||||
|
||||
probeLocations
|
||||
(
|
||||
( 1e-06 0 0.01 ) // at inlet
|
||||
(0.21 -0.20999 0.01) // at outlet1
|
||||
(0.21 0.20999 0.01) // at outlet2
|
||||
(0.21 0 0.01) // at central block
|
||||
);
|
||||
|
||||
// Optional: filter out points that haven't been found. Default
|
||||
// is to include them (with value -VGREAT)
|
||||
includeOutOfBounds true;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
Entries:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
type | Type name: probes | word | yes | -
|
||||
libs | Library name: sampling | word | yes | -
|
||||
fields | Names of fields to probe | wordRes | yes | -
|
||||
probeLocations | Locations of probes | vectorList | yes | -
|
||||
verbose | Enable/disable verbose output | bool | no | false
|
||||
sampleOnExecute | Sample on execution and store results | bool | no <!--
|
||||
--> | false
|
||||
fixedLocations | Do not recalculate cells if mesh moves | bool | no | true
|
||||
includeOutOfBounds | Include out-of-bounds locations | bool | no | true
|
||||
interpolationScheme | Scheme to obtain values at the points | word <!--
|
||||
--> | no | cell
|
||||
Property | Description | Required | Default
|
||||
type | Type-name: probes | yes |
|
||||
probeLocations | Probe locations | yes |
|
||||
fields | word/regex list of fields to sample | yes |
|
||||
interpolationScheme | scheme to obtain values | no | cell
|
||||
fixedLocations | Do not recalculate cells if mesh moves | no | true
|
||||
includeOutOfBounds | Include out-of-bounds locations | no | true
|
||||
sampleOnExecute | Sample on execution and store results | no | false
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link fvMeshFunctionObject.H \endlink
|
||||
- \link ProbesBase.H \endlink
|
||||
- \link internalPointProber.H \endlink
|
||||
- \link pointProberBase.H \endlink
|
||||
|
||||
Note
|
||||
- The \c includeOutOfBounds filters out points that haven't been found.
|
||||
Default is to include them (with value \c -VGREAT).
|
||||
|
||||
SourceFiles
|
||||
probes.C
|
||||
probesTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_probes_H
|
||||
#define Foam_probes_H
|
||||
|
||||
#include "ProbesBase.H"
|
||||
#include "internalPointProber.H"
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "HashPtrTable.H"
|
||||
#include "OFstream.H"
|
||||
#include "polyMesh.H"
|
||||
#include "pointField.H"
|
||||
#include "volFieldsFwd.H"
|
||||
#include "surfaceFieldsFwd.H"
|
||||
#include "surfaceMesh.H"
|
||||
#include "wordRes.H"
|
||||
#include "IOobjectList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class Time;
|
||||
class objectRegistry;
|
||||
class dictionary;
|
||||
class fvMesh;
|
||||
class mapPolyMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class probes Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class probes
|
||||
:
|
||||
public ProbesBase<internalPointProber>
|
||||
public functionObjects::fvMeshFunctionObject,
|
||||
public pointField
|
||||
{
|
||||
// Private Data
|
||||
protected:
|
||||
|
||||
//- Use simpler synonym for the base type
|
||||
using Base = ProbesBase<internalPointProber>;
|
||||
// Protected Classes
|
||||
|
||||
//- Grouping of field names by GeometricField type
|
||||
template<class GeoField>
|
||||
struct fieldGroup : public DynamicList<word> {};
|
||||
|
||||
|
||||
// Data Types
|
||||
|
||||
//- Local control for sampling actions
|
||||
enum sampleActionType : unsigned
|
||||
{
|
||||
ACTION_NONE = 0,
|
||||
ACTION_WRITE = 0x1,
|
||||
ACTION_STORE = 0x2,
|
||||
ACTION_ALL = 0xF
|
||||
};
|
||||
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Load fields from files (not from objectRegistry)
|
||||
bool loadFromFiles_;
|
||||
|
||||
//- Fixed locations (default: true)
|
||||
// Note: set to false for moving mesh calculations where locations
|
||||
// should move with the mesh
|
||||
bool fixedLocations_;
|
||||
|
||||
//- Include probes that were not found (default: true)
|
||||
bool includeOutOfBounds_;
|
||||
|
||||
//- Output verbosity
|
||||
bool verbose_;
|
||||
|
||||
//- Perform sample actions on execute as well
|
||||
bool onExecute_;
|
||||
|
||||
//- Requested names of fields to probe
|
||||
wordRes fieldSelection_;
|
||||
|
||||
//- Interpolation/sample scheme to obtain values at the points
|
||||
// Note: only possible when fixedLocations_ is true
|
||||
word samplePointScheme_;
|
||||
|
||||
|
||||
// Calculated
|
||||
|
||||
//- Current list of field names selected for sampling
|
||||
DynamicList<word> selectedFieldNames_;
|
||||
|
||||
//- Categorized scalar/vector/tensor volume fields
|
||||
fieldGroup<volScalarField> scalarFields_;
|
||||
fieldGroup<volVectorField> vectorFields_;
|
||||
fieldGroup<volSphericalTensorField> sphericalTensorFields_;
|
||||
fieldGroup<volSymmTensorField> symmTensorFields_;
|
||||
fieldGroup<volTensorField> tensorFields_;
|
||||
|
||||
//- Categorized scalar/vector/tensor surface fields
|
||||
fieldGroup<surfaceScalarField> surfaceScalarFields_;
|
||||
fieldGroup<surfaceVectorField> surfaceVectorFields_;
|
||||
fieldGroup<surfaceSphericalTensorField> surfaceSphericalTensorFields_;
|
||||
fieldGroup<surfaceSymmTensorField> surfaceSymmTensorFields_;
|
||||
fieldGroup<surfaceTensorField> surfaceTensorFields_;
|
||||
|
||||
//- Cells to be probed (obtained from the locations)
|
||||
labelList elementList_;
|
||||
|
||||
//- Faces to be probed
|
||||
labelList faceList_;
|
||||
|
||||
//- Processor holding the cell or face (-1 if point not found
|
||||
// on any processor)
|
||||
labelList processor_;
|
||||
|
||||
//- Current open files (non-empty on master only)
|
||||
HashPtrTable<OFstream> probeFilePtrs_;
|
||||
|
||||
//- Patch IDs on which the new probes are located (for patchProbes)
|
||||
labelList patchIDList_;
|
||||
|
||||
//- Original probes location (only used for patchProbes)
|
||||
pointField oldPoints_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Find cells and faces containing probes
|
||||
virtual void findElements(const fvMesh& mesh);
|
||||
|
||||
//- Classify field types, close/open file streams
|
||||
// \return number of fields to sample
|
||||
label prepare(unsigned request);
|
||||
|
||||
//- Get from registry or load from disk
|
||||
template<class GeoField>
|
||||
tmp<GeoField> getOrLoadField(const word& fieldName) const;
|
||||
|
||||
//- Store results: min/max/average/size
|
||||
template<class Type>
|
||||
void storeResults(const word& fieldName, const Field<Type>& values);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Create new streams as required
|
||||
void createProbeFiles(const wordList& fieldNames);
|
||||
|
||||
//- Write field values
|
||||
template<class Type>
|
||||
void writeValues
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
const scalar timeValue
|
||||
);
|
||||
|
||||
//- Sample and store/write all applicable sampled fields
|
||||
template<class GeoField>
|
||||
void performAction
|
||||
(
|
||||
const fieldGroup<GeoField>& fieldNames, /* must be sorted */
|
||||
unsigned request
|
||||
);
|
||||
|
||||
//- Perform sampling action with store/write
|
||||
bool performAction(unsigned request);
|
||||
|
||||
//- No copy construct
|
||||
probes(const probes&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const probes&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
@ -139,19 +288,86 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Bring Base::prober into this class's public scope.
|
||||
using Base::prober;
|
||||
//- Enable/disable verbose output
|
||||
// \return old value
|
||||
bool verbose(const bool on) noexcept;
|
||||
|
||||
//- Read the settings from the dictionary
|
||||
//- Return names of fields to probe
|
||||
virtual const wordRes& fieldNames() const noexcept
|
||||
{
|
||||
return fieldSelection_;
|
||||
}
|
||||
|
||||
//- Return locations to probe
|
||||
virtual const pointField& probeLocations() const noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
//- Return location for probe i
|
||||
virtual const point& probe(const label i) const
|
||||
{
|
||||
return operator[](i);
|
||||
}
|
||||
|
||||
//- Cells to be probed (obtained from the locations)
|
||||
const labelList& elements() const noexcept
|
||||
{
|
||||
return elementList_;
|
||||
}
|
||||
|
||||
//- Read the probes
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
//- Sample and store result if the sampleOnExecute is enabled.
|
||||
virtual bool execute();
|
||||
|
||||
//- Sample and write
|
||||
virtual bool write();
|
||||
|
||||
//- Update for changes of mesh
|
||||
virtual void updateMesh(const mapPolyMesh&);
|
||||
|
||||
//- Update for changes of mesh
|
||||
virtual void movePoints(const polyMesh&);
|
||||
|
||||
//- Update for changes of mesh due to readUpdate
|
||||
virtual void readUpdate(const polyMesh::readUpdateState state)
|
||||
{}
|
||||
|
||||
|
||||
// Sampling
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const VolumeField<Type>&) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const SurfaceField<Type>&) const;
|
||||
|
||||
//- Sample a volume field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sample(const word& fieldName) const;
|
||||
|
||||
//- Sample a surface field at all locations
|
||||
template<class Type>
|
||||
tmp<Field<Type>> sampleSurfaceField(const word& fieldName) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "probesTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
35
src/sampling/probes/probesDict
Normal file
35
src/sampling/probes/probesDict
Normal file
@ -0,0 +1,35 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2306 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object probesDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Fields to be probed. runTime modifiable!
|
||||
fields
|
||||
(
|
||||
p
|
||||
);
|
||||
|
||||
// Locations to be probed. runTime modifiable!
|
||||
probeLocations
|
||||
(
|
||||
(0.0254 0.0253 0.0)
|
||||
(0.0508 0.0253 0.0)
|
||||
(0.0762 0.0253 0.0)
|
||||
(0.1016 0.0253 0.0)
|
||||
(0.1270 0.0253 0.0)
|
||||
(0.1524 0.0253 0.0)
|
||||
(0.1778 0.0253 0.0)
|
||||
);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2025 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,14 +26,47 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "ProbesBase.H"
|
||||
#include "probes.H"
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "IOmanip.H"
|
||||
#include "interpolation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
template<class T>
|
||||
struct isNotEqOp
|
||||
{
|
||||
void operator()(T& x, const T& y) const
|
||||
{
|
||||
const T unsetVal(-VGREAT*pTraits<T>::one);
|
||||
|
||||
if (x != unsetVal)
|
||||
{
|
||||
// Keep x.
|
||||
|
||||
// Note: should check for y != unsetVal but multiple sample cells
|
||||
// already handled in read().
|
||||
}
|
||||
else
|
||||
{
|
||||
// x is not set. y might be.
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Prober>
|
||||
template<class GeoField>
|
||||
Foam::tmp<GeoField>
|
||||
Foam::ProbesBase<Prober>::getOrLoadField(const word& fieldName) const
|
||||
Foam::probes::getOrLoadField(const word& fieldName) const
|
||||
{
|
||||
tmp<GeoField> tfield;
|
||||
|
||||
@ -66,9 +99,8 @@ Foam::ProbesBase<Prober>::getOrLoadField(const word& fieldName) const
|
||||
}
|
||||
|
||||
|
||||
template<class Prober>
|
||||
template<class Type>
|
||||
void Foam::ProbesBase<Prober>::storeResults
|
||||
void Foam::probes::storeResults
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
@ -94,9 +126,8 @@ void Foam::ProbesBase<Prober>::storeResults
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Prober>
|
||||
template<class Type>
|
||||
void Foam::ProbesBase<Prober>::writeValues
|
||||
void Foam::probes::writeValues
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values,
|
||||
@ -110,11 +141,9 @@ void Foam::ProbesBase<Prober>::writeValues
|
||||
|
||||
os << setw(width) << timeValue;
|
||||
|
||||
const bool includeOutOfBounds = prober_.includeOutOfBounds();
|
||||
const labelList& procs = prober_.processors();
|
||||
forAll(values, probei)
|
||||
{
|
||||
if (includeOutOfBounds || procs[probei] != -1)
|
||||
if (includeOutOfBounds_ || processor_[probei] != -1)
|
||||
{
|
||||
os << ' ' << setw(width) << values[probei];
|
||||
}
|
||||
@ -124,9 +153,8 @@ void Foam::ProbesBase<Prober>::writeValues
|
||||
}
|
||||
|
||||
|
||||
template<class Prober>
|
||||
template<class GeoField>
|
||||
void Foam::ProbesBase<Prober>::performAction
|
||||
void Foam::probes::performAction
|
||||
(
|
||||
const fieldGroup<GeoField>& fieldNames,
|
||||
unsigned request
|
||||
@ -141,7 +169,7 @@ void Foam::ProbesBase<Prober>::performAction
|
||||
const auto& field = tfield();
|
||||
const scalar timeValue = field.time().timeOutputValue();
|
||||
|
||||
Field<typename GeoField::value_type> values(prober_.sample(field));
|
||||
Field<typename GeoField::value_type> values(sample(field));
|
||||
|
||||
this->storeResults(fieldName, values);
|
||||
if (request & ACTION_WRITE)
|
||||
@ -153,4 +181,93 @@ void Foam::ProbesBase<Prober>::performAction
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sample(const VolumeField<Type>& vField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
if (fixedLocations_)
|
||||
{
|
||||
autoPtr<interpolation<Type>> interpPtr
|
||||
(
|
||||
interpolation<Type>::New(samplePointScheme_, vField)
|
||||
);
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (elementList_[probei] >= 0)
|
||||
{
|
||||
const vector& position = operator[](probei);
|
||||
|
||||
values[probei] = interpPtr().interpolate
|
||||
(
|
||||
position,
|
||||
elementList_[probei],
|
||||
-1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (elementList_[probei] >= 0)
|
||||
{
|
||||
values[probei] = vField[elementList_[probei]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::listCombineReduce(values, isNotEqOp<Type>());
|
||||
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sample(const SurfaceField<Type>& sField) const
|
||||
{
|
||||
const Type unsetVal(-VGREAT*pTraits<Type>::one);
|
||||
|
||||
auto tvalues = tmp<Field<Type>>::New(Field<Type>(this->size(), unsetVal));
|
||||
auto& values = tvalues.ref();
|
||||
|
||||
forAll(*this, probei)
|
||||
{
|
||||
if (faceList_[probei] >= 0)
|
||||
{
|
||||
values[probei] = sField[faceList_[probei]];
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::listCombineReduce(values, isNotEqOp<Type>());
|
||||
|
||||
return tvalues;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sample(const word& fieldName) const
|
||||
{
|
||||
return sample(mesh_.lookupObject<VolumeField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::probes::sampleSurfaceField(const word& fieldName) const
|
||||
{
|
||||
return sample(mesh_.lookupObject<SurfaceField<Type>>(fieldName));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -149,7 +149,6 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
string line;
|
||||
while (is.good())
|
||||
{
|
||||
string::size_type linei = 0; // Parsing position within current line
|
||||
is.getLine(line);
|
||||
|
||||
// ANSA extension
|
||||
@ -223,16 +222,30 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parsing position within current line
|
||||
std::string::size_type linei = 0;
|
||||
|
||||
// Is free format if line contains a comma
|
||||
const bool freeFormat = line.contains(',');
|
||||
|
||||
// First word (column 0-8)
|
||||
const word cmd(word::validate(nextNasField(line, linei, 8)));
|
||||
|
||||
if (cmd == "CTRIA3")
|
||||
{
|
||||
label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
|
||||
const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40
|
||||
const auto c = readLabel(nextNasField(line, linei, 8)); // 40-48
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : group id
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
// 40-48 : vertex
|
||||
|
||||
label elemId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label groupId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto c = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
// Convert groupId into zoneId
|
||||
const auto iterZone = zoneLookup.cfind(groupId);
|
||||
@ -261,12 +274,20 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
}
|
||||
else if (cmd == "CQUAD4")
|
||||
{
|
||||
label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
|
||||
const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40
|
||||
const auto c = readLabel(nextNasField(line, linei, 8)); // 40-48
|
||||
const auto d = readLabel(nextNasField(line, linei, 8)); // 48-56
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : group id
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
// 40-48 : vertex
|
||||
// 48-56 : vertex
|
||||
|
||||
label elemId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label groupId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto c = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto d = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
// Convert groupId into zoneId
|
||||
const auto iterZone = zoneLookup.cfind(groupId);
|
||||
@ -310,11 +331,21 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
}
|
||||
else if (cmd == "GRID")
|
||||
{
|
||||
label index = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
(void) nextNasField(line, linei, 8); // 16-24
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8)); // 24-32
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8)); // 32-40
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8)); // 40-48
|
||||
// Fixed (short) format:
|
||||
// 8-16 : point id
|
||||
// 16-24 : coordinate system (not supported)
|
||||
// 24-32 : point x coordinate
|
||||
// 32-40 : point y coordinate
|
||||
// 40-48 : point z coordinate
|
||||
// 48-56 : displacement coordinate system (optional, unsupported)
|
||||
// 56-64 : single point constraints (optional, unsupported)
|
||||
// 64-70 : super-element id (optional, unsupported)
|
||||
|
||||
label index = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
pointId.append(index);
|
||||
dynPoints.append(point(x, y, z));
|
||||
@ -327,6 +358,8 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
// GRID* 126 0 -5.55999875E+02 -5.68730474E+02
|
||||
// * 2.14897901E+02
|
||||
|
||||
// Cannot be long format and free format at the same time!
|
||||
|
||||
label index = readLabel(nextNasField(line, linei, 16)); // 8-24
|
||||
(void) nextNasField(line, linei, 16); // 24-40
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -307,16 +307,10 @@ void Foam::surfaceWriters::nastranWriter::writeGeometry
|
||||
Foam::surfaceWriters::nastranWriter::nastranWriter()
|
||||
:
|
||||
surfaceWriter(),
|
||||
writeFormat_(fieldFormat::SHORT),
|
||||
fieldMap_(),
|
||||
writeFormat_(fieldFormat::FREE),
|
||||
commonGeometry_(false),
|
||||
separator_()
|
||||
{
|
||||
// if (writeFormat_ == fieldFormat::FREE)
|
||||
// {
|
||||
// separator_ = ",";
|
||||
// }
|
||||
}
|
||||
separator_(",") // FREE format
|
||||
{}
|
||||
|
||||
|
||||
Foam::surfaceWriters::nastranWriter::nastranWriter
|
||||
@ -331,12 +325,10 @@ Foam::surfaceWriters::nastranWriter::nastranWriter
|
||||
(
|
||||
"format",
|
||||
options,
|
||||
fieldFormat::LONG
|
||||
fieldFormat::FREE
|
||||
)
|
||||
),
|
||||
fieldMap_(),
|
||||
commonGeometry_(options.getOrDefault("commonGeometry", false)),
|
||||
separator_()
|
||||
commonGeometry_(options.getOrDefault("commonGeometry", false))
|
||||
{
|
||||
if (writeFormat_ == fieldFormat::FREE)
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -33,13 +33,13 @@ Description
|
||||
The formatOptions for nastran:
|
||||
\table
|
||||
Property | Description | Reqd | Default
|
||||
fields | Field pairs for PLOAD2/PLOAD4 | yes |
|
||||
format | Nastran format (short/long/free) | no | long
|
||||
format | Nastran format (short/long/free) | no | free
|
||||
scale | Output geometry scaling | no | 1
|
||||
transform | Output coordinate transform | no |
|
||||
fieldLevel | Subtract field level before scaling | no | empty dict
|
||||
fieldScale | Output field scaling | no | empty dict
|
||||
commonGeometry | use separate geometry files | no | false
|
||||
fields | Field pairs for PLOAD2/PLOAD4 | yes |
|
||||
\endtable
|
||||
|
||||
For example,
|
||||
@ -48,13 +48,6 @@ Description
|
||||
{
|
||||
nastran
|
||||
{
|
||||
// OpenFOAM field name to NASTRAN load types
|
||||
fields
|
||||
(
|
||||
(pMean PLOAD2)
|
||||
(p PLOAD4)
|
||||
);
|
||||
|
||||
format free; // format type
|
||||
|
||||
scale 1000; // [m] -> [mm]
|
||||
@ -62,6 +55,13 @@ Description
|
||||
{
|
||||
"p.*" 0.01; // [Pa] -> [mbar]
|
||||
}
|
||||
|
||||
// OpenFOAM field name to NASTRAN load types
|
||||
fields
|
||||
(
|
||||
(pMean PLOAD2)
|
||||
(p PLOAD4)
|
||||
);
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
@ -93,7 +93,6 @@ Description
|
||||
|
||||
Note
|
||||
Output variable scaling does not apply to integer types such as Ids.
|
||||
Field pairs default to PLOAD2 for scalars and PLOAD4 for vectors etc.
|
||||
|
||||
SourceFiles
|
||||
nastranSurfaceWriter.C
|
||||
@ -221,10 +220,10 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct. Default SHORT format
|
||||
//- Default construct. Default FREE format
|
||||
nastranWriter();
|
||||
|
||||
//- Construct with some output options. Default LONG format
|
||||
//- Construct with some output options. Default FREE format
|
||||
explicit nastranWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
|
||||
@ -240,9 +240,6 @@ public:
|
||||
return radiation_;
|
||||
}
|
||||
|
||||
//- Return the radiation solver frequency
|
||||
label solverFreq() const noexcept { return solverFreq_; }
|
||||
|
||||
//- Source term component (for power of T^4)
|
||||
virtual tmp<volScalarField> Rp() const = 0;
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ solvers
|
||||
"pcorr.*"
|
||||
{
|
||||
solver GAMG;
|
||||
smoother GaussSeidel;
|
||||
smoother DICGaussSeidel;
|
||||
cacheAgglomeration no;
|
||||
tolerance 0.02;
|
||||
relTol 0;
|
||||
|
||||
Reference in New Issue
Block a user