Skip to content

Commit b849146

Browse files
authored
Merge pull request #581 from sebproell/node-parsing
Use ValueParser for parsing of nodes
2 parents 9acbc6e + 5627456 commit b849146

9 files changed

+15079
-15135
lines changed

src/core/io/src/4C_io_nodereader.cpp

Lines changed: 35 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
#include "4C_fem_general_fiber_node.hpp"
1414
#include "4C_fem_nurbs_discretization_control_point.hpp"
1515
#include "4C_io_input_file.hpp"
16-
17-
#include <istream>
16+
#include "4C_io_value_parser.hpp"
1817

1918
FOUR_C_NAMESPACE_OPEN
2019

@@ -40,23 +39,19 @@ void Core::IO::read_nodes(Core::IO::InputFile& input, const std::string& node_se
4039
const int myrank = Core::Communication::my_mpi_rank(input.get_comm());
4140
if (myrank > 0) return;
4241

43-
std::string tmp;
44-
std::string tmp2;
45-
4642
int line_count = 0;
4743
for (const auto& node_line : input.in_section_rank_0_only(node_section_name))
4844
{
49-
std::istringstream linestream{std::string{node_line.get_as_dat_style_string()}};
50-
linestream >> tmp;
45+
Core::IO::ValueParser parser{
46+
node_line.get_as_dat_style_string(), {.user_scope_message = "While reading node data: "}};
47+
auto type = parser.read<std::string>();
5148

52-
if (tmp == "NODE")
49+
if (type == "NODE")
5350
{
54-
std::vector<double> coords(3, 0.0);
55-
int nodeid;
56-
// read in the node coordinates
57-
linestream >> nodeid >> tmp >> coords[0] >> coords[1] >> coords[2];
51+
int nodeid = parser.read<int>() - 1;
52+
parser.consume("COORD");
53+
auto coords = parser.read<std::vector<double>>(3);
5854

59-
nodeid--;
6055
max_node_id = std::max(max_node_id, nodeid) + 1;
6156
std::vector<std::shared_ptr<Core::FE::Discretization>> dis =
6257
find_dis_node(element_readers, nodeid);
@@ -70,20 +65,17 @@ void Core::IO::read_nodes(Core::IO::InputFile& input, const std::string& node_se
7065
}
7166
}
7267
// this node is a Nurbs control point
73-
else if (tmp == "CP")
68+
else if (type == "CP")
7469
{
75-
// read control points for isogeometric analysis (Nurbs)
76-
std::vector<double> coords(3, 0.0);
77-
double weight;
70+
int cpid = parser.read<int>() - 1;
71+
parser.consume("COORD");
72+
auto coords = parser.read<std::vector<double>>(3);
73+
double weight = parser.read<double>();
7874

79-
int cpid;
80-
linestream >> cpid >> tmp >> coords[0] >> coords[1] >> coords[2] >> weight;
81-
cpid--;
8275
max_node_id = std::max(max_node_id, cpid) + 1;
8376
if (cpid != line_count)
8477
FOUR_C_THROW(
8578
"Reading of control points {} failed: They must be numbered consecutive!!", cpid);
86-
if (tmp != "COORD") FOUR_C_THROW("failed to read control point {}", cpid);
8779
std::vector<std::shared_ptr<Core::FE::Discretization>> diss =
8880
find_dis_node(element_readers, cpid);
8981

@@ -96,7 +88,7 @@ void Core::IO::read_nodes(Core::IO::InputFile& input, const std::string& node_se
9688
}
9789
}
9890
// this is a special node with additional fiber information
99-
else if (tmp == "FNODE")
91+
else if (type == "FNODE")
10092
{
10193
enum class FiberType
10294
{
@@ -107,97 +99,45 @@ void Core::IO::read_nodes(Core::IO::InputFile& input, const std::string& node_se
10799
};
108100

109101
// read fiber node
110-
std::vector<double> coords(3, 0.0);
111102
std::map<Core::Nodes::CoordinateSystemDirection, std::array<double, 3>> cosyDirections;
112103
std::vector<std::array<double, 3>> fibers;
113104
std::map<Core::Nodes::AngleType, double> angles;
114105

115-
int nodeid;
116-
// read in the node coordinates and fiber direction
117-
linestream >> nodeid >> tmp >> coords[0] >> coords[1] >> coords[2];
118-
nodeid--;
106+
int nodeid = parser.read<int>() - 1;
107+
parser.consume("COORD");
108+
auto coords = parser.read<std::vector<double>>(3);
119109
max_node_id = std::max(max_node_id, nodeid) + 1;
120110

121-
while (true)
111+
while (!parser.at_end())
122112
{
123-
// store current position of linestream reader
124-
auto length = linestream.tellg();
125-
// try to read new fiber direction or coordinate system
126-
linestream >> tmp2;
127-
128-
// Nothing more to read.
129-
if (linestream.fail()) break;
113+
auto next = parser.read<std::string>();
130114

131-
Core::Nodes::CoordinateSystemDirection coordinateSystemDirection;
132-
Core::Nodes::AngleType angleType;
133-
FiberType type = FiberType::Unknown;
134-
135-
if (tmp2 == "FIBER" + std::to_string(1 + fibers.size()))
115+
if (next == "FIBER" + std::to_string(1 + fibers.size()))
136116
{
137-
type = FiberType::Fiber;
117+
fibers.emplace_back(parser.read<std::array<double, 3>>());
138118
}
139-
else if (tmp2 == "CIR")
119+
else if (next == "CIR")
140120
{
141-
coordinateSystemDirection = Core::Nodes::CoordinateSystemDirection::Circular;
142-
type = FiberType::CosyDirection;
121+
cosyDirections[Nodes::CoordinateSystemDirection::Circular] =
122+
parser.read<std::array<double, 3>>();
143123
}
144-
else if (tmp2 == "TAN")
124+
else if (next == "TAN")
145125
{
146-
coordinateSystemDirection = Core::Nodes::CoordinateSystemDirection::Tangential;
147-
type = FiberType::CosyDirection;
126+
cosyDirections[Nodes::CoordinateSystemDirection::Tangential] =
127+
parser.read<std::array<double, 3>>();
148128
}
149-
else if (tmp2 == "RAD")
129+
else if (next == "RAD")
150130
{
151-
coordinateSystemDirection = Core::Nodes::CoordinateSystemDirection::Radial;
152-
type = FiberType::CosyDirection;
131+
cosyDirections[Nodes::CoordinateSystemDirection::Radial] =
132+
parser.read<std::array<double, 3>>();
153133
}
154-
else if (tmp2 == "HELIX")
134+
else if (next == "HELIX")
155135
{
156-
angleType = Core::Nodes::AngleType::Helix;
157-
type = FiberType::Angle;
136+
angles[Nodes::AngleType::Helix] = parser.read<double>();
158137
}
159-
else if (tmp2 == "TRANS")
160-
{
161-
angleType = Core::Nodes::AngleType::Transverse;
162-
type = FiberType::Angle;
163-
}
164-
else
165-
{
166-
// No more fiber information. Jump to last position.
167-
linestream.seekg(length);
168-
break;
169-
}
170-
171-
// add fiber / angle to the map
172-
switch (type)
138+
else if (next == "TRANS")
173139
{
174-
case FiberType::Unknown:
175-
{
176-
FOUR_C_THROW(
177-
"Unknown fiber node attribute. Numbered fibers must be in order, i.e. "
178-
"FIBER1, FIBER2, ...");
179-
}
180-
case FiberType::Angle:
181-
{
182-
linestream >> angles[angleType];
183-
break;
184-
}
185-
case FiberType::Fiber:
186-
{
187-
std::array<double, 3> fiber_components;
188-
linestream >> fiber_components[0] >> fiber_components[1] >> fiber_components[2];
189-
fibers.emplace_back(fiber_components);
190-
break;
191-
}
192-
case FiberType::CosyDirection:
193-
{
194-
linestream >> cosyDirections[coordinateSystemDirection][0] >>
195-
cosyDirections[coordinateSystemDirection][1] >>
196-
cosyDirections[coordinateSystemDirection][2];
197-
break;
198-
}
199-
default:
200-
FOUR_C_THROW("Unknown number of components");
140+
angles[Nodes::AngleType::Transverse] = parser.read<double>();
201141
}
202142
}
203143

@@ -212,7 +152,7 @@ void Core::IO::read_nodes(Core::IO::InputFile& input, const std::string& node_se
212152
}
213153
}
214154
else
215-
FOUR_C_THROW("unexpected word '{}'", tmp.c_str());
155+
FOUR_C_THROW("Unknown node type '{}'", type);
216156

217157
++line_count;
218158
}

src/core/io/src/4C_io_value_parser.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include "4C_io_value_parser.hpp"
99

10+
#include <c4/charconv.hpp>
11+
1012
#include <algorithm>
1113

1214
FOUR_C_NAMESPACE_OPEN
@@ -74,34 +76,36 @@ void Core::IO::ValueParser::read_internal(bool& value)
7476

7577
void Core::IO::ValueParser::read_internal(int& value)
7678
{
77-
std::string token(advance_token());
78-
std::size_t end;
79-
try
79+
auto token(advance_token());
80+
if (token.front() == '+') [[unlikely]]
8081
{
81-
value = std::stoi(token.data(), &end);
82+
token = token.substr(1);
8283
}
83-
catch (const std::logic_error&)
84+
85+
c4::csubstr token_cstr = c4::csubstr{token.data(), token.size()};
86+
// Note: this could use std::from_chars if clang fully supports it at some point.
87+
std::size_t n_chars_used = c4::from_chars_first(token_cstr, &value);
88+
if (n_chars_used != token.size())
8489
{
85-
FOUR_C_THROW("Could not parse '{}' as an integer value.", token.c_str());
90+
FOUR_C_THROW("Could not parse '{}' as an integer value.", token);
8691
}
87-
88-
if (end != token.size()) FOUR_C_THROW("Could not parse '{}' as an integer value.", token.c_str());
8992
}
9093

9194
void Core::IO::ValueParser::read_internal(double& value)
9295
{
93-
std::string token(advance_token());
94-
std::size_t end;
95-
try
96+
auto token(advance_token());
97+
if (token.front() == '+') [[unlikely]]
9698
{
97-
value = std::stod(token.data(), &end);
99+
token = token.substr(1);
98100
}
99-
catch (const std::logic_error&)
101+
102+
c4::csubstr token_cstr = c4::csubstr{token.data(), token.size()};
103+
// Note: this could use std::from_chars if clang fully supports it at some point.
104+
std::size_t n_chars_used = c4::from_chars_first(token_cstr, &value);
105+
if (n_chars_used != token.size())
100106
{
101-
FOUR_C_THROW("Could not parse '{}' as a double value.", token.c_str());
107+
FOUR_C_THROW("Could not parse '{}' as a double value.", token);
102108
}
103-
104-
if (end != token.size()) FOUR_C_THROW("Could not parse '{}' as a double value.", token.c_str());
105109
}
106110

107111
void Core::IO::ValueParser::read_internal(std::string& value)

0 commit comments

Comments
 (0)