mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add low-level handling for abaqus files (#1600)
- reads/write shell elements Output elements are "bunched" according to type and their set without reordering. - preliminary reading of solids without extraction. Handling of *Surface specifications is not implemented
This commit is contained in:
@ -25,6 +25,7 @@ $(part)/surface/ensightOutputSurface.C
|
||||
ensight/read/ensightReadFile.C
|
||||
ensight/type/ensightPTraits.C
|
||||
|
||||
abaqus/ABAQUSCore.C
|
||||
nastran/NASCore.C
|
||||
obj/OBJstream.C
|
||||
fire/FIRECore.C
|
||||
|
||||
695
src/fileFormats/abaqus/ABAQUSCore.C
Normal file
695
src/fileFormats/abaqus/ABAQUSCore.C
Normal file
@ -0,0 +1,695 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 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 "ABAQUSCore.H"
|
||||
#include "IFstream.H"
|
||||
#include "ListOps.H"
|
||||
#include "stringOps.H"
|
||||
#include "UIListStream.H"
|
||||
|
||||
#undef Foam_readAbaqusSurface
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
static Foam::Map<Foam::labelList> abaqusToFoamFaceAddr_;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Use peek(), get(), unget() to detect and skip lines that appear to be
|
||||
// "** comment" lines.
|
||||
//
|
||||
// Uses a mix of std::istream and ISstream methods
|
||||
// since we need the low-level get()/unget()
|
||||
|
||||
static void skipComments(ISstream& iss)
|
||||
{
|
||||
#if OPENFOAM < 2002
|
||||
string line;
|
||||
#endif
|
||||
|
||||
auto& is = iss.stdStream();
|
||||
|
||||
bool isComment = true;
|
||||
while (isComment)
|
||||
{
|
||||
isComment = ('*' == is.peek());
|
||||
|
||||
if (isComment)
|
||||
{
|
||||
// Get and check the next one
|
||||
(void) is.get();
|
||||
|
||||
isComment = ('*' == is.peek());
|
||||
if (isComment)
|
||||
{
|
||||
// Found "** ..." (a comment) - read/discard
|
||||
// ISstream::getLine to keep track of the line numbers
|
||||
|
||||
#if OPENFOAM >= 2002
|
||||
iss.getLine(nullptr);
|
||||
#else
|
||||
iss.getLine(line);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a comment
|
||||
// - unget the '*', implicitly break out of loop
|
||||
is.unget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get an identifier of the form "NSET=..." (case-insensitive)
|
||||
// Return the string on success, an empty string on failure
|
||||
|
||||
static string getIdentifier(const word& keyword, string& inputLine)
|
||||
{
|
||||
// Strip out whitespace (not a valid Abaqus identifier anyhow)
|
||||
// - makes parsing easier, avoids tab/carriage-returns etc.
|
||||
|
||||
stringOps::inplaceRemoveSpace(inputLine);
|
||||
|
||||
// Do string comparisons in upper-case
|
||||
|
||||
const auto key(stringOps::upper(keyword));
|
||||
const auto line(stringOps::upper(inputLine));
|
||||
|
||||
// Extract "..,key=value,key2=value,"
|
||||
|
||||
// Not sure if we need the additional ',' prefix
|
||||
// in search to avoid similar keys.
|
||||
|
||||
auto beg = line.find("," + key + "=");
|
||||
|
||||
if (beg != std::string::npos)
|
||||
{
|
||||
// Skip past the '='
|
||||
beg += key.size() + 2;
|
||||
|
||||
// The closing comma
|
||||
auto len = line.find(',', beg);
|
||||
if (len != std::string::npos)
|
||||
{
|
||||
len -= beg;
|
||||
}
|
||||
|
||||
// Substring from inputLine (not uppercase!)
|
||||
return inputLine.substr(beg, len);
|
||||
}
|
||||
|
||||
// Not found
|
||||
return string();
|
||||
}
|
||||
|
||||
|
||||
// Walk the string content (CSV format) to append integer labels
|
||||
// until the line is exhausted or the list is full.
|
||||
//
|
||||
// Return false on read error or if the line exhausted while getting
|
||||
// element.
|
||||
|
||||
static bool appendCsvLabels
|
||||
(
|
||||
const std::string& line,
|
||||
labelUList& elemNodes,
|
||||
label& nodei
|
||||
)
|
||||
{
|
||||
const label nNodes = elemNodes.size();
|
||||
|
||||
std::size_t pos = 0;
|
||||
|
||||
while (nodei < nNodes && pos != std::string::npos)
|
||||
{
|
||||
auto beg = pos;
|
||||
auto len = line.find(',', pos);
|
||||
|
||||
if (len == std::string::npos)
|
||||
{
|
||||
pos = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = len + 1;
|
||||
len -= beg;
|
||||
}
|
||||
|
||||
if (readLabel(line.substr(beg, len), elemNodes[nodei]))
|
||||
{
|
||||
++nodei;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read error, or need another line
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (nodei >= nNodes);
|
||||
}
|
||||
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
const Foam::Map<Foam::labelList>&
|
||||
Foam::fileFormats::ABAQUSCore::abaqusToFoamFaceAddr()
|
||||
{
|
||||
if (abaqusToFoamFaceAddr_.empty())
|
||||
{
|
||||
abaqusToFoamFaceAddr_.emplace(abaqusTet, labelList({3, 2, 0, 1}));
|
||||
abaqusToFoamFaceAddr_.emplace(abaqusPrism, labelList({0, 1, 4, 3, 2}));
|
||||
abaqusToFoamFaceAddr_.emplace(abaqusHex, labelList({4, 5, 2, 1, 3, 0}));
|
||||
}
|
||||
|
||||
return abaqusToFoamFaceAddr_;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileFormats::ABAQUSCore::shapeType
|
||||
Foam::fileFormats::ABAQUSCore::getElementType(const std::string& elemTypeName)
|
||||
{
|
||||
// Check for element-type
|
||||
#undef checkElemType
|
||||
#define checkElemType(test) (elemTypeName.find(test) != std::string::npos)
|
||||
|
||||
if
|
||||
(
|
||||
checkElemType("S3")
|
||||
|| checkElemType("CPE3")
|
||||
|| checkElemType("2D3")
|
||||
)
|
||||
{
|
||||
return shapeType::abaqusTria;
|
||||
}
|
||||
else if
|
||||
(
|
||||
checkElemType("S4")
|
||||
|| checkElemType("CPE4")
|
||||
|| checkElemType("2D4")
|
||||
|| checkElemType("CPEG4")
|
||||
)
|
||||
{
|
||||
return shapeType::abaqusQuad;
|
||||
}
|
||||
else if
|
||||
(
|
||||
checkElemType("3D4") // C3D4*, Q3D4, ...
|
||||
)
|
||||
{
|
||||
return shapeType::abaqusTet;
|
||||
}
|
||||
else if
|
||||
(
|
||||
checkElemType("3D5") // C3D5*
|
||||
)
|
||||
{
|
||||
return shapeType::abaqusPyr;
|
||||
}
|
||||
else if
|
||||
(
|
||||
checkElemType("3D6") // C3D6*
|
||||
)
|
||||
{
|
||||
return shapeType::abaqusPrism;
|
||||
}
|
||||
else if
|
||||
(
|
||||
checkElemType("3D8") // C3D8*
|
||||
)
|
||||
{
|
||||
return shapeType::abaqusHex;
|
||||
}
|
||||
|
||||
#undef checkElemType
|
||||
|
||||
return shapeType::abaqusUnknownShape;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::label
|
||||
Foam::fileFormats::ABAQUSCore::readHelper::addNewElset
|
||||
(
|
||||
const std::string& setName
|
||||
)
|
||||
{
|
||||
if (elsetMap_.empty())
|
||||
{
|
||||
// Always have a lookup for empty string
|
||||
elsetMap_.set(string::null, 0);
|
||||
}
|
||||
|
||||
if (setName.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Direct case-sensitive lookup - it might be there
|
||||
|
||||
label setId = elsetMap_.lookup(setName, -1);
|
||||
if (setId >= 0)
|
||||
{
|
||||
return setId;
|
||||
}
|
||||
|
||||
|
||||
// Case-insensitive search, use upper-case
|
||||
|
||||
const auto needle(stringOps::upper(setName));
|
||||
|
||||
forAllConstIters(elsetMap_, iter)
|
||||
{
|
||||
const auto haystack(stringOps::upper(iter.key()));
|
||||
|
||||
if (needle == haystack)
|
||||
{
|
||||
return iter.val();
|
||||
}
|
||||
}
|
||||
|
||||
// Not there. Save at the next location
|
||||
setId = elsetMap_.size();
|
||||
elsetMap_.set(setName, setId);
|
||||
|
||||
return setId;
|
||||
}
|
||||
|
||||
|
||||
Foam::label
|
||||
Foam::fileFormats::ABAQUSCore::readHelper::readPoints
|
||||
(
|
||||
ISstream& is
|
||||
)
|
||||
{
|
||||
const label initialCount = points_.size();
|
||||
|
||||
char sep; // Comma separator (dummy)
|
||||
label id;
|
||||
point p;
|
||||
|
||||
string line;
|
||||
|
||||
// Read nodes (points) until next "*Section"
|
||||
while (is.peek() != '*' && is.peek() != EOF)
|
||||
{
|
||||
// Grab the line and wrap as string-stream
|
||||
is.getLine(line);
|
||||
UIListStream ss(line.data(), line.length());
|
||||
|
||||
if (line.empty())
|
||||
{
|
||||
// Not sure if we should terminate on blank lines?
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse line for ID, X, Y, Z
|
||||
ss >> id >> sep >> p.x() >> sep >> p.y() >> sep >> p.z();
|
||||
|
||||
nodeIds_.append(id);
|
||||
points_.append(p);
|
||||
}
|
||||
|
||||
return (points_.size() - initialCount);
|
||||
}
|
||||
|
||||
|
||||
Foam::label
|
||||
Foam::fileFormats::ABAQUSCore::readHelper::readElements
|
||||
(
|
||||
ISstream& is,
|
||||
const ABAQUSCore::shapeType shape,
|
||||
const label setId
|
||||
)
|
||||
{
|
||||
// Info<< "*Element" << nl;
|
||||
|
||||
const label nNodes = ABAQUSCore::nPoints(shape);
|
||||
|
||||
if (!nNodes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const label initialCount = elemTypes_.size();
|
||||
|
||||
char sep; // Comma separator (dummy)
|
||||
label id;
|
||||
labelList elemNodes(nNodes, Zero);
|
||||
|
||||
string line;
|
||||
|
||||
// Read element connectivity until next "*Section"
|
||||
|
||||
// Parse for ID, node1, node2, ...
|
||||
while (is.peek() != '*' && is.peek() != EOF)
|
||||
{
|
||||
// elemNodes = Zero; for sanity checks?
|
||||
|
||||
is >> id >> sep;
|
||||
|
||||
label nodei = 0;
|
||||
while (nodei < nNodes)
|
||||
{
|
||||
// Grab the rest of the line, walk through CSV fields
|
||||
is.getLine(line);
|
||||
|
||||
appendCsvLabels(line, elemNodes, nodei);
|
||||
}
|
||||
|
||||
// Checks?
|
||||
|
||||
connectivity_.append(elemNodes);
|
||||
elemTypes_.append(shape);
|
||||
elemIds_.append(id);
|
||||
elsetIds_.append(setId);
|
||||
}
|
||||
|
||||
return (elemTypes_.size() - initialCount);
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileFormats::ABAQUSCore::readHelper::read
|
||||
(
|
||||
ISstream& is
|
||||
)
|
||||
{
|
||||
clear();
|
||||
|
||||
label nread;
|
||||
string line;
|
||||
|
||||
while (is.good())
|
||||
{
|
||||
is.getLine(line);
|
||||
|
||||
// Start processing on "*Section-Name",
|
||||
// but skip "** comments" etc
|
||||
if (line[0] != '*' || !std::isalpha(line[1]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Some abaqus files use upper-case or mixed-case for section names,
|
||||
// convert all to upper-case for ease.
|
||||
|
||||
string upperLine(stringOps::upper(line));
|
||||
|
||||
// "*Nodes" section
|
||||
if (upperLine.starts_with("*NODE"))
|
||||
{
|
||||
// Ignore "NSET=...", we cannot do anything useful with it
|
||||
|
||||
skipComments(is);
|
||||
|
||||
nread = readPoints(is);
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
InfoErr
|
||||
<< "Read " << nread << " *NODE entries" << nl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// "*Element" section
|
||||
if (upperLine.starts_with("*ELEMENT,"))
|
||||
{
|
||||
// Must have "TYPE=..."
|
||||
auto elemTypeName = getIdentifier("TYPE", line);
|
||||
|
||||
// May have "ELSET=..." on the same line
|
||||
string elsetName(getIdentifier("ELSET", line));
|
||||
|
||||
const shapeType shape(getElementType(elemTypeName));
|
||||
|
||||
if (!ABAQUSCore::nPoints(shape))
|
||||
{
|
||||
// Unknown/unsupported
|
||||
if (verbose_)
|
||||
{
|
||||
InfoErr
|
||||
<< "Ignore abaqus element type: "
|
||||
<< elemTypeName << nl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const label elsetId = addNewElset(elsetName);
|
||||
|
||||
skipComments(is);
|
||||
|
||||
nread = readElements(is, shape, elsetId);
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
InfoErr
|
||||
<< "Read " << nread << " *ELEMENT entries ("
|
||||
<< elemTypeName << ") elset="
|
||||
<< elsetName << nl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// "*Surface" section
|
||||
if (upperLine.starts_with("*SURFACE,"))
|
||||
{
|
||||
#ifdef Foam_readAbaqusSurface
|
||||
|
||||
skipComments(is);
|
||||
|
||||
#else
|
||||
Info<< "Reading of abaqus surfaces not implemented" << nl;
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileFormats::ABAQUSCore::readHelper::purge_solids()
|
||||
{
|
||||
// Negative set
|
||||
bitSet select(elemTypes_.size(), false);
|
||||
|
||||
forAll(elemTypes_, i)
|
||||
{
|
||||
if (!isValidType(elemTypes_[i]) || isSolidType(elemTypes_[i]))
|
||||
{
|
||||
select.set(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (select.any())
|
||||
{
|
||||
select.flip();
|
||||
|
||||
inplaceSubset(select, connectivity_);
|
||||
inplaceSubset(select, elemTypes_);
|
||||
|
||||
inplaceSubset(select, elemIds_);
|
||||
inplaceSubset(select, elsetIds_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileFormats::ABAQUSCore::readHelper::compact_nodes()
|
||||
{
|
||||
if (!nodeIds_.empty())
|
||||
{
|
||||
// Has original 1-based ids
|
||||
//
|
||||
// Need to convert to local (0-based) points
|
||||
// in the order in which we read them
|
||||
// and compact unused values
|
||||
|
||||
// Could construct a sort order to preserve the original
|
||||
// point order, but that is not likely relevant for anyone.
|
||||
|
||||
|
||||
// Which original node ids actually being used by elements?
|
||||
|
||||
// We may have many ids, but speculate that they are sparse
|
||||
// and have high element numbers.
|
||||
|
||||
// Use a Map instead of labelList.
|
||||
|
||||
Map<label> nodeIdRemapping(2*points_.size());
|
||||
|
||||
// Pass 1: which nodes are being used?
|
||||
|
||||
for (const labelList& elem : connectivity_)
|
||||
{
|
||||
for (const label origId : elem)
|
||||
{
|
||||
nodeIdRemapping(origId) = 0; // any value
|
||||
}
|
||||
}
|
||||
|
||||
// Define compact local points, finalize the node id remapping
|
||||
|
||||
label nPoints = 0;
|
||||
labelList oldToNewLocal(nodeIds_.size(), -1);
|
||||
|
||||
forAll(nodeIds_, i)
|
||||
{
|
||||
const label origId = nodeIds_[i];
|
||||
|
||||
if (nodeIdRemapping.found(origId))
|
||||
{
|
||||
oldToNewLocal[i] = nPoints;
|
||||
nodeIdRemapping(origId) = nPoints;
|
||||
++nPoints;
|
||||
}
|
||||
}
|
||||
|
||||
// Prune out -1 values (shrinks list)
|
||||
inplaceReorder(oldToNewLocal, points_, true);
|
||||
|
||||
// Relabel the elements
|
||||
|
||||
for (labelList& elem : connectivity_)
|
||||
{
|
||||
for (label& id : elem)
|
||||
{
|
||||
id = nodeIdRemapping[id];
|
||||
}
|
||||
}
|
||||
|
||||
// Done!
|
||||
nodeIds_.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Already numbered (0-based), but perhaps not compacted
|
||||
|
||||
// Which node ids actually being used by elements?
|
||||
bitSet usedNodeIds(points_.size());
|
||||
|
||||
for (const labelList& elem : connectivity_)
|
||||
{
|
||||
usedNodeIds.set(elem);
|
||||
}
|
||||
|
||||
// Compact the numbers
|
||||
labelList oldToNewLocal = invert(points_.size(), usedNodeIds);
|
||||
|
||||
// Prune out -1 values (shrinks list)
|
||||
inplaceReorder(oldToNewLocal, points_, true);
|
||||
|
||||
|
||||
// Renumber non-compact to compact
|
||||
for (labelList& elem : connectivity_)
|
||||
{
|
||||
inplaceRenumber(oldToNewLocal, elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::fileFormats::ABAQUSCore::writePoints
|
||||
(
|
||||
Ostream& os,
|
||||
const UList<point>& points,
|
||||
const scalar scaleFactor
|
||||
)
|
||||
{
|
||||
if (points.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the precision of the points data to 10
|
||||
os.precision(10);
|
||||
|
||||
// Force decimal point for Fortran input
|
||||
os.setf(std::ios::showpoint);
|
||||
|
||||
label vertId = 1; // 1-based vertex labels
|
||||
|
||||
os << "*NODE" << nl;
|
||||
for (const point& p : points)
|
||||
{
|
||||
// Convert [m] -> [mm] etc
|
||||
os << " "
|
||||
<< vertId << ", "
|
||||
<< (scaleFactor * p.x()) << ','
|
||||
<< (scaleFactor * p.y()) << ','
|
||||
<< (scaleFactor * p.z()) << nl;
|
||||
|
||||
++vertId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::fileFormats::ABAQUSCore::faceDecomposition
|
||||
(
|
||||
const UList<point>& points,
|
||||
const UList<face>& faces,
|
||||
labelList& decompOffsets,
|
||||
DynamicList<face>& decompFaces
|
||||
)
|
||||
{
|
||||
// On-demand face decomposition (triangulation)
|
||||
|
||||
decompOffsets.resize(faces.size()+1);
|
||||
decompFaces.clear();
|
||||
|
||||
auto offsetIter = decompOffsets.begin();
|
||||
*offsetIter = 0; // The first offset is always zero
|
||||
|
||||
for (const face& f : faces)
|
||||
{
|
||||
const label n = f.size();
|
||||
|
||||
if (n != 3 && n != 4)
|
||||
{
|
||||
// Decompose non-tri/quad into tris
|
||||
f.triangles(points, decompFaces);
|
||||
}
|
||||
|
||||
// The end offset, which is the next begin offset
|
||||
*(++offsetIter) = decompFaces.size();
|
||||
}
|
||||
|
||||
return decompFaces.size();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
307
src/fileFormats/abaqus/ABAQUSCore.H
Normal file
307
src/fileFormats/abaqus/ABAQUSCore.H
Normal file
@ -0,0 +1,307 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 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::fileFormats::ABAQUSCore
|
||||
|
||||
Description
|
||||
Core routines used when reading/writing ABAQUS files.
|
||||
|
||||
Face mappings for abaqus deduced from libmesh internals
|
||||
|
||||
Tet4 cells
|
||||
\table
|
||||
Face | OpenFOAM | libmesh | abaqus | starcd
|
||||
(1 2 3) | 0 | 2 | 2 | 5
|
||||
(0 3 2) | 1 | 3 | 3 | 4
|
||||
(0 1 3) | 2 | 1 | 1 | 2
|
||||
(0 2 1) | 3 | 0 | 0 | 0
|
||||
\endtable
|
||||
|
||||
Pyr5 cells
|
||||
\table
|
||||
Face | OpenFOAM | libmesh | abaqus | starcd
|
||||
(0 3 2 1) | 0 | 4 | n/a | 0
|
||||
(0 4 3) | 1 | 3 | n/a | 4
|
||||
(3 4 2) | 2 | 2 | n/a | 3
|
||||
(1 2 4) | 3 | 1 | n/a | 5
|
||||
(0 1 4) | 4 | 0 | n/a | 2
|
||||
\endtable
|
||||
|
||||
Prism6 cells
|
||||
\table
|
||||
Face | OpenFOAM | libmesh | abaqus | starcd
|
||||
(0 2 1) | 0 | 0 | 0 | 0
|
||||
(3 4 5) | 1 | 4 | 1 | 1
|
||||
(0 3 5 2) | 2 | 3 | 4 | 4
|
||||
(1 2 5 4) | 3 | 2 | 3 | 5
|
||||
(0 1 4 3) | 4 | 1 | 2 | 2
|
||||
\endtable
|
||||
|
||||
Hex8 cells
|
||||
\table
|
||||
Face | OpenFOAM | libmesh | abaqus | starcd
|
||||
(0 4 7 3) | 0 | 4 | 5 | 4
|
||||
(1 2 6 5) | 1 | 2 | 3 | 5
|
||||
(0 1 5 4) | 2 | 1 | 2 | 2
|
||||
(3 7 6 2) | 3 | 3 | 4 | 3
|
||||
(0 3 2 1) | 4 | 0 | 0 | 0
|
||||
(4 5 6 7) | 5 | 5 | 1 | 1
|
||||
\endtable
|
||||
|
||||
SourceFiles
|
||||
ABAQUSCore.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ABAQUSCore_H
|
||||
#define ABAQUSCore_H
|
||||
|
||||
#include "Fstream.H"
|
||||
#include "Enum.H"
|
||||
#include "Map.H"
|
||||
#include "face.H"
|
||||
#include "point.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace fileFormats
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fileFormats::ABAQUSCore Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class ABAQUSCore
|
||||
{
|
||||
public:
|
||||
|
||||
// Public Data, Declarations
|
||||
|
||||
//- Shape-Type - the values are for internal use only!
|
||||
enum shapeType : uint8_t
|
||||
{
|
||||
abaqusUnknownShape = 0,
|
||||
abaqusTria = 0x03,
|
||||
abaqusQuad = 0x04,
|
||||
abaqusTet = 0x84,
|
||||
abaqusPyr = 0x85,
|
||||
abaqusPrism = 0x86,
|
||||
abaqusHex = 0x88
|
||||
};
|
||||
|
||||
|
||||
// Public Functions
|
||||
|
||||
//- Classify named element type (eg, S4R) to known/supported
|
||||
//- element types.
|
||||
// The input string must be Uppercase!
|
||||
static shapeType getElementType(const std::string& elemTypeName);
|
||||
|
||||
//- The number of points associated with the element type
|
||||
inline static int nPoints(shapeType tag)
|
||||
{
|
||||
return (tag & 0x3F);
|
||||
}
|
||||
|
||||
//- True if element type is not unknown/invalid
|
||||
inline static bool isValidType(shapeType tag)
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
//- True if element type is a 2D shell
|
||||
inline static bool isShellType(shapeType tag)
|
||||
{
|
||||
return (tag & 0x07) && !(tag & 0x80);
|
||||
}
|
||||
|
||||
//- True if element type is a 3D element
|
||||
inline static bool isSolidType(shapeType tag)
|
||||
{
|
||||
return (tag & 0x80);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Face addressing from ABAQUS faces to OpenFOAM faces.
|
||||
// For hex, prism, tet primitive shapes.
|
||||
static const Map<labelList>& abaqusToFoamFaceAddr();
|
||||
|
||||
|
||||
// Protected Classes
|
||||
|
||||
//- Raw reader structure
|
||||
struct readHelper
|
||||
{
|
||||
// General
|
||||
|
||||
//- Additional verbosity
|
||||
bool verbose_;
|
||||
|
||||
|
||||
// Point Handling
|
||||
|
||||
//- Locations of the points (nodes)
|
||||
DynamicList<point> points_;
|
||||
|
||||
//- The 1-based abaqus Id for the point (node)
|
||||
DynamicList<label> nodeIds_;
|
||||
|
||||
|
||||
// Element Handling
|
||||
|
||||
//- The element connectivity.
|
||||
// Initially uses the abaqus node Id (1-based)
|
||||
// but remapped to 0-based compact form later.
|
||||
DynamicList<labelList> connectivity_;
|
||||
|
||||
//- The 1-based abaqus Id for the element
|
||||
DynamicList<label> elemIds_;
|
||||
|
||||
//- The element types
|
||||
DynamicList<ABAQUSCore::shapeType> elemTypes_;
|
||||
|
||||
//- The element set ids
|
||||
DynamicList<label> elsetIds_;
|
||||
|
||||
//- Mapping of elem set names
|
||||
HashTable<label, string> elsetMap_;
|
||||
|
||||
|
||||
// Constructos
|
||||
|
||||
//- Default construct without verbosity
|
||||
explicit readHelper(bool verbosity = false)
|
||||
:
|
||||
verbose_(verbosity)
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Clear out contents.
|
||||
void clear()
|
||||
{
|
||||
points_.clear();
|
||||
nodeIds_.clear();
|
||||
|
||||
connectivity_.clear();
|
||||
elemTypes_.clear();
|
||||
|
||||
elemIds_.clear();
|
||||
elsetIds_.clear();
|
||||
elsetMap_.clear();
|
||||
}
|
||||
|
||||
//- Add a new element set name or return an existing one.
|
||||
// Case-insensitive.
|
||||
label addNewElset(const std::string& setName);
|
||||
|
||||
|
||||
//- Read an abaqus input file
|
||||
void read(ISstream& is);
|
||||
|
||||
//- Read entries within a "*Nodes" section.
|
||||
// Appends to points and nodeIds lists.
|
||||
//
|
||||
// \return the number of points read
|
||||
label readPoints(ISstream& is);
|
||||
|
||||
//- Read entries within an "*Element" section.
|
||||
// If the shape is known/supported, appends to
|
||||
// connectivity, elemType, elemIds lists.
|
||||
//
|
||||
// \return the number of elements read
|
||||
label readElements
|
||||
(
|
||||
ISstream& is,
|
||||
const ABAQUSCore::shapeType shape,
|
||||
const label setId = 0
|
||||
);
|
||||
|
||||
|
||||
//- Remove non-shell elements and compact the points
|
||||
void purge_solids();
|
||||
|
||||
//- Compact unused points and relabel connectivity
|
||||
void compact_nodes();
|
||||
};
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
ABAQUSCore() = default;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Public Member Functions
|
||||
|
||||
//- Write '*NODE' header and entries to file, optionally with scaling
|
||||
// This is a no-op for an empty list
|
||||
static void writePoints
|
||||
(
|
||||
Ostream& os,
|
||||
const UList<point>& points,
|
||||
const scalar scaleFactor = 1.0
|
||||
);
|
||||
|
||||
//- Calculate face decomposition for non tri/quad faces
|
||||
//
|
||||
// \param points the surface points
|
||||
// \param faces the surface faces
|
||||
// \param decompOffsets begin/end offsets (size+1) into decompFaces
|
||||
// \param decompFaces List of non-tri/quad decomposed into triangles
|
||||
//
|
||||
// \return number of decomposed faces
|
||||
static label faceDecomposition
|
||||
(
|
||||
const UList<point>& points,
|
||||
const UList<face>& faces,
|
||||
labelList& decompOffsets,
|
||||
DynamicList<face>& decompFaces
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fileFormats
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -25,6 +25,8 @@ surfZone/surfZoneIOList.C
|
||||
surfaceFormats = surfaceFormats
|
||||
$(surfaceFormats)/surfaceFormatsCore.C
|
||||
|
||||
$(surfaceFormats)/abaqus/ABAQUSsurfaceFormatCore.C
|
||||
$(surfaceFormats)/abaqus/ABAQUSsurfaceFormatRunTime.C
|
||||
$(surfaceFormats)/ac3d/AC3DsurfaceFormatCore.C
|
||||
$(surfaceFormats)/ac3d/AC3DsurfaceFormatRunTime.C
|
||||
$(surfaceFormats)/fire/FLMAsurfaceFormatRunTime.C
|
||||
|
||||
356
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.C
Normal file
356
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.C
Normal file
@ -0,0 +1,356 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 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 "ABAQUSsurfaceFormat.H"
|
||||
#include "IFstream.H"
|
||||
#include "IOmanip.H"
|
||||
#include "faceTraits.H"
|
||||
#include "stringOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face>
|
||||
inline Foam::label Foam::fileFormats::ABAQUSsurfaceFormat<Face>::writeShell
|
||||
(
|
||||
Ostream& os,
|
||||
const Face& f,
|
||||
label elemId,
|
||||
const std::string& elsetName,
|
||||
bool header
|
||||
)
|
||||
{
|
||||
const label n = f.size();
|
||||
|
||||
if (n == 4)
|
||||
{
|
||||
if (header)
|
||||
{
|
||||
os << "*ELEMENT, TYPE=S4";
|
||||
|
||||
if (!elsetName.empty())
|
||||
{
|
||||
os << ", ELSET=" << elsetName;
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
|
||||
os << " "
|
||||
<< (++elemId) << ','
|
||||
<< (f[0] + 1) << ','
|
||||
<< (f[1] + 1) << ','
|
||||
<< (f[2] + 1) << ','
|
||||
<< (f[3] + 1) << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (header)
|
||||
{
|
||||
os << "*ELEMENT, TYPE=S3";
|
||||
|
||||
if (!elsetName.empty())
|
||||
{
|
||||
os << ", ELSET=" << elsetName;
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
|
||||
if (n == 3)
|
||||
{
|
||||
os << " "
|
||||
<< (++elemId) << ','
|
||||
<< (f[0] + 1) << ','
|
||||
<< (f[1] + 1) << ','
|
||||
<< (f[2] + 1) << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// simple triangulation about f[0].
|
||||
// better triangulation should have been done before
|
||||
|
||||
for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
|
||||
{
|
||||
const label fp2 = f.fcIndex(fp1);
|
||||
|
||||
os << " "
|
||||
<< (++elemId) << ','
|
||||
<< (f[0] + 1) << ','
|
||||
<< (f[fp1] + 1) << ','
|
||||
<< (f[fp2] + 1) << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return elemId;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face>
|
||||
Foam::fileFormats::ABAQUSsurfaceFormat<Face>::ABAQUSsurfaceFormat
|
||||
(
|
||||
const fileName& filename
|
||||
)
|
||||
{
|
||||
read(filename);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face>
|
||||
bool Foam::fileFormats::ABAQUSsurfaceFormat<Face>::read
|
||||
(
|
||||
const fileName& filename
|
||||
)
|
||||
{
|
||||
// Clear everything
|
||||
this->clear();
|
||||
|
||||
IFstream is(filename);
|
||||
if (!is.good())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot read file " << filename << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
ABAQUSCore::readHelper reader(true); // Debugging verbosity
|
||||
#else
|
||||
ABAQUSCore::readHelper reader;
|
||||
#endif
|
||||
|
||||
|
||||
reader.read(is);
|
||||
|
||||
// This needs more work
|
||||
|
||||
// No solids
|
||||
reader.purge_solids();
|
||||
reader.compact_nodes();
|
||||
|
||||
|
||||
// Convert connectivity to faces
|
||||
|
||||
DynamicList<Face> dynFaces(reader.connectivity_.size());
|
||||
|
||||
for (labelList& conn : reader.connectivity_)
|
||||
{
|
||||
dynFaces.append(Face(std::move(conn)));
|
||||
}
|
||||
|
||||
|
||||
// Rationalize the zones (elset)
|
||||
|
||||
// Only retain element sets that are actually used
|
||||
labelHashSet elsetUsed(reader.elsetIds_);
|
||||
|
||||
labelList newToOldZone(elsetUsed.sortedToc());
|
||||
|
||||
// Extra safety
|
||||
if (newToOldZone.empty())
|
||||
{
|
||||
newToOldZone.resize(1, Zero);
|
||||
}
|
||||
|
||||
Map<label> oldToNewZone(2*newToOldZone.size());
|
||||
|
||||
forAll(newToOldZone, zonei)
|
||||
{
|
||||
oldToNewZone.set(newToOldZone[zonei], zonei);
|
||||
}
|
||||
|
||||
wordList zoneNames(newToOldZone.size());
|
||||
labelList zoneSizes(newToOldZone.size(), Zero);
|
||||
|
||||
forAllConstIters(reader.elsetMap_, iter)
|
||||
{
|
||||
const label zonei = oldToNewZone.lookup(iter.val(), -1);
|
||||
|
||||
if (zonei >= 0)
|
||||
{
|
||||
zoneNames[zonei] = word::validate(iter.key());
|
||||
}
|
||||
}
|
||||
|
||||
// No empty strings
|
||||
forAll(zoneNames, zonei)
|
||||
{
|
||||
if (zoneNames[zonei].empty())
|
||||
{
|
||||
zoneNames[zonei] = surfZoneIdentifier::defaultName(zonei);
|
||||
}
|
||||
}
|
||||
|
||||
// Steal the elset Ids for our zones
|
||||
DynamicList<label> dynZones(std::move(reader.elsetIds_));
|
||||
|
||||
// Renumber elset -> zoneId and increment the count
|
||||
for (label& zonei : dynZones)
|
||||
{
|
||||
zonei = oldToNewZone.lookup(zonei, 0);
|
||||
|
||||
++zoneSizes[zonei];
|
||||
}
|
||||
|
||||
|
||||
// Transfer to normal lists
|
||||
this->storedPoints().transfer(reader.points_);
|
||||
|
||||
this->sortFacesAndStore
|
||||
(
|
||||
dynFaces,
|
||||
dynZones,
|
||||
reader.elemIds_,
|
||||
true // sorted
|
||||
);
|
||||
|
||||
// Add zones (retaining empty ones)
|
||||
this->addZones(zoneSizes, zoneNames);
|
||||
this->addZonesToFaces(); // for labelledTri
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Face>
|
||||
void Foam::fileFormats::ABAQUSsurfaceFormat<Face>::write
|
||||
(
|
||||
const fileName& filename,
|
||||
const MeshedSurfaceProxy<Face>& surf,
|
||||
IOstreamOption streamOpt,
|
||||
const dictionary&
|
||||
)
|
||||
{
|
||||
// ASCII only, allow output compression
|
||||
streamOpt.format(IOstream::ASCII);
|
||||
|
||||
const UList<point>& pointLst = surf.points();
|
||||
const UList<Face>& faceLst = surf.surfFaces();
|
||||
const UList<label>& faceMap = surf.faceMap();
|
||||
const UList<label>& elemIds = surf.faceIds();
|
||||
|
||||
// for no zones, suppress the group name
|
||||
const surfZoneList zones =
|
||||
(
|
||||
surf.surfZones().empty()
|
||||
? surfaceFormatsCore::oneZone(faceLst, "")
|
||||
: surf.surfZones()
|
||||
);
|
||||
|
||||
const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
|
||||
|
||||
// Possible to use faceIds?
|
||||
bool useOrigFaceIds =
|
||||
(!useFaceMap && elemIds.size() == faceLst.size());
|
||||
|
||||
if (useOrigFaceIds)
|
||||
{
|
||||
// Not possible with on-the-fly face decomposition
|
||||
|
||||
for (const auto& f : faceLst)
|
||||
{
|
||||
if (f.size() > 4)
|
||||
{
|
||||
useOrigFaceIds = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OFstream os(filename, streamOpt);
|
||||
if (!os.good())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot write file " << filename << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
os << "*HEADING" << nl;
|
||||
|
||||
os << nl
|
||||
<< "**" << nl
|
||||
<< "** Points" << nl
|
||||
<< "**" << nl;
|
||||
|
||||
writePoints(os, pointLst);
|
||||
|
||||
os << "**" << nl
|
||||
<< "** Faces" << nl
|
||||
<< "**" << nl
|
||||
<< nl;
|
||||
|
||||
|
||||
// Simple tracking for change of element type/set
|
||||
labelPair prevOutput(-1, -1);
|
||||
|
||||
label faceIndex = 0;
|
||||
label zoneIndex = 0;
|
||||
label elemId = 0;
|
||||
|
||||
for (const surfZone& zone : zones)
|
||||
{
|
||||
for (label nLocal = zone.size(); nLocal--; ++faceIndex)
|
||||
{
|
||||
const label facei =
|
||||
(useFaceMap ? faceMap[faceIndex] : faceIndex);
|
||||
|
||||
const Face& f = faceLst[facei];
|
||||
|
||||
if (useOrigFaceIds)
|
||||
{
|
||||
elemId = elemIds[facei];
|
||||
}
|
||||
|
||||
const label n = f.size();
|
||||
|
||||
bool header =
|
||||
(prevOutput.first() != n || prevOutput.second() != zoneIndex);
|
||||
|
||||
if (header)
|
||||
{
|
||||
// Update values
|
||||
prevOutput.first() = n;
|
||||
prevOutput.second() = zoneIndex;
|
||||
}
|
||||
|
||||
elemId = writeShell(os, f, elemId, zone.name(), header);
|
||||
}
|
||||
|
||||
++zoneIndex;
|
||||
}
|
||||
|
||||
os << "**" << nl
|
||||
<< "**" << nl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
144
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.H
Normal file
144
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.H
Normal file
@ -0,0 +1,144 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 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::fileFormats::ABAQUSsurfaceFormat
|
||||
|
||||
Description
|
||||
Abaqus surface reader.
|
||||
|
||||
Output stream options:
|
||||
- ASCII only
|
||||
- compression on/off
|
||||
|
||||
Output dictionary options: ignored
|
||||
|
||||
SourceFiles
|
||||
ABAQUSsurfaceFormat.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ABAQUSsurfaceFormat_H
|
||||
#define ABAQUSsurfaceFormat_H
|
||||
|
||||
#include "MeshedSurface.H"
|
||||
#include "MeshedSurfaceProxy.H"
|
||||
#include "UnsortedMeshedSurface.H"
|
||||
#include "ABAQUSsurfaceFormatCore.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileFormats
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fileFormats::ABAQUSsurfaceFormat Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Face>
|
||||
class ABAQUSsurfaceFormat
|
||||
:
|
||||
public MeshedSurface<Face>,
|
||||
public ABAQUSsurfaceFormatCore
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Output S3 or S4
|
||||
inline static label writeShell
|
||||
(
|
||||
Ostream& os,
|
||||
const Face& f,
|
||||
label elemId, //!< 0-based element Id
|
||||
const std::string& elsetName,
|
||||
bool header = true
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
ABAQUSsurfaceFormat() = default;
|
||||
|
||||
//- Read construct from file name
|
||||
explicit ABAQUSsurfaceFormat(const fileName& filename);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~ABAQUSsurfaceFormat() = default;
|
||||
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Write surface mesh components by proxy
|
||||
static void write
|
||||
(
|
||||
const fileName& filename,
|
||||
const MeshedSurfaceProxy<Face>& surf,
|
||||
IOstreamOption streamOpt = IOstreamOption(),
|
||||
const dictionary& /*unused*/ = dictionary::null
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Read from file
|
||||
virtual bool read
|
||||
(
|
||||
const fileName& filename
|
||||
);
|
||||
|
||||
//- Write surface mesh to file
|
||||
virtual void write
|
||||
(
|
||||
const fileName& name,
|
||||
IOstreamOption streamOpt = IOstreamOption(),
|
||||
const dictionary& options = dictionary::null
|
||||
) const
|
||||
{
|
||||
write(name, MeshedSurfaceProxy<Face>(*this), streamOpt, options);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fileFormats
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ABAQUSsurfaceFormat.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
33
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormatCore.C
Normal file
33
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormatCore.C
Normal file
@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 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 "ABAQUSsurfaceFormatCore.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
76
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormatCore.H
Normal file
76
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormatCore.H
Normal file
@ -0,0 +1,76 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 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::fileFormats::ABAQUSsurfaceFormatCore
|
||||
|
||||
Description
|
||||
Internal class used by the ABAQUSsurfaceFormat
|
||||
|
||||
SourceFiles
|
||||
ABAQUSsurfaceFormatCore.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ABAQUSsurfaceFormatCore_H
|
||||
#define ABAQUSsurfaceFormatCore_H
|
||||
|
||||
#include "Fstream.H"
|
||||
#include "Ostream.H"
|
||||
#include "MeshedSurface.H"
|
||||
#include "DynamicList.H"
|
||||
#include "ABAQUSCore.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileFormats
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fileFormats::ABAQUSsurfaceFormatCore Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class ABAQUSsurfaceFormatCore
|
||||
:
|
||||
public ABAQUSCore
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Static Member Functions
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fileFormats
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
119
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormatRunTime.C
Normal file
119
src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormatRunTime.C
Normal file
@ -0,0 +1,119 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020 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 "ABAQUSsurfaceFormat.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "addToMemberFunctionSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fileFormats
|
||||
{
|
||||
|
||||
// Read MeshedSurface - tag as abaqus or abq
|
||||
// avoid .inp (name conflict with starcd)
|
||||
addNamedTemplatedToRunTimeSelectionTable
|
||||
(
|
||||
MeshedSurface,
|
||||
ABAQUSsurfaceFormat,
|
||||
face,
|
||||
fileExtension,
|
||||
abaqus
|
||||
);
|
||||
|
||||
addNamedTemplatedToRunTimeSelectionTable
|
||||
(
|
||||
MeshedSurface,
|
||||
ABAQUSsurfaceFormat,
|
||||
face,
|
||||
fileExtension,
|
||||
abq
|
||||
);
|
||||
|
||||
// Write with MeshedSurfaceProxy
|
||||
addNamedTemplatedToMemberFunctionSelectionTable
|
||||
(
|
||||
MeshedSurfaceProxy,
|
||||
ABAQUSsurfaceFormat,
|
||||
face,
|
||||
write,
|
||||
fileExtension,
|
||||
abaqus
|
||||
);
|
||||
addNamedTemplatedToMemberFunctionSelectionTable
|
||||
(
|
||||
MeshedSurfaceProxy,
|
||||
ABAQUSsurfaceFormat,
|
||||
face,
|
||||
write,
|
||||
fileExtension,
|
||||
abq
|
||||
);
|
||||
addNamedTemplatedToMemberFunctionSelectionTable
|
||||
(
|
||||
MeshedSurfaceProxy,
|
||||
ABAQUSsurfaceFormat,
|
||||
triFace,
|
||||
write,
|
||||
fileExtension,
|
||||
abaqus
|
||||
);
|
||||
addNamedTemplatedToMemberFunctionSelectionTable
|
||||
(
|
||||
MeshedSurfaceProxy,
|
||||
ABAQUSsurfaceFormat,
|
||||
triFace,
|
||||
write,
|
||||
fileExtension,
|
||||
abq
|
||||
);
|
||||
addNamedTemplatedToMemberFunctionSelectionTable
|
||||
(
|
||||
MeshedSurfaceProxy,
|
||||
ABAQUSsurfaceFormat,
|
||||
labelledTri,
|
||||
write,
|
||||
fileExtension,
|
||||
abaqus
|
||||
);
|
||||
|
||||
addNamedTemplatedToMemberFunctionSelectionTable
|
||||
(
|
||||
MeshedSurfaceProxy,
|
||||
ABAQUSsurfaceFormat,
|
||||
labelledTri,
|
||||
write,
|
||||
fileExtension,
|
||||
abq
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user