ENH: additional ensight output routines for finite-area fields (#2084)

- adds support for retaining local face numbers, to allow direct
  addressing into the corresponding area field
This commit is contained in:
Mark Olesen
2021-05-28 14:11:54 +02:00
parent 6c4a1b17ad
commit 9f5df1adba
19 changed files with 757 additions and 177 deletions

View File

@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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/>.
InNamespace
Foam::ensightOutput
Description
A collection of functions for writing areaField content in ensight format.
\*---------------------------------------------------------------------------*/
#ifndef ensightOutputAreaField_H
#define ensightOutputAreaField_H
#include "ensightOutput.H"
#include "ensightFaces.H"
#include "areaFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class ensightFaMesh;
namespace ensightOutput
{
/*---------------------------------------------------------------------------*\
Namespace ensightOutput
\*---------------------------------------------------------------------------*/
//- Write finite-area field component-wise
template<class Type>
bool writeAreaField
(
ensightFile& os,
const GeometricField<Type, faPatchField, areaMesh>& fld,
const ensightFaMesh& ensMesh
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace ensightOutput
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "ensightOutputAreaFieldTemplates.C"
#endif
#endif
// ************************************************************************* //

View File

@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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 "ensightOutputAreaField.H"
#include "ensightFaMesh.H"
#include "areaFaMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
bool Foam::ensightOutput::writeAreaField
(
ensightFile& os,
const GeometricField<Type, faPatchField, areaMesh>& fld,
const ensightFaMesh& ensMesh
)
{
bool parallel = Pstream::parRun();
// Write area part(s)
{
ensightOutput::Detail::writeFaceLocalField
(
os,
fld,
ensMesh.areaPart(),
parallel
);
}
return true;
}
// ************************************************************************* //

View File

@ -146,7 +146,10 @@ public:
// Access // Access
//- Reference to the underlying polyMesh //- Reference to the underlying polyMesh
inline const polyMesh& mesh() const; const polyMesh& mesh() const noexcept
{
return mesh_;
}
//- Reference to the writer/mesh options //- Reference to the writer/mesh options
inline const ensightMesh::options& option() const; inline const ensightMesh::options& option() const;
@ -154,30 +157,42 @@ public:
//- Face elements per selected patch, lookup by patch index //- Face elements per selected patch, lookup by patch index
// Process in sorted order. // Process in sorted order.
// May require special treatment for zone -1 (internal). // May require special treatment for zone -1 (internal).
inline const Map<ensightCells>& cellZoneParts() const; const Map<ensightCells>& cellZoneParts() const noexcept
{
return cellZoneParts_;
}
//- Face elements per faceZone, lookup by zone index. //- Face elements per faceZone, lookup by zone index.
// Process in sorted order. // Process in sorted order.
inline const Map<ensightFaces>& faceZoneParts() const; const Map<ensightFaces>& faceZoneParts() const noexcept
{
return faceZoneParts_;
}
//- Face elements per selected patch, lookup by patch index //- Face elements per selected patch, lookup by patch index
// Process in sorted order. // Process in sorted order.
inline const Map<ensightFaces>& boundaryParts() const; const Map<ensightFaces>& boundaryParts() const noexcept
{
return boundaryParts_;
}
// Sizing Information // Sizing Information
//- Any parts? //- Any parts?
inline bool empty() const; inline bool empty() const noexcept;
//- Number of parts //- Number of parts
inline label size() const; inline label size() const noexcept;
// Other // Other
//- Does the content need an update? //- Does the content need an update?
inline bool needsUpdate() const; bool needsUpdate() const noexcept
{
return needsUpdate_;
}
//- Mark as needing an update. //- Mark as needing an update.
// May also free up unneeded data. // May also free up unneeded data.
@ -191,16 +206,16 @@ public:
// Output // Output
//- Write geometry to file. Normally in parallel //- Write geometry to file. Normally in parallel
inline void write void write
( (
autoPtr<ensightGeoFile>& os, ensightGeoFile& os,
bool parallel = Pstream::parRun() bool parallel = Pstream::parRun()
) const; ) const;
//- Write geometry to file. Normally in parallel //- Write geometry to file. Normally in parallel
void write inline void write
( (
ensightGeoFile& os, autoPtr<ensightGeoFile>& os,
bool parallel = Pstream::parRun() bool parallel = Pstream::parRun()
) const; ) const;
}; };
@ -252,32 +267,44 @@ public:
// Access // Access
//- Lazy creation? (ie, ensightMesh starts as needsUpdate) //- Lazy creation? (ie, starts as needsUpdate)
bool lazy() const; bool lazy() const noexcept;
//- Using internal? //- Using internal?
bool useInternalMesh() const; bool useInternalMesh() const noexcept;
//- Using boundary? //- Using boundary?
bool useBoundaryMesh() const; bool useBoundaryMesh() const noexcept;
//- Using faceZones? //- Using faceZones?
bool useFaceZones() const; bool useFaceZones() const noexcept;
//- Using cellZones? //- Using cellZones?
bool useCellZones() const; bool useCellZones() const noexcept;
//- Selection of patches. Empty if unspecified. //- Selection of patches. Empty if unspecified.
const wordRes& patchSelection() const; const wordRes& patchSelection() const noexcept
{
return patchInclude_;
}
//- Selection of black listed patches. Empty if unspecified. //- Selection of black listed patches. Empty if unspecified.
const wordRes& patchExclude() const; const wordRes& patchExclude() const noexcept
{
return patchExclude_;
}
//- Selection of faceZones. Empty if unspecified. //- Selection of faceZones. Empty if unspecified.
const wordRes& faceZoneSelection() const; const wordRes& faceZoneSelection() const noexcept
{
return faceZoneInclude_;
}
//- Selection of faceZones. Empty if unspecified. //- Selection of faceZones. Empty if unspecified.
const wordRes& cellZoneSelection() const; const wordRes& cellZoneSelection() const noexcept
{
return cellZoneInclude_;
}
// Edit // Edit
@ -286,16 +313,20 @@ public:
void reset(); void reset();
//- Lazy creation - ensightMesh starts as needsUpdate //- Lazy creation - ensightMesh starts as needsUpdate
void lazy(bool beLazy); // \return old value
bool lazy(bool on) noexcept;
//- Alter the useBoundaryMesh state //- Alter the useBoundaryMesh state
void useInternalMesh(bool on); // \return old value
bool useInternalMesh(bool on) noexcept;
//- Alter the useBoundaryMesh state //- Alter the useBoundaryMesh state
void useBoundaryMesh(bool on); // \return old value
bool useBoundaryMesh(bool on);
//- Alter the useCellZones state //- Alter the useCellZones state
void useCellZones(bool on); // \return old value
bool useCellZones(bool on);
//- Define patch selection matcher //- Define patch selection matcher
void patchSelection(const UList<wordRe>& patterns); void patchSelection(const UList<wordRe>& patterns);

View File

@ -27,39 +27,12 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::polyMesh& Foam::ensightMesh::mesh() const
{
return mesh_;
}
inline const Foam::ensightMesh::options& Foam::ensightMesh::option() const inline const Foam::ensightMesh::options& Foam::ensightMesh::option() const
{ {
return *options_; return *options_;
} }
inline const Foam::Map<Foam::ensightCells>&
Foam::ensightMesh::cellZoneParts() const
{
return cellZoneParts_;
}
inline const Foam::Map<Foam::ensightFaces>&
Foam::ensightMesh::faceZoneParts() const
{
return faceZoneParts_;
}
inline const Foam::Map<Foam::ensightFaces>&
Foam::ensightMesh::boundaryParts() const
{
return boundaryParts_;
}
inline bool Foam::ensightMesh::expire() inline bool Foam::ensightMesh::expire()
{ {
clear(); clear();
@ -75,13 +48,7 @@ inline bool Foam::ensightMesh::expire()
} }
inline bool Foam::ensightMesh::needsUpdate() const inline bool Foam::ensightMesh::empty() const noexcept
{
return needsUpdate_;
}
inline bool Foam::ensightMesh::empty() const
{ {
return return
( (
@ -92,7 +59,7 @@ inline bool Foam::ensightMesh::empty() const
} }
inline Foam::label Foam::ensightMesh::size() const inline Foam::label Foam::ensightMesh::size() const noexcept
{ {
return return
( (

View File

@ -43,9 +43,9 @@ static Ostream& printPatterns(Ostream& os, const wordRes& list)
for (const wordRe& item : list) for (const wordRe& item : list)
{ {
if (sep) os << token::SPACE; if (sep) os << token::SPACE;
os << item;
sep = true; sep = true;
os << item;
} }
os << token::END_LIST; os << token::END_LIST;
@ -72,31 +72,31 @@ Foam::ensightMesh::options::options()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::ensightMesh::options::lazy() const bool Foam::ensightMesh::options::lazy() const noexcept
{ {
return lazy_; return lazy_;
} }
bool Foam::ensightMesh::options::useInternalMesh() const bool Foam::ensightMesh::options::useInternalMesh() const noexcept
{ {
return internal_; return internal_;
} }
bool Foam::ensightMesh::options::useBoundaryMesh() const bool Foam::ensightMesh::options::useBoundaryMesh() const noexcept
{ {
return boundary_; return boundary_;
} }
bool Foam::ensightMesh::options::useCellZones() const bool Foam::ensightMesh::options::useCellZones() const noexcept
{ {
return cellZones_; return cellZones_;
} }
bool Foam::ensightMesh::options::useFaceZones() const bool Foam::ensightMesh::options::useFaceZones() const noexcept
{ {
return faceZoneInclude_.size(); return faceZoneInclude_.size();
} }
@ -114,20 +114,25 @@ void Foam::ensightMesh::options::reset()
} }
void Foam::ensightMesh::options::lazy(bool beLazy) bool Foam::ensightMesh::options::lazy(bool on) noexcept
{ {
lazy_ = beLazy; bool old(lazy_);
lazy_ = on;
return old;
} }
void Foam::ensightMesh::options::useInternalMesh(bool on) bool Foam::ensightMesh::options::useInternalMesh(bool on) noexcept
{ {
bool old(internal_);
internal_ = on; internal_ = on;
return old;
} }
void Foam::ensightMesh::options::useBoundaryMesh(bool on) bool Foam::ensightMesh::options::useBoundaryMesh(bool on)
{ {
bool old(boundary_);
boundary_ = on; boundary_ = on;
if (!boundary_) if (!boundary_)
@ -141,11 +146,14 @@ void Foam::ensightMesh::options::useBoundaryMesh(bool on)
<< endl; << endl;
} }
} }
return old;
} }
void Foam::ensightMesh::options::useCellZones(bool on) bool Foam::ensightMesh::options::useCellZones(bool on)
{ {
bool old(cellZones_);
cellZones_ = on; cellZones_ = on;
if (!cellZones_ && cellZoneInclude_.size()) if (!cellZones_ && cellZoneInclude_.size())
@ -156,6 +164,8 @@ void Foam::ensightMesh::options::useCellZones(bool on)
<< "Deactivating cellZones, removed old zone selection" << "Deactivating cellZones, removed old zone selection"
<< endl; << endl;
} }
return old;
} }
@ -267,30 +277,6 @@ void Foam::ensightMesh::options::cellZoneSelection
} }
const Foam::wordRes& Foam::ensightMesh::options::patchSelection() const
{
return patchInclude_;
}
const Foam::wordRes& Foam::ensightMesh::options::patchExclude() const
{
return patchExclude_;
}
const Foam::wordRes& Foam::ensightMesh::options::faceZoneSelection() const
{
return faceZoneInclude_;
}
const Foam::wordRes& Foam::ensightMesh::options::cellZoneSelection() const
{
return cellZoneInclude_;
}
void Foam::ensightMesh::options::print(Ostream& os) const void Foam::ensightMesh::options::print(Ostream& os) const
{ {
os << "internal: " << Switch::name(internal_) << nl; os << "internal: " << Switch::name(internal_) << nl;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -307,6 +307,18 @@ bool writeFaceSubField
); );
//- Write a field of faces values as an indirect list,
//- using the face order from ensightFaces
template<class Type>
bool writeFaceLocalField
(
ensightFile& os,
const Field<Type>& fld,
const ensightFaces& part,
bool parallel //!< Collective write?
);
} // End namespace Detail } // End namespace Detail

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -236,8 +236,6 @@ bool Foam::ensightOutput::Detail::writeFaceSubField
os.beginPart(part.index()); os.beginPart(part.index());
} }
labelList localAddr;
for (int typei=0; typei < ensightFaces::nTypes; ++typei) for (int typei=0; typei < ensightFaces::nTypes; ++typei)
{ {
const auto etype = ensightFaces::elemType(typei); const auto etype = ensightFaces::elemType(typei);
@ -255,6 +253,71 @@ bool Foam::ensightOutput::Detail::writeFaceSubField
} }
template<class Type>
bool Foam::ensightOutput::Detail::writeFaceLocalField
(
ensightFile& os,
const Field<Type>& fld,
const ensightFaces& part,
bool parallel
)
{
parallel = parallel && Pstream::parRun();
// Preliminary checks: total() contains pre-reduced information
{
// No geometry
if (parallel ? !part.total() : !part.size()) return false;
bool hasField = !fld.empty();
if (parallel)
{
reduce(hasField, orOp<bool>());
}
// No field
if (!hasField) return false;
}
bool validAddressing = (part.size() == part.faceOrder().size());
if (parallel)
{
reduce(validAddressing, orOp<bool>());
}
if (!validAddressing)
{
FatalErrorInFunction
<< "Called without faceOrder having been set" << nl
<< exit(FatalError);
}
if (Pstream::master())
{
os.beginPart(part.index());
}
for (int typei=0; typei < ensightFaces::nTypes; ++typei)
{
const auto etype = ensightFaces::elemType(typei);
ensightOutput::Detail::writeFieldComponents
(
os,
ensightFaces::key(etype),
UIndirectList<Type>(fld, part.faceOrder(etype)),
parallel
);
}
return true;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> template<class Type>
bool Foam::ensightOutput::writeField bool Foam::ensightOutput::writeField
( (

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -39,7 +39,9 @@ namespace Foam
} }
const char* Foam::ensightCells::elemNames[5] = const char* Foam::ensightCells::elemNames[5] =
{ "tetra4", "pyramid5", "penta6", "hexa8", "nfaced" }; {
"tetra4", "pyramid5", "penta6", "hexa8", "nfaced"
};
static_assert static_assert
( (
@ -106,12 +108,12 @@ Foam::FixedList<Foam::label, 5> Foam::ensightCells::sizes() const
Foam::label Foam::ensightCells::total() const Foam::label Foam::ensightCells::total() const
{ {
label n = 0; label nTotal = 0;
forAll(sizes_, typei) forAll(sizes_, typei)
{ {
n += sizes_[typei]; nTotal += sizes_[typei];
} }
return n; return nTotal;
} }

View File

@ -99,7 +99,8 @@ private:
// Private Member Functions // Private Member Functions
//- Low-level internal addition routine //- Low-level internal addition routine
inline void add(const elemType etype, label id); // \return insertion locaion
inline label add(const elemType etype, label id);
//- Use temporarily stored sizes to redimension the element lists //- Use temporarily stored sizes to redimension the element lists
void resizeAll(); void resizeAll();

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,12 +27,14 @@ License
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
inline void Foam::ensightCells::add(const elemType etype, label id) inline Foam::label Foam::ensightCells::add(const elemType etype, label id)
{ {
// Linear addressing location // Linear addressing location
const label index = offsets_[etype] + sizes_[etype]++; const label index = offsets_[etype] + sizes_[etype]++;
addressing()[index] = id; addressing()[index] = id;
return index;
} }

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -37,7 +37,9 @@ namespace Foam
} }
const char* Foam::ensightFaces::elemNames[3] = const char* Foam::ensightFaces::elemNames[3] =
{ "tria3", "quad4", "nsided" }; {
"tria3", "quad4", "nsided"
};
static_assert static_assert
( (
@ -52,7 +54,7 @@ namespace
{ {
// Trivial shape classifier // Trivial shape classifier
static inline Foam::ensightFaces::elemType whatType(const Foam::face& f) inline Foam::ensightFaces::elemType whatType(const Foam::face& f)
{ {
return return
( (
@ -71,6 +73,12 @@ static inline Foam::ensightFaces::elemType whatType(const Foam::face& f)
void Foam::ensightFaces::resizeAll() void Foam::ensightFaces::resizeAll()
{ {
// Invalidate any previous face ordering
faceOrder_.clear();
// Invalidate any previous flipMap
flipMap_.clear();
// Assign sub-list offsets, determine overall size // Assign sub-list offsets, determine overall size
label len = 0; label len = 0;
@ -87,9 +95,6 @@ void Foam::ensightFaces::resizeAll()
// The addressing space // The addressing space
addressing().resize(len, Zero); addressing().resize(len, Zero);
// Normally assume no flipMap
flipMap_.clear();
} }
@ -98,6 +103,7 @@ void Foam::ensightFaces::resizeAll()
Foam::ensightFaces::ensightFaces() Foam::ensightFaces::ensightFaces()
: :
ensightPart(), ensightPart(),
faceOrder_(),
flipMap_(), flipMap_(),
offsets_(Zero), offsets_(Zero),
sizes_(Zero) sizes_(Zero)
@ -129,12 +135,12 @@ Foam::FixedList<Foam::label, 3> Foam::ensightFaces::sizes() const
Foam::label Foam::ensightFaces::total() const Foam::label Foam::ensightFaces::total() const
{ {
label n = 0; label nTotal = 0;
forAll(sizes_, typei) forAll(sizes_, typei)
{ {
n += sizes_[typei]; nTotal += sizes_[typei];
} }
return n; return nTotal;
} }
@ -144,6 +150,7 @@ void Foam::ensightFaces::clear()
ensightPart::clear(); ensightPart::clear();
faceOrder_.clear();
flipMap_.clear(); flipMap_.clear();
sizes_ = Zero; sizes_ = Zero;
offsets_ = Zero; offsets_ = Zero;
@ -167,42 +174,42 @@ void Foam::ensightFaces::reduce()
void Foam::ensightFaces::sort() void Foam::ensightFaces::sort()
{ {
const bool useFlip = (size() == flipMap_.size()); // Some extra safety
if (faceOrder_.size() != size())
if (useFlip)
{ {
// Must sort flip map as well faceOrder_.clear();
labelList order;
for (int typei=0; typei < nTypes; ++typei)
{
const labelRange sub(range(elemType(typei)));
if (!sub.empty())
{
SubList<label> ids(addressing(), sub);
SubList<bool> flips(flipMap_, sub);
Foam::sortedOrder(ids, order);
ids = reorder<labelList>(order, ids);
flips = reorder<boolList>(order, flips);
}
}
} }
else if (flipMap_.size() != size())
{ {
flipMap_.clear(); // Extra safety flipMap_.clear();
}
// No flip-maps, simply sort addresses // Sort by face Ids.
for (int typei=0; typei < nTypes; ++typei) // Use to reorder flip maps and face-order too.
for (int typei=0; typei < nTypes; ++typei)
{
const labelRange sub(range(elemType(typei)));
if (!sub.empty())
{ {
const labelRange sub(range(elemType(typei))); SubList<label> ids(sub, addressing());
labelList order(Foam::sortedOrder(ids));
if (!sub.empty()) ids = reorder<labelList>(order, ids);
// Sort flip map as well
if (!flipMap_.empty())
{ {
SubList<label> ids(addressing(), sub); SubList<bool> flips(flipMap_, sub);
Foam::sort(ids); flips = reorder<boolList>(order, flips);
}
// Sort face ordering as well
if (!faceOrder_.empty())
{
SubList<label> faceOrder(faceOrder_, sub);
faceOrder = reorder<labelList>(order, faceOrder);
} }
} }
} }
@ -226,7 +233,6 @@ void Foam::ensightFaces::classify(const UList<face>& faces)
resizeAll(); // adjust allocation resizeAll(); // adjust allocation
sizes_ = Zero; // reset sizes - use for local indexing here sizes_ = Zero; // reset sizes - use for local indexing here
// Pass 2: Assign face-id per shape type // Pass 2: Assign face-id per shape type
for (label listi = 0; listi < len; ++listi) for (label listi = 0; listi < len; ++listi)
@ -283,28 +289,34 @@ void Foam::ensightFaces::classify
resizeAll(); // adjust allocation resizeAll(); // adjust allocation
sizes_ = Zero; // reset sizes - use for local indexing here sizes_ = Zero; // reset sizes - use for local indexing here
label nUsed = addressing().size();
if (useFlip) if (useFlip)
{ {
flipMap_.resize(len); flipMap_.resize(nUsed);
flipMap_ = false; flipMap_ = false;
} }
else
{ faceOrder_.resize(nUsed);
flipMap_.clear(); // Extra safety
}
// Pass 2: Assign face-id per shape type // Pass 2: Assign face-id per shape type
// - also record the face order
nUsed = 0;
for (label listi = 0; listi < len; ++listi) for (label listi = 0; listi < len; ++listi)
{ {
const label faceId = addr[listi]; const label faceId = addr[listi];
const bool doFlip = useFlip && flipMap[listi];
if (!exclude.test(faceId)) if (!exclude.test(faceId))
{ {
const bool doFlip = useFlip && flipMap.test(listi);
const auto etype = whatType(faces[faceId]); const auto etype = whatType(faces[faceId]);
add(etype, faceId, doFlip); const label idx = add(etype, faceId, doFlip);
faceOrder_[nUsed] = idx;
++nUsed;
} }
} }
} }

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -43,14 +43,17 @@ Description
// Can now address into boundaryField // Can now address into boundaryField
\endcode \endcode
Additionally, for some uses (eg, finiteArea), the ordered
list of faces can be used for a direct local lookup into the field
instead of via the overall mesh face addressing.
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef ensightFaces_H #ifndef ensightFaces_H
#define ensightFaces_H #define ensightFaces_H
#include "ensightPart.H" #include "ensightPart.H"
#include "boolList.H" #include "face.H"
#include "faceList.H"
#include "FixedList.H" #include "FixedList.H"
#include "bitSet.H" #include "bitSet.H"
@ -100,7 +103,10 @@ private:
// Private Data // Private Data
//- Linear list of face-flips //- The input face order, for indirect face lists
labelList faceOrder_;
//- List of face-flips (optional)
boolList flipMap_; boolList flipMap_;
//- Begin/end offsets for address/flips of each element type //- Begin/end offsets for address/flips of each element type
@ -113,8 +119,9 @@ private:
// Private Member Functions // Private Member Functions
//- Low-level internal addition routine //- Low-level internal addition routine.
inline void add(const elemType etype, label id, bool flip=false); // \return insertion locaion
inline label add(const elemType etype, label id, bool flip=false);
//- Use temporarily stored sizes to redimension the element lists //- Use temporarily stored sizes to redimension the element lists
void resizeAll(); void resizeAll();
@ -168,7 +175,7 @@ public:
FixedList<label, nTypes> sizes() const; FixedList<label, nTypes> sizes() const;
//- Processor-local face ids of all elements //- Processor-local face ids of all elements
inline const labelList& faceIds() const; inline const labelList& faceIds() const noexcept;
//- Processor-local face ids of the specified element type //- Processor-local face ids of the specified element type
inline const labelUList faceIds(const elemType etype) const; inline const labelUList faceIds(const elemType etype) const;
@ -179,6 +186,14 @@ public:
//- True for non-zero flip-map that spans the addresses //- True for non-zero flip-map that spans the addresses
inline bool usesFlipMap() const; inline bool usesFlipMap() const;
//- Processor-local face order
//- (where applicable)
inline const labelList& faceOrder() const noexcept;
//- Processor-local face order of specified element type
//- (where applicable)
inline const labelUList faceOrder(const elemType etype) const;
// Edit // Edit
@ -211,7 +226,7 @@ public:
//- Sum element counts across all processes. //- Sum element counts across all processes.
void reduce(); void reduce();
//- Sort element lists numerically. //- Inplace sort element lists numerically.
void sort(); void sort();

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +27,8 @@ License
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
inline void Foam::ensightFaces::add(const elemType etype, label id, bool flip) inline Foam::label
Foam::ensightFaces::add(const elemType etype, label id, bool flip)
{ {
// Linear addressing location // Linear addressing location
const label index = offsets_[etype] + sizes_[etype]++; const label index = offsets_[etype] + sizes_[etype]++;
@ -38,6 +39,8 @@ inline void Foam::ensightFaces::add(const elemType etype, label id, bool flip)
{ {
flipMap_[index] = flip; flipMap_[index] = flip;
} }
return index;
} }
@ -73,7 +76,7 @@ inline Foam::labelRange Foam::ensightFaces::range(const elemType etype) const
} }
inline const Foam::labelList& Foam::ensightFaces::faceIds() const inline const Foam::labelList& Foam::ensightFaces::faceIds() const noexcept
{ {
return addressing(); return addressing();
} }
@ -98,6 +101,20 @@ inline bool Foam::ensightFaces::usesFlipMap() const
} }
inline const Foam::labelList&
Foam::ensightFaces::faceOrder() const noexcept
{
return faceOrder_;
}
inline const Foam::labelUList
Foam::ensightFaces::faceOrder(const elemType etype) const
{
return faceOrder_[range(etype)];
}
inline void Foam::ensightFaces::incrFaceIds(const label off) inline void Foam::ensightFaces::incrFaceIds(const label off)
{ {
incrAddressing(off); incrAddressing(off);

View File

@ -58,7 +58,7 @@ void Foam::ensightPart::decrAddressing(const label off)
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ensightPart::ensightPart() noexcept Foam::ensightPart::ensightPart()
: :
index_(0), index_(0),
identifier_(-1), identifier_(-1),

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -74,13 +74,13 @@ class ensightPart
protected: protected:
//- Element addressing //- Element addressing
const labelList& addressing() const const labelList& addressing() const noexcept
{ {
return address_; return address_;
} }
//- Element addressing //- Element addressing
labelList& addressing() labelList& addressing() noexcept
{ {
return address_; return address_;
} }
@ -109,7 +109,7 @@ public:
// Constructors // Constructors
//- Default construct. Index=0, identifier = -1 //- Default construct. Index=0, identifier = -1
ensightPart() noexcept; ensightPart();
//- Default construct, with description/partName //- Default construct, with description/partName
explicit ensightPart(const string& description); explicit ensightPart(const string& description);
@ -122,43 +122,43 @@ public:
// Member Functions // Member Functions
//- The index in a list (0-based) //- The index in a list (0-based)
label index() const label index() const noexcept
{ {
return index_; return index_;
} }
//- The index in a list (0-based) //- The index in a list (0-based)
label& index() label& index() noexcept
{ {
return index_; return index_;
} }
//- OpenFOAM identifier (patch, zone, etc), -1 when not in use. //- OpenFOAM identifier (patch, zone, etc), -1 when not in use.
label identifier() const label identifier() const noexcept
{ {
return identifier_; return identifier_;
} }
//- OpenFOAM identifier (patch, zone, etc), -1 when not in use. //- OpenFOAM identifier (patch, zone, etc), -1 when not in use.
label& identifier() label& identifier() noexcept
{ {
return identifier_; return identifier_;
} }
//- Processor-local test for any elements. //- Processor-local test for any elements.
bool empty() const bool empty() const noexcept
{ {
return address_.empty(); return address_.empty();
} }
//- Processor-local size of all elements. //- Processor-local size of all elements.
label size() const label size() const noexcept
{ {
return address_.size(); return address_.size();
} }
//- The part name or description //- The part name or description
const string& name() const const string& name() const noexcept
{ {
return name_; return name_;
} }

View File

@ -16,6 +16,9 @@ $(faPatches)/constraint/wedge/wedgeFaPatch.C
$(faPatches)/constraint/cyclic/cyclicFaPatch.C $(faPatches)/constraint/cyclic/cyclicFaPatch.C
$(faPatches)/constraint/symmetry/symmetryFaPatch.C $(faPatches)/constraint/symmetry/symmetryFaPatch.C
ensight = output/ensight
$(ensight)/ensightFaMesh.C
faMeshMapper = faMesh/faMeshMapper faMeshMapper = faMesh/faMeshMapper
$(faMeshMapper)/faMeshMapper.C $(faMeshMapper)/faMeshMapper.C
$(faMeshMapper)/faAreaMapper.C $(faMeshMapper)/faAreaMapper.C

View File

@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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 "ensightFaMesh.H"
#include "ensightGeoFile.H"
#include "faMesh.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::ensightFaMesh::clear()
{
areaPart_.clear();
}
void Foam::ensightFaMesh::renumber()
{
label partNo = 0;
areaPart_.index() = partNo++;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ensightFaMesh::ensightFaMesh
(
const faMesh& mesh
)
:
mesh_(mesh),
needsUpdate_(true)
{
// Lazy?
if (true)
{
correct();
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::ensightFaMesh::correct()
{
clear();
// Area meshes (currently only one)
const label areaId = 0;
{
ensightFaces& part = areaPart_;
part.clear();
part.identifier() = areaId;
part.rename("finite-area");
part.classify
(
mesh_.mesh().faces(),
mesh_.faceLabels()
);
// Finalize
part.reduce();
// if (!part.total())
// {
// areaParts_.erase(areaId);
// }
}
renumber();
needsUpdate_ = false;
}
void Foam::ensightFaMesh::write
(
ensightGeoFile& os,
bool parallel
) const
{
// Area meshes (currently only one)
// const label areaId = 0;
areaPart_.write(os, mesh_.mesh(), parallel);
}
// ************************************************************************* //

View File

@ -0,0 +1,162 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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::ensightFaMesh
Description
Encapsulation of area meshes for writing in ensight format.
Note
Currently restricted to a single faMesh representation.
The face elements are created from a specified subset of polyMesh
faces. The original ordering of these faces is retained in the
ensightFaces faceOrder().
SourceFiles
ensightFaMesh.C
ensightFaMeshI.H
\*---------------------------------------------------------------------------*/
#ifndef fa_ensightMesh_H
#define fa_ensightMesh_H
#include "ensightFaces.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class faMesh;
class ensightGeoFile;
class ensightFaMesh;
/*---------------------------------------------------------------------------*\
Class ensightMesh Declaration
\*---------------------------------------------------------------------------*/
class ensightFaMesh
{
// Private Data
//- Reference to the finite-area mesh
const faMesh& mesh_;
//- Face elements for the area mesh (currently only one)
ensightFaces areaPart_;
//- Track if it needs an update
mutable bool needsUpdate_;
// Private Member Functions
//- Clear all storage
void clear();
//- Enforce consistent index/part numbering
void renumber();
//- No copy construct
ensightFaMesh(const ensightFaMesh&) = delete;
//- No copy assignment
void operator=(const ensightFaMesh&) = delete;
public:
// Constructors
//- Construct from mesh with all default options
explicit ensightFaMesh(const faMesh& mesh);
// Member Functions
// Access
//- Reference to the underlying faMesh
const faMesh& mesh() const noexcept
{
return mesh_;
}
//- Face elements for finite-area
const ensightFaces& areaPart() const noexcept
{
return areaPart_;
}
// Other
//- Does the content need an update?
bool needsUpdate() const noexcept
{
return needsUpdate_;
}
//- Mark as needing an update.
// May also free up unneeded data.
// Return false if already marked as expired.
inline bool expire();
//- Update for new mesh
void correct();
// Output
//- Write geometry to file. Normally in parallel
void write
(
ensightGeoFile& os,
bool parallel = Pstream::parRun()
) const;
//- Write geometry to file. Normally in parallel
inline void write
(
autoPtr<ensightGeoFile>& os,
bool parallel = Pstream::parRun()
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "ensightFaMeshI.H"
#endif
// ************************************************************************* //

View File

@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::ensightFaMesh::expire()
{
clear();
// Already marked as expired
if (needsUpdate_)
{
return false;
}
needsUpdate_ = true;
return true;
}
inline void Foam::ensightFaMesh::write
(
autoPtr<ensightGeoFile>& os,
bool parallel
) const
{
write(os.ref(), parallel);
}
// ************************************************************************* //