BUG: Nastran reading of free format truncates last field (fixes #3189)
- the old logic relied on the presence/absence of a comma to decide whether to parse as fixed or free format. This logic is faulty when handling the final (trailing) entry and will generally lead to the last field being truncated when read in. Now the caller decides on fixed vs free. 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
905d63357c
commit
956fb4ca3a
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -122,7 +122,8 @@ std::string Foam::fileFormats::NASCore::nextNasField
|
||||
(
|
||||
const std::string& str,
|
||||
std::string::size_type& pos,
|
||||
std::string::size_type len
|
||||
const std::string::size_type width,
|
||||
const bool free_format
|
||||
)
|
||||
{
|
||||
const auto beg = pos;
|
||||
@ -130,15 +131,23 @@ std::string Foam::fileFormats::NASCore::nextNasField
|
||||
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
pos = beg + len; // Continue after field width
|
||||
if (free_format)
|
||||
{
|
||||
// Nothing left
|
||||
pos = str.size();
|
||||
return str.substr(beg);
|
||||
}
|
||||
|
||||
// Fixed format - continue after field width
|
||||
pos = beg + width;
|
||||
return str.substr(beg, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (end - beg); // Efffective width
|
||||
pos = end + 1; // Continue after comma
|
||||
// Free format - continue after comma
|
||||
pos = end + 1;
|
||||
return str.substr(beg, (end - beg));
|
||||
}
|
||||
|
||||
return str.substr(beg, len);
|
||||
}
|
||||
|
||||
|
||||
@ -235,8 +244,8 @@ void Foam::fileFormats::NASCore::writeCoord
|
||||
// 2 ID : point ID - requires starting index of 1
|
||||
// 3 CP : coordinate system ID (blank)
|
||||
// 4 X1 : point x coordinate
|
||||
// 5 X2 : point x coordinate
|
||||
// 6 X3 : point x coordinate
|
||||
// 5 X2 : point y coordinate
|
||||
// 6 X3 : point z coordinate
|
||||
// 7 CD : coordinate system for displacements (blank)
|
||||
// 8 PS : single point constraints (blank)
|
||||
// 9 SEID : super-element ID
|
||||
|
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -48,7 +48,6 @@ SourceFiles
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace fileFormats
|
||||
{
|
||||
|
||||
@ -74,18 +73,18 @@ public:
|
||||
//- Output load format
|
||||
enum loadFormat
|
||||
{
|
||||
PLOAD2,
|
||||
PLOAD4
|
||||
PLOAD2, //!< Face load (eg, pressure)
|
||||
PLOAD4 //!< Vertex load
|
||||
};
|
||||
|
||||
//- Selection names for the NASTRAN file field formats
|
||||
//- Selection names for the NASTRAN load formats
|
||||
static const Enum<loadFormat> loadFormatNames;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
NASCore() = default;
|
||||
NASCore() noexcept = default;
|
||||
|
||||
|
||||
// Public Static Member Functions
|
||||
@ -93,18 +92,20 @@ public:
|
||||
//- Extract numbers from things like "-2.358-8" (same as "-2.358e-8")
|
||||
static scalar readNasScalar(const std::string& str);
|
||||
|
||||
//- A string::substr() to handle fixed-format and free-format NASTRAN.
|
||||
// Returns the substr to the next comma (if found) or the given length
|
||||
//
|
||||
// \param str The string to extract from
|
||||
// \param pos On input, the position of the first character of the
|
||||
// substring. On output, advances to the next position to use.
|
||||
// \param len The fixed-format length to use if a comma is not found.
|
||||
//- A std::string::substr() variant to handle fixed-format and
|
||||
//- free-format NASTRAN.
|
||||
// Returns the substr until the next comma (if found)
|
||||
// or the given fixed width
|
||||
static std::string nextNasField
|
||||
(
|
||||
//! The string to extract from
|
||||
const std::string& str,
|
||||
//! [in,out] The parse position within \p str
|
||||
std::string::size_type& pos,
|
||||
std::string::size_type len
|
||||
//! The fixed-format width to use (if comma is not found)
|
||||
const std::string::size_type width,
|
||||
//! The input is known to be free-format
|
||||
const bool free_format = false
|
||||
);
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2017 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -62,13 +62,17 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
|
||||
while (is.good())
|
||||
{
|
||||
string::size_type linei = 0; // parsing position within current line
|
||||
string line;
|
||||
is.getLine(line);
|
||||
|
||||
if (line.empty() || line[0] == '$')
|
||||
if (line.empty())
|
||||
{
|
||||
continue; // Skip empty or comment
|
||||
continue; // Ignore empty
|
||||
}
|
||||
else if (line[0] == '$')
|
||||
{
|
||||
// Ignore comment
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if character 72 is continuation
|
||||
@ -94,38 +98,66 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
}
|
||||
|
||||
|
||||
// Parsing position within current line
|
||||
std::string::size_type linei = 0;
|
||||
|
||||
// Is free format if line contains a comma
|
||||
const bool freeFormat = line.contains(',');
|
||||
|
||||
// First word (column 0-8)
|
||||
const word cmd(word::validate(nextNasField(line, linei, 8)));
|
||||
|
||||
if (cmd == "CBEAM" || cmd == "CROD")
|
||||
{
|
||||
// discard elementId (8-16)
|
||||
(void) nextNasField(line, linei, 8); // 8-16
|
||||
// discard groupId (16-24)
|
||||
(void) nextNasField(line, linei, 8); // 16-24
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : group id
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
|
||||
label a = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
label b = readLabel(nextNasField(line, linei, 8)); // 32-40
|
||||
// discard elementId
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
// discard groupId
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
|
||||
label a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
dynEdges.append(edge(a,b));
|
||||
}
|
||||
else if (cmd == "PLOTEL")
|
||||
{
|
||||
// discard elementId (8-16)
|
||||
(void) nextNasField(line, linei, 8); // 8-16
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : vertex
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
|
||||
label a = readLabel(nextNasField(line, linei, 8)); // 16-24
|
||||
label b = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
// discard elementId (8-16)
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
|
||||
label a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
dynEdges.append(edge(a,b));
|
||||
}
|
||||
else if (cmd == "GRID")
|
||||
{
|
||||
label index = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
(void) nextNasField(line, linei, 8); // 16-24
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8)); // 24-32
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8)); // 32-40
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8)); // 40-48
|
||||
// Fixed (short) format:
|
||||
// 8-16 : point id
|
||||
// 16-24 : coordinate system (unsupported)
|
||||
// 24-32 : point x coordinate
|
||||
// 32-40 : point y coordinate
|
||||
// 40-48 : point z coordinate
|
||||
// 48-56 : displacement coordinate system (optional, unsupported)
|
||||
// 56-64 : single point constraints (optional, unsupported)
|
||||
// 64-70 : super-element id (optional, unsupported)
|
||||
|
||||
label index = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
pointId.append(index);
|
||||
dynPoints.append(point(x, y, z));
|
||||
@ -138,6 +170,8 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
// GRID* 126 0 -5.55999875E+02 -5.68730474E+02
|
||||
// * 2.14897901E+02
|
||||
|
||||
// Cannot be long format and free format at the same time!
|
||||
|
||||
label index = readLabel(nextNasField(line, linei, 16)); // 8-24
|
||||
(void) nextNasField(line, linei, 16); // 24-40
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -149,7 +149,6 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
string line;
|
||||
while (is.good())
|
||||
{
|
||||
string::size_type linei = 0; // Parsing position within current line
|
||||
is.getLine(line);
|
||||
|
||||
// ANSA extension
|
||||
@ -223,16 +222,30 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parsing position within current line
|
||||
std::string::size_type linei = 0;
|
||||
|
||||
// Is free format if line contains a comma
|
||||
const bool freeFormat = line.contains(',');
|
||||
|
||||
// First word (column 0-8)
|
||||
const word cmd(word::validate(nextNasField(line, linei, 8)));
|
||||
|
||||
if (cmd == "CTRIA3")
|
||||
{
|
||||
label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
|
||||
const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40
|
||||
const auto c = readLabel(nextNasField(line, linei, 8)); // 40-48
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : group id
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
// 40-48 : vertex
|
||||
|
||||
label elemId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label groupId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto c = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
// Convert groupId into zoneId
|
||||
const auto iterZone = zoneLookup.cfind(groupId);
|
||||
@ -261,12 +274,20 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
}
|
||||
else if (cmd == "CQUAD4")
|
||||
{
|
||||
label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
|
||||
const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32
|
||||
const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40
|
||||
const auto c = readLabel(nextNasField(line, linei, 8)); // 40-48
|
||||
const auto d = readLabel(nextNasField(line, linei, 8)); // 48-56
|
||||
// Fixed format:
|
||||
// 8-16 : element id
|
||||
// 16-24 : group id
|
||||
// 24-32 : vertex
|
||||
// 32-40 : vertex
|
||||
// 40-48 : vertex
|
||||
// 48-56 : vertex
|
||||
|
||||
label elemId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
label groupId = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto a = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto b = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto c = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
const auto d = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
// Convert groupId into zoneId
|
||||
const auto iterZone = zoneLookup.cfind(groupId);
|
||||
@ -310,11 +331,21 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
}
|
||||
else if (cmd == "GRID")
|
||||
{
|
||||
label index = readLabel(nextNasField(line, linei, 8)); // 8-16
|
||||
(void) nextNasField(line, linei, 8); // 16-24
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8)); // 24-32
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8)); // 32-40
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8)); // 40-48
|
||||
// Fixed (short) format:
|
||||
// 8-16 : point id
|
||||
// 16-24 : coordinate system (not supported)
|
||||
// 24-32 : point x coordinate
|
||||
// 32-40 : point y coordinate
|
||||
// 40-48 : point z coordinate
|
||||
// 48-56 : displacement coordinate system (optional, unsupported)
|
||||
// 56-64 : single point constraints (optional, unsupported)
|
||||
// 64-70 : super-element id (optional, unsupported)
|
||||
|
||||
label index = readLabel(nextNasField(line, linei, 8, freeFormat));
|
||||
(void) nextNasField(line, linei, 8, freeFormat);
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar y = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
scalar z = readNasScalar(nextNasField(line, linei, 8, freeFormat));
|
||||
|
||||
pointId.append(index);
|
||||
dynPoints.append(point(x, y, z));
|
||||
@ -327,6 +358,8 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
// GRID* 126 0 -5.55999875E+02 -5.68730474E+02
|
||||
// * 2.14897901E+02
|
||||
|
||||
// Cannot be long format and free format at the same time!
|
||||
|
||||
label index = readLabel(nextNasField(line, linei, 16)); // 8-24
|
||||
(void) nextNasField(line, linei, 16); // 24-40
|
||||
scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -307,16 +307,10 @@ void Foam::surfaceWriters::nastranWriter::writeGeometry
|
||||
Foam::surfaceWriters::nastranWriter::nastranWriter()
|
||||
:
|
||||
surfaceWriter(),
|
||||
writeFormat_(fieldFormat::SHORT),
|
||||
fieldMap_(),
|
||||
writeFormat_(fieldFormat::FREE),
|
||||
commonGeometry_(false),
|
||||
separator_()
|
||||
{
|
||||
// if (writeFormat_ == fieldFormat::FREE)
|
||||
// {
|
||||
// separator_ = ",";
|
||||
// }
|
||||
}
|
||||
separator_(",") // FREE format
|
||||
{}
|
||||
|
||||
|
||||
Foam::surfaceWriters::nastranWriter::nastranWriter
|
||||
@ -331,12 +325,10 @@ Foam::surfaceWriters::nastranWriter::nastranWriter
|
||||
(
|
||||
"format",
|
||||
options,
|
||||
fieldFormat::LONG
|
||||
fieldFormat::FREE
|
||||
)
|
||||
),
|
||||
fieldMap_(),
|
||||
commonGeometry_(options.getOrDefault("commonGeometry", false)),
|
||||
separator_()
|
||||
commonGeometry_(options.getOrDefault("commonGeometry", false))
|
||||
{
|
||||
if (writeFormat_ == fieldFormat::FREE)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -33,13 +33,13 @@ Description
|
||||
The formatOptions for nastran:
|
||||
\table
|
||||
Property | Description | Reqd | Default
|
||||
fields | Field pairs for PLOAD2/PLOAD4 | yes |
|
||||
format | Nastran format (short/long/free) | no | long
|
||||
format | Nastran format (short/long/free) | no | free
|
||||
scale | Output geometry scaling | no | 1
|
||||
transform | Output coordinate transform | no |
|
||||
fieldLevel | Subtract field level before scaling | no | empty dict
|
||||
fieldScale | Output field scaling | no | empty dict
|
||||
commonGeometry | use separate geometry files | no | false
|
||||
fields | Field pairs for PLOAD2/PLOAD4 | yes |
|
||||
\endtable
|
||||
|
||||
For example,
|
||||
@ -48,13 +48,6 @@ Description
|
||||
{
|
||||
nastran
|
||||
{
|
||||
// OpenFOAM field name to NASTRAN load types
|
||||
fields
|
||||
(
|
||||
(pMean PLOAD2)
|
||||
(p PLOAD4)
|
||||
);
|
||||
|
||||
format free; // format type
|
||||
|
||||
scale 1000; // [m] -> [mm]
|
||||
@ -62,6 +55,13 @@ Description
|
||||
{
|
||||
"p.*" 0.01; // [Pa] -> [mbar]
|
||||
}
|
||||
|
||||
// OpenFOAM field name to NASTRAN load types
|
||||
fields
|
||||
(
|
||||
(pMean PLOAD2)
|
||||
(p PLOAD4)
|
||||
);
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
@ -93,7 +93,6 @@ Description
|
||||
|
||||
Note
|
||||
Output variable scaling does not apply to integer types such as Ids.
|
||||
Field pairs default to PLOAD2 for scalars and PLOAD4 for vectors etc.
|
||||
|
||||
SourceFiles
|
||||
nastranSurfaceWriter.C
|
||||
@ -221,10 +220,10 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct. Default SHORT format
|
||||
//- Default construct. Default FREE format
|
||||
nastranWriter();
|
||||
|
||||
//- Construct with some output options. Default LONG format
|
||||
//- Construct with some output options. Default FREE format
|
||||
explicit nastranWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
|
Loading…
Reference in New Issue
Block a user