mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: initial support for abaqus surface sampled output (#1600)
- supports geometry and field-specific scaling, separate geometry and fields. Beta-feature for suppressing geometry output entirely.
This commit is contained in:
@ -63,6 +63,7 @@ writers = writers
|
||||
|
||||
$(writers)/surfaceWriter.C
|
||||
$(writers)/caching/surfaceWriterCaching.C
|
||||
$(writers)/abaqus/abaqusSurfaceWriter.C
|
||||
$(writers)/boundaryData/boundaryDataSurfaceWriter.C
|
||||
$(writers)/ensight/ensightSurfaceWriter.C
|
||||
$(writers)/foam/foamSurfaceWriter.C
|
||||
|
||||
355
src/surfMesh/writers/abaqus/abaqusSurfaceWriter.C
Normal file
355
src/surfMesh/writers/abaqus/abaqusSurfaceWriter.C
Normal file
@ -0,0 +1,355 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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 "abaqusSurfaceWriter.H"
|
||||
#include "ABAQUSCore.H"
|
||||
#include "IOmanip.H"
|
||||
#include "ListOps.H"
|
||||
#include "OSspecific.H"
|
||||
#include "surfaceWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace surfaceWriters
|
||||
{
|
||||
defineTypeName(abaqusWriter);
|
||||
addToRunTimeSelectionTable(surfaceWriter, abaqusWriter, word);
|
||||
addToRunTimeSelectionTable(surfaceWriter, abaqusWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing implementation
|
||||
#include "abaqusSurfaceWriterImpl.C"
|
||||
|
||||
// Field writing methods
|
||||
defineSurfaceWriterWriteFields(Foam::surfaceWriters::abaqusWriter);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Write connectivity as CSV list
|
||||
inline static void writeConnectivity
|
||||
(
|
||||
Ostream& os,
|
||||
const label elemId,
|
||||
const labelUList& elem
|
||||
)
|
||||
{
|
||||
os << " " << elemId;
|
||||
|
||||
for (const label vert : elem)
|
||||
{
|
||||
os << ", " << (vert + 1);
|
||||
}
|
||||
|
||||
os << nl;
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::surfaceWriters::abaqusWriter::writeFace
|
||||
(
|
||||
Ostream& os,
|
||||
const labelUList& f,
|
||||
const label elemId,
|
||||
const label propId,
|
||||
bool header
|
||||
) const
|
||||
{
|
||||
// Only called with 3 or 4 points!
|
||||
|
||||
if (header)
|
||||
{
|
||||
os << "*ELEMENT, TYPE=S" << f.size();
|
||||
|
||||
if (propId >= 0)
|
||||
{
|
||||
os << ", ELSET=_" << propId;
|
||||
}
|
||||
|
||||
os << nl;
|
||||
}
|
||||
|
||||
writeConnectivity(os, elemId, f);
|
||||
}
|
||||
|
||||
|
||||
void Foam::surfaceWriters::abaqusWriter::writeGeometry
|
||||
(
|
||||
Ostream& os,
|
||||
const meshedSurf& surf,
|
||||
labelList& decompOffsets,
|
||||
DynamicList<face>& decompFaces
|
||||
) const
|
||||
{
|
||||
const pointField& points = surf.points();
|
||||
const faceList& faces = surf.faces();
|
||||
const labelList& zones = surf.zoneIds();
|
||||
const labelList& elemIds = surf.faceIds();
|
||||
|
||||
// Possible to use faceIds?
|
||||
bool useOrigFaceIds =
|
||||
(
|
||||
elemIds.size() == faces.size()
|
||||
&& !ListOps::found(elemIds, lessOp1<label>(0))
|
||||
);
|
||||
|
||||
if (useOrigFaceIds)
|
||||
{
|
||||
// Not possible with on-the-fly face decomposition
|
||||
for (const auto& f : faces)
|
||||
{
|
||||
if (f.size() > 4)
|
||||
{
|
||||
useOrigFaceIds = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
os << "** Geometry" << nl;
|
||||
|
||||
os << nl
|
||||
<< "**" << nl
|
||||
<< "** Points" << nl
|
||||
<< "**" << nl;
|
||||
|
||||
fileFormats::ABAQUSCore::writePoints(os, points, geometryScale_);
|
||||
|
||||
|
||||
// Write faces, with on-the-fly decomposition (triangulation)
|
||||
decompOffsets.resize(faces.size()+1);
|
||||
decompFaces.clear();
|
||||
|
||||
decompOffsets[0] = 0; // The first offset is always zero
|
||||
|
||||
os << "**" << nl
|
||||
<< "** Faces" << nl
|
||||
<< "**" << nl;
|
||||
|
||||
// Simple tracking for change of element type/set
|
||||
labelPair prevOutput(-1, -1);
|
||||
|
||||
label elemId = 0; // The element-id
|
||||
forAll(faces, facei)
|
||||
{
|
||||
const face& f = faces[facei];
|
||||
|
||||
if (useOrigFaceIds)
|
||||
{
|
||||
// When available and not decomposed
|
||||
elemId = elemIds[facei];
|
||||
}
|
||||
|
||||
// 1-offset for PID
|
||||
const label propId = 1 + (facei < zones.size() ? zones[facei] : 0);
|
||||
|
||||
const label n = f.size();
|
||||
|
||||
bool header =
|
||||
(prevOutput.first() != n || prevOutput.second() != propId);
|
||||
|
||||
if (header)
|
||||
{
|
||||
// Update values
|
||||
prevOutput.first() = n;
|
||||
prevOutput.second() = propId;
|
||||
}
|
||||
|
||||
if (n == 3 || n == 4)
|
||||
{
|
||||
writeFace(os, f, ++elemId, propId, header);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decompose into tris
|
||||
prevOutput.first() = 3;
|
||||
|
||||
f.triangles(points, decompFaces);
|
||||
|
||||
for
|
||||
(
|
||||
label decompi = decompOffsets[facei];
|
||||
decompi < decompFaces.size();
|
||||
++decompi
|
||||
)
|
||||
{
|
||||
writeFace
|
||||
(
|
||||
os,
|
||||
decompFaces[decompi],
|
||||
++elemId,
|
||||
propId,
|
||||
header
|
||||
);
|
||||
|
||||
header = false;
|
||||
}
|
||||
}
|
||||
|
||||
// The end offset, which is the next begin offset
|
||||
decompOffsets[facei+1] = decompFaces.size();
|
||||
}
|
||||
|
||||
os << "**" << nl
|
||||
<< "**" << nl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::surfaceWriters::abaqusWriter::abaqusWriter()
|
||||
:
|
||||
surfaceWriter(),
|
||||
geometryScale_(1),
|
||||
fieldScale_(),
|
||||
noGeometry_(false),
|
||||
outputLayout_(outputLayoutType::BY_FIELD)
|
||||
{}
|
||||
|
||||
|
||||
Foam::surfaceWriters::abaqusWriter::abaqusWriter
|
||||
(
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
surfaceWriter(options),
|
||||
geometryScale_(options.getOrDefault<scalar>("scale", 1)),
|
||||
fieldScale_(options.subOrEmptyDict("fieldScale")),
|
||||
noGeometry_(options.getOrDefault("noGeometry", false)),
|
||||
outputLayout_(outputLayoutType::BY_FIELD)
|
||||
{}
|
||||
|
||||
|
||||
Foam::surfaceWriters::abaqusWriter::abaqusWriter
|
||||
(
|
||||
const meshedSurf& surf,
|
||||
const fileName& outputPath,
|
||||
bool parallel,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
abaqusWriter(options)
|
||||
{
|
||||
open(surf, outputPath, parallel);
|
||||
}
|
||||
|
||||
|
||||
Foam::surfaceWriters::abaqusWriter::abaqusWriter
|
||||
(
|
||||
const pointField& points,
|
||||
const faceList& faces,
|
||||
const fileName& outputPath,
|
||||
bool parallel,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
abaqusWriter(options)
|
||||
{
|
||||
open(points, faces, outputPath, parallel);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::surfaceWriters::abaqusWriter::write()
|
||||
{
|
||||
checkOpen();
|
||||
|
||||
// Geometry:
|
||||
// 1) rootdir/<TIME>/surfaceName.abq
|
||||
// 2) rootdir/geometry/surfaceName_<TIME>.abq
|
||||
|
||||
fileName outputFile;
|
||||
|
||||
switch (outputLayout_)
|
||||
{
|
||||
case outputLayoutType::BY_TIME:
|
||||
{
|
||||
outputFile = outputPath_;
|
||||
if (useTimeDir() && !timeName().empty())
|
||||
{
|
||||
// Splice in time-directory
|
||||
outputFile =
|
||||
outputPath_.path() / timeName() / outputPath_.name();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case outputLayoutType::BY_FIELD:
|
||||
{
|
||||
outputFile = outputPath_ / "geometry" / outputPath_.name();
|
||||
if (!timeName().empty())
|
||||
{
|
||||
// Append time information to file name
|
||||
outputFile += '_' + timeName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
outputFile.ext("abq");
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing abaqus geometry to " << outputFile << endl;
|
||||
}
|
||||
|
||||
|
||||
const meshedSurf& surf = surface();
|
||||
|
||||
if (Pstream::master() || !parallel_)
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile);
|
||||
|
||||
labelList decompOffsets;
|
||||
DynamicList<face> decompFaces;
|
||||
|
||||
writeGeometry(os, surf, decompOffsets, decompFaces);
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
239
src/surfMesh/writers/abaqus/abaqusSurfaceWriter.H
Normal file
239
src/surfMesh/writers/abaqus/abaqusSurfaceWriter.H
Normal file
@ -0,0 +1,239 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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::surfaceWriters::abaqusWriter
|
||||
|
||||
Description
|
||||
A surface writer for the ABAQUS file format - both surface mesh and fields
|
||||
|
||||
The formatOptions for abaqus:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
scale | output geometry scaling | no | 1
|
||||
fieldScale | output field scaling (dictionary) | no | empty
|
||||
noGeometry | Suppress geometry output (beta feature) | no | false
|
||||
\endtable
|
||||
|
||||
For example,
|
||||
\verbatim
|
||||
formatOptions
|
||||
{
|
||||
abaqus
|
||||
{
|
||||
scale 1000; // [m] -> [mm]
|
||||
fieldScale
|
||||
{
|
||||
"p.*" 0.01; // [Pa] -> [mbar]
|
||||
}
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
\heading Output file locations
|
||||
|
||||
The \c rootdir normally corresponds to something like
|
||||
\c postProcessing/\<name\>
|
||||
|
||||
\subheading Geometry
|
||||
\verbatim
|
||||
rootdir
|
||||
`-- surfaceName0
|
||||
`-- geometry
|
||||
`-- surfaceName0_<time>.abq
|
||||
\endverbatim
|
||||
|
||||
\subheading Fields
|
||||
\verbatim
|
||||
rootdir
|
||||
`-- surfaceName0
|
||||
`-- field0
|
||||
| `-- surfaceName0_<time>.{inp}
|
||||
`-- field1
|
||||
`-- surfaceName0_<time>.{inp}
|
||||
\endverbatim
|
||||
|
||||
Note
|
||||
Output variable scaling does not apply to integer types such as Ids.
|
||||
|
||||
SourceFiles
|
||||
abaqusSurfaceWriter.C
|
||||
abaqusSurfaceWriterImpl.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef abaqusSurfaceWriter_H
|
||||
#define abaqusSurfaceWriter_H
|
||||
|
||||
#include "surfaceWriter.H"
|
||||
#include "ABAQUSCore.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace surfaceWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class abaqusWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class abaqusWriter
|
||||
:
|
||||
public surfaceWriter
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Output geometry scaling
|
||||
const scalar geometryScale_;
|
||||
|
||||
//- Output field scaling
|
||||
const dictionary fieldScale_;
|
||||
|
||||
//- BETA feature
|
||||
bool noGeometry_;
|
||||
|
||||
//- Output directory layouts
|
||||
enum class outputLayoutType
|
||||
{
|
||||
BY_TIME = 0,
|
||||
BY_FIELD,
|
||||
};
|
||||
|
||||
//- Output directory layout
|
||||
outputLayoutType outputLayout_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Write face element (tri/quad)
|
||||
void writeFace
|
||||
(
|
||||
Ostream& os,
|
||||
const labelUList& f,
|
||||
const label elemId, //!< 1-based Element Id
|
||||
const label propId, //!< 1-based Property Id
|
||||
const bool header = true
|
||||
) const;
|
||||
|
||||
//- Write the surface mesh geometry, tracking face decomposition
|
||||
//
|
||||
// \param decompOffsets begin/end offsets (size+1) into decompFaces
|
||||
// \param decompFaces Non tri/quad decomposed into triangles
|
||||
void writeGeometry
|
||||
(
|
||||
Ostream& os,
|
||||
const meshedSurf& surf,
|
||||
labelList& decompOffsets,
|
||||
DynamicList<face>& decompFaces
|
||||
) const;
|
||||
|
||||
//- Write a face-based value
|
||||
template<class Type>
|
||||
Ostream& writeFaceValue
|
||||
(
|
||||
Ostream& os,
|
||||
const Type& value,
|
||||
const label elemId //!< 0-based Element Id
|
||||
) const;
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& localValues //!< Local field values to write
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Declare type-name, virtual type (with debug switch)
|
||||
TypeNameNoDebug("abaqus");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
abaqusWriter();
|
||||
|
||||
//- Construct with some output options
|
||||
explicit abaqusWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
abaqusWriter
|
||||
(
|
||||
const meshedSurf& surf,
|
||||
const fileName& outputPath,
|
||||
bool parallel = Pstream::parRun(),
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
abaqusWriter
|
||||
(
|
||||
const pointField& points,
|
||||
const faceList& faces,
|
||||
const fileName& outputPath,
|
||||
bool parallel = Pstream::parRun(),
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~abaqusWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Format uses faceIds as part of its output
|
||||
virtual bool usesFaceIds() const // override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//- Write surface geometry to file.
|
||||
virtual fileName write(); // override
|
||||
|
||||
declareSurfaceWriterWriteMethod(label);
|
||||
declareSurfaceWriterWriteMethod(scalar);
|
||||
declareSurfaceWriterWriteMethod(vector);
|
||||
declareSurfaceWriterWriteMethod(sphericalTensor);
|
||||
declareSurfaceWriterWriteMethod(symmTensor);
|
||||
declareSurfaceWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace surfaceWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
308
src/surfMesh/writers/abaqus/abaqusSurfaceWriterImpl.C
Normal file
308
src/surfMesh/writers/abaqus/abaqusSurfaceWriterImpl.C
Normal file
@ -0,0 +1,308 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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 "OFstream.H"
|
||||
#include "IOmanip.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::Ostream& Foam::surfaceWriters::abaqusWriter::writeFaceValue
|
||||
(
|
||||
Ostream& os,
|
||||
const Type& value,
|
||||
const label elemId
|
||||
) const
|
||||
{
|
||||
if (fileFormats::ABAQUSCore::isEncodedSolidId(elemId))
|
||||
{
|
||||
const label solidId =
|
||||
fileFormats::ABAQUSCore::decodeSolidElementId(elemId);
|
||||
|
||||
const label sideNum =
|
||||
fileFormats::ABAQUSCore::decodeSolidSideNum(elemId);
|
||||
|
||||
// Element-id: 0-based to 1-based
|
||||
// Side-id: always 1-based
|
||||
os << (solidId + 1) << ", P" << sideNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Element-id: 0-based to 1-based
|
||||
os << (elemId + 1) << ", P";
|
||||
}
|
||||
|
||||
os << ", ";
|
||||
if (pTraits<Type>::nComponents == 1)
|
||||
{
|
||||
os << value;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << mag(value);
|
||||
}
|
||||
os << nl;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::surfaceWriters::abaqusWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& localValues
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
|
||||
// Field:
|
||||
// 1) rootdir/<TIME>/<field>_surfaceName.inp
|
||||
// 2) rootdir/<field>/surfaceName_<TIME>.inp
|
||||
|
||||
fileName outputFile;
|
||||
|
||||
switch (outputLayout_)
|
||||
{
|
||||
case outputLayoutType::BY_TIME:
|
||||
{
|
||||
outputFile = outputPath_;
|
||||
if (useTimeDir() && !timeName().empty())
|
||||
{
|
||||
// Splice in time-directory
|
||||
outputFile =
|
||||
outputPath_.path() / timeName() / outputPath_.name();
|
||||
}
|
||||
|
||||
// Append <field>_surfaceName
|
||||
outputFile /= fieldName + '_' + outputPath_.name();
|
||||
break;
|
||||
}
|
||||
case outputLayoutType::BY_FIELD:
|
||||
{
|
||||
outputFile = outputPath_ / fieldName / outputPath_.name();
|
||||
if (!timeName().empty())
|
||||
{
|
||||
// Append time information to file name
|
||||
outputFile += '_' + timeName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
outputFile.ext("inp");
|
||||
|
||||
|
||||
// Output scaling for the variable, but not for integer types.
|
||||
// could also solve with clever templating
|
||||
|
||||
const scalar varScale =
|
||||
(
|
||||
std::is_integral<Type>::value
|
||||
? scalar(1)
|
||||
: fieldScale_.getOrDefault<scalar>(fieldName, 1)
|
||||
);
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing field " << fieldName;
|
||||
if (!equal(varScale, 1))
|
||||
{
|
||||
Info<< " (scaling " << varScale << ')';
|
||||
}
|
||||
Info<< " to " << outputFile << endl;
|
||||
}
|
||||
|
||||
|
||||
// Implicit geometry merge()
|
||||
tmp<Field<Type>> tfield = mergeField(localValues) * varScale;
|
||||
|
||||
const meshedSurf& surf = surface();
|
||||
|
||||
if (Pstream::master() || !parallel_)
|
||||
{
|
||||
const auto& values = tfield();
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
// const scalar timeValue(0);
|
||||
|
||||
|
||||
// Additional bookkeeping for decomposing non tri/quad
|
||||
labelList decompOffsets;
|
||||
DynamicList<face> decompFaces;
|
||||
|
||||
|
||||
OFstream os(outputFile);
|
||||
|
||||
if (noGeometry_ || wroteGeom_)
|
||||
{
|
||||
// Geometry already written (or suppressed)
|
||||
// - still need decomposition information
|
||||
|
||||
fileFormats::ABAQUSCore::faceDecomposition
|
||||
(
|
||||
surf.points(),
|
||||
surf.faces(),
|
||||
decompOffsets,
|
||||
decompFaces
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write geometry (separate file)
|
||||
|
||||
OFstream osGeom(outputFile.lessExt().ext("abq"));
|
||||
writeGeometry(osGeom, surf, decompOffsets, decompFaces);
|
||||
}
|
||||
|
||||
// Write field
|
||||
// *DLOAD
|
||||
// Element-based: // elemId, P, 1000
|
||||
// Surface-based: // elemId, P4, 1000
|
||||
|
||||
os << "**" << nl
|
||||
<< "** field = " << fieldName << nl
|
||||
<< "** type = " << pTraits<Type>::typeName << nl;
|
||||
|
||||
if (useTimeDir() && !timeName().empty())
|
||||
{
|
||||
os << "** time = " << timeName() << nl;
|
||||
}
|
||||
|
||||
os << "**" << nl
|
||||
<< "*DLOAD" << nl;
|
||||
|
||||
|
||||
// Regular (undecomposed) faces
|
||||
const faceList& faces = surf.faces();
|
||||
const labelList& elemIds = surf.faceIds();
|
||||
|
||||
// Possible to use faceIds?
|
||||
const bool useOrigFaceIds =
|
||||
(
|
||||
elemIds.size() == faces.size()
|
||||
&& decompFaces.empty()
|
||||
);
|
||||
|
||||
|
||||
label elemId = 0;
|
||||
|
||||
if (this->isPointData())
|
||||
{
|
||||
forAll(faces, facei)
|
||||
{
|
||||
if (useOrigFaceIds)
|
||||
{
|
||||
// When available and not decomposed
|
||||
elemId = elemIds[facei];
|
||||
}
|
||||
|
||||
const label beginElemId = elemId;
|
||||
|
||||
// Any face decomposition
|
||||
for
|
||||
(
|
||||
label decompi = decompOffsets[facei];
|
||||
decompi < decompOffsets[facei+1];
|
||||
++decompi
|
||||
)
|
||||
{
|
||||
const face& f = decompFaces[decompi];
|
||||
|
||||
Type v = Zero;
|
||||
for (const label verti : f)
|
||||
{
|
||||
v += values[verti];
|
||||
}
|
||||
v /= f.size();
|
||||
|
||||
writeFaceValue(os, v, elemId); // 0-based
|
||||
++elemId;
|
||||
}
|
||||
|
||||
|
||||
// Face not decomposed
|
||||
if (beginElemId == elemId)
|
||||
{
|
||||
const face& f = faces[facei];
|
||||
|
||||
Type v = Zero;
|
||||
for (const label verti : f)
|
||||
{
|
||||
v += values[verti];
|
||||
}
|
||||
v /= f.size();
|
||||
|
||||
writeFaceValue(os, v, elemId); // 0-based
|
||||
++elemId;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto valIter = values.cbegin();
|
||||
|
||||
forAll(faces, facei)
|
||||
{
|
||||
if (useOrigFaceIds)
|
||||
{
|
||||
// When available and not decomposed
|
||||
elemId = elemIds[facei];
|
||||
}
|
||||
|
||||
const Type v(*valIter);
|
||||
++valIter;
|
||||
|
||||
label nValues =
|
||||
max
|
||||
(
|
||||
label(1),
|
||||
(decompOffsets[facei+1] - decompOffsets[facei])
|
||||
);
|
||||
|
||||
while (nValues--)
|
||||
{
|
||||
writeFaceValue(os, v, elemId); // 0-based
|
||||
++elemId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os << "**" << nl
|
||||
<< "**" << nl;
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user