ENH: make Nastran PLOAD2,PLOAD4 field mappings optional
- PLOAD2 is a reasonable default and PLOAD4 output (currently misused for vectors/tensors) is the exception. - simplify the specification by using optional PLOAD4, PLOAD2 wordRes lists to act as allow/deny selectors. In the regular case won't need to specify anything or perhaps only the PLOAD4 list. ENH: atomic creation of Nastran files FIX: inconsistent Nastran surface output format - use FREE format by default. Previously had an odd mix of SHORT format when created without options and LONG format (as default) when created with format options.
This commit is contained in:
parent
d8d3e34d5c
commit
dce009cef1
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -250,12 +250,12 @@ Foam::fileName Foam::coordSetWriters::nastranWriter::writeTemplate
|
||||
Info<< "Writing nastran geometry to " << outputFile << endl;
|
||||
}
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
if (!Foam::isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
Foam::mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile);
|
||||
OFstream os(IOstreamOption::ATOMIC, outputFile);
|
||||
fileFormats::NASCore::setPrecision(os, writeFormat_);
|
||||
|
||||
os << "TITLE=OpenFOAM " << outputFile.stem()
|
||||
@ -293,12 +293,12 @@ Foam::fileName Foam::coordSetWriters::nastranWriter::writeTemplate
|
||||
Info<< "Writing nastran geometry to " << outputFile << endl;
|
||||
}
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
if (!Foam::isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
Foam::mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile);
|
||||
OFstream os(IOstreamOption::ATOMIC, outputFile);
|
||||
fileFormats::NASCore::setPrecision(os, writeFormat_);
|
||||
|
||||
os << "TITLE=OpenFOAM " << outputFile.stem()
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -307,16 +307,10 @@ void Foam::surfaceWriters::nastranWriter::writeGeometry
|
||||
Foam::surfaceWriters::nastranWriter::nastranWriter()
|
||||
:
|
||||
surfaceWriter(),
|
||||
writeFormat_(fieldFormat::SHORT),
|
||||
fieldMap_(),
|
||||
writeFormat_(fieldFormat::FREE),
|
||||
commonGeometry_(false),
|
||||
separator_()
|
||||
{
|
||||
// if (writeFormat_ == fieldFormat::FREE)
|
||||
// {
|
||||
// separator_ = ",";
|
||||
// }
|
||||
}
|
||||
separator_(",") // FREE format
|
||||
{}
|
||||
|
||||
|
||||
Foam::surfaceWriters::nastranWriter::nastranWriter
|
||||
@ -331,29 +325,40 @@ Foam::surfaceWriters::nastranWriter::nastranWriter
|
||||
(
|
||||
"format",
|
||||
options,
|
||||
fieldFormat::LONG
|
||||
fieldFormat::FREE
|
||||
)
|
||||
),
|
||||
fieldMap_(),
|
||||
commonGeometry_(options.getOrDefault("commonGeometry", false)),
|
||||
separator_()
|
||||
commonGeometry_(options.getOrDefault("commonGeometry", false))
|
||||
{
|
||||
if (writeFormat_ == fieldFormat::FREE)
|
||||
{
|
||||
separator_ = ",";
|
||||
}
|
||||
|
||||
// Explicit PLOAD2, PLOAD4 field specification
|
||||
options.readIfPresent("PLOAD2", pload2_);
|
||||
options.readIfPresent("PLOAD4", pload4_);
|
||||
|
||||
// Compatibility:
|
||||
// Optional pairs of (field name => load format)
|
||||
// Could make conditional on (pload2_.empty() && pload4_.empty())
|
||||
|
||||
List<Pair<word>> fieldPairs;
|
||||
options.readEntry("fields", fieldPairs);
|
||||
options.readIfPresent("fields", fieldPairs);
|
||||
|
||||
for (const Pair<word>& item : fieldPairs)
|
||||
{
|
||||
// (field name => load format)
|
||||
fieldMap_.insert
|
||||
(
|
||||
item.first(),
|
||||
fileFormats::NASCore::loadFormatNames[item.second()]
|
||||
);
|
||||
const loadFormat format =
|
||||
fileFormats::NASCore::loadFormatNames[item.second()];
|
||||
|
||||
if (format == loadFormat::PLOAD2)
|
||||
{
|
||||
pload2_.push_back(item.first());
|
||||
}
|
||||
else if (format == loadFormat::PLOAD4)
|
||||
{
|
||||
pload4_.push_back(item.first());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,12 +419,12 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::write()
|
||||
|
||||
if (UPstream::master() || !parallel_)
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
if (!Foam::isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
Foam::mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile);
|
||||
OFstream os(IOstreamOption::ATOMIC, outputFile);
|
||||
fileFormats::NASCore::setPrecision(os, writeFormat_);
|
||||
|
||||
os << "TITLE=OpenFOAM " << outputPath_.name() << " geometry" << nl
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -33,13 +33,15 @@ Description
|
||||
The formatOptions for nastran:
|
||||
\table
|
||||
Property | Description | Reqd | Default
|
||||
fields | Field pairs for PLOAD2/PLOAD4 | yes |
|
||||
format | Nastran format (short/long/free) | no | long
|
||||
format | Nastran format (short/long/free) | no | free
|
||||
scale | Output geometry scaling | no | 1
|
||||
transform | Output coordinate transform | no |
|
||||
fieldLevel | Subtract field level before scaling | no | empty dict
|
||||
fieldScale | Output field scaling | no | empty dict
|
||||
commonGeometry | use separate geometry files | no | false
|
||||
PLOAD2 | Field selection (words/regex) for PLOAD2 | no |
|
||||
PLOAD4 | Field selection (words/regex) for PLOAD4 | no |
|
||||
fields | Compat: Field pairs for PLOAD2/PLOAD4 | no |
|
||||
\endtable
|
||||
|
||||
For example,
|
||||
@ -48,13 +50,6 @@ Description
|
||||
{
|
||||
nastran
|
||||
{
|
||||
// OpenFOAM field name to NASTRAN load types
|
||||
fields
|
||||
(
|
||||
(pMean PLOAD2)
|
||||
(p PLOAD4)
|
||||
);
|
||||
|
||||
format free; // format type
|
||||
|
||||
scale 1000; // [m] -> [mm]
|
||||
@ -62,10 +57,27 @@ Description
|
||||
{
|
||||
"p.*" 0.01; // [Pa] -> [mbar]
|
||||
}
|
||||
|
||||
// Specific NASTRAN load types
|
||||
PLOAD2 ( pMean );
|
||||
PLOAD4 ( "p.*" );
|
||||
|
||||
// old style specification
|
||||
fields
|
||||
(
|
||||
(pMean PLOAD2)
|
||||
(p PLOAD4)
|
||||
);
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Unless otherwise specified, all fields will be treated as PLOAD2
|
||||
output. Can optionally specify PLOAD4 output using a combination
|
||||
of \c PLOAD4 (accept) and \c PLOAD2 (deny) entries. The older \c fields
|
||||
specification is also accepted and will be transcribed to
|
||||
corresponding PLOAD4, PLOAD2 entries.
|
||||
|
||||
\section Output file locations
|
||||
|
||||
The \c rootdir normally corresponds to something like
|
||||
@ -93,7 +105,6 @@ Description
|
||||
|
||||
Note
|
||||
Output variable scaling does not apply to integer types such as Ids.
|
||||
Field pairs default to PLOAD2 for scalars and PLOAD4 for vectors etc.
|
||||
|
||||
SourceFiles
|
||||
nastranSurfaceWriter.C
|
||||
@ -106,7 +117,7 @@ SourceFiles
|
||||
|
||||
#include "surfaceWriter.H"
|
||||
#include "NASCore.H"
|
||||
#include "HashTable.H"
|
||||
#include "wordRes.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -139,15 +150,18 @@ private:
|
||||
//- Field format (width and separator)
|
||||
fieldFormat writeFormat_;
|
||||
|
||||
//- Mapping from field name to data format enumeration
|
||||
HashTable<loadFormat> fieldMap_;
|
||||
|
||||
//- Use common geometry file
|
||||
bool commonGeometry_;
|
||||
|
||||
//- Separator (used for free format)
|
||||
word separator_;
|
||||
|
||||
//- Explicit selection for PLOAD2 output (deselects for PLOAD4)
|
||||
wordRes pload2_;
|
||||
|
||||
//- Explicit selection for PLOAD4 output
|
||||
wordRes pload4_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
@ -221,10 +235,10 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct. Default SHORT format
|
||||
//- Default construct. Default FREE format
|
||||
nastranWriter();
|
||||
|
||||
//- Construct with some output options. Default LONG format
|
||||
//- Construct with some output options. Default FREE format
|
||||
explicit nastranWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
|
@ -103,13 +103,13 @@ Foam::Ostream& Foam::surfaceWriters::nastranWriter::writeFaceValue
|
||||
{
|
||||
case loadFormat::PLOAD2 :
|
||||
{
|
||||
if (pTraits<Type>::nComponents == 1)
|
||||
if (pTraits<Type>::nComponents > 1)
|
||||
{
|
||||
writeValue(os, value);
|
||||
writeValue(os, Foam::mag(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
writeValue(os, mag(value));
|
||||
writeValue(os, value);
|
||||
}
|
||||
|
||||
os << separator_;
|
||||
@ -121,6 +121,9 @@ Foam::Ostream& Foam::surfaceWriters::nastranWriter::writeFaceValue
|
||||
{
|
||||
writeValue(os, elemId);
|
||||
|
||||
// NOTE: these should actually be vertex values,
|
||||
// but misused here to provide vector quantities!
|
||||
|
||||
for (direction d = 0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
os << separator_;
|
||||
@ -156,43 +159,23 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate
|
||||
|
||||
checkOpen();
|
||||
|
||||
const loadFormat format
|
||||
(
|
||||
fieldMap_.lookup
|
||||
(
|
||||
fieldName,
|
||||
// Default format
|
||||
(
|
||||
pTraits<Type>::nComponents == 1
|
||||
? loadFormat::PLOAD2
|
||||
: loadFormat::PLOAD4
|
||||
)
|
||||
)
|
||||
);
|
||||
// Default is PLOAD2
|
||||
loadFormat format = loadFormat::PLOAD2;
|
||||
|
||||
if
|
||||
(
|
||||
!std::is_integral<Type>::value // Handle 'Ids' etc silently
|
||||
&& !fieldMap_.empty()
|
||||
&& !fieldMap_.found(fieldName)
|
||||
&& !pload4_.empty()
|
||||
)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "No mapping found between field " << fieldName
|
||||
<< " and corresponding Nastran field. Available types:"
|
||||
<< fieldMap_ << nl;
|
||||
}
|
||||
const wordRes::filter matcher(pload4_, pload2_);
|
||||
|
||||
// Emit any common warnings
|
||||
if (format == loadFormat::PLOAD2 && pTraits<Type>::nComponents != 1)
|
||||
{
|
||||
WarningInFunction
|
||||
<< fileFormats::NASCore::loadFormatNames[format]
|
||||
<< " cannot be used for higher rank values"
|
||||
<< " - reverting to mag()" << endl;
|
||||
if (matcher(fieldName))
|
||||
{
|
||||
format = loadFormat::PLOAD4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Common geometry
|
||||
// Field: rootdir/<TIME>/<field>_surfaceName.bdf
|
||||
|
||||
@ -239,9 +222,9 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate
|
||||
{
|
||||
const auto& values = tfield();
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
if (!Foam::isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
Foam::mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
const scalar timeValue(0);
|
||||
@ -251,7 +234,7 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate
|
||||
DynamicList<face> decompFaces;
|
||||
|
||||
|
||||
OFstream os(outputFile);
|
||||
OFstream os(IOstreamOption::ATOMIC, outputFile);
|
||||
fileFormats::NASCore::setPrecision(os, writeFormat_);
|
||||
|
||||
os << "TITLE=OpenFOAM " << outputFile.name()
|
||||
|
Loading…
Reference in New Issue
Block a user