Skip to content

Commit d04f25a

Browse files
committed
Remove InputFile::in_section from public interface
1 parent 1828d26 commit d04f25a

File tree

3 files changed

+42
-85
lines changed

3 files changed

+42
-85
lines changed

src/core/io/src/4C_io_input_file.cpp

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,20 @@ namespace Core::IO
315315
return std::ranges::any_of(
316316
legacy_section_names_, [&](const auto& name) { return name == section_name; });
317317
}
318+
319+
InputFile::FragmentIteratorRange in_section(const std::string& section_name) const
320+
{
321+
static const std::vector<InputFile::Fragment> empty;
322+
323+
if (!content_by_section_.contains(section_name))
324+
{
325+
return std::views::all(empty);
326+
}
327+
328+
// Take a const reference to the section content to match the return type.
329+
const auto& lines = content_by_section_.at(section_name).fragments;
330+
return std::views::all(lines);
331+
}
318332
};
319333

320334
} // namespace Internal
@@ -830,44 +844,6 @@ namespace Core::IO
830844
}
831845
}
832846

833-
InputFile::FragmentIteratorRange InputFile::in_section(const std::string& section_name) const
834-
{
835-
static const std::vector<Fragment> empty;
836-
837-
// Early return in case the section does not exist at all.
838-
const bool known_somewhere = has_section(section_name);
839-
if (!known_somewhere)
840-
{
841-
return std::views::all(empty);
842-
}
843-
844-
const bool locally_known = pimpl_->content_by_section_.contains(section_name);
845-
const bool known_everywhere = Core::Communication::all_reduce<bool>(
846-
locally_known, [](const bool& r, const bool& in) { return r && in; }, pimpl_->comm_);
847-
848-
if (known_everywhere)
849-
{
850-
// Take a const reference to the section content to match the return type.
851-
const auto& lines = pimpl_->content_by_section_.at(section_name).fragments;
852-
return std::views::all(lines);
853-
}
854-
else
855-
// Distribute the content of the section to all ranks.
856-
{
857-
FOUR_C_ASSERT((!locally_known && (Core::Communication::my_mpi_rank(pimpl_->comm_) > 0)) ||
858-
(locally_known && (Core::Communication::my_mpi_rank(pimpl_->comm_) == 0)),
859-
"Implementation error: section should be known on rank 0 and unknown on others.");
860-
861-
auto& content = pimpl_->content_by_section_[section_name];
862-
Core::Communication::broadcast(content, 0, pimpl_->comm_);
863-
content.set_up_fragments();
864-
865-
const auto& lines = pimpl_->content_by_section_.at(section_name).fragments;
866-
return std::views::all(lines);
867-
}
868-
}
869-
870-
871847

872848
InputFile::FragmentIteratorRange InputFile::in_section_rank_0_only(
873849
const std::string& section_name) const
@@ -951,7 +927,7 @@ namespace Core::IO
951927
if (list_spec)
952928
{
953929
std::vector<InputParameterContainer> list_entries;
954-
for (const auto& line : in_section(section_name))
930+
for (const auto& line : pimpl_->in_section(section_name))
955931
{
956932
Core::IO::ValueParser parser{line.get_as_dat_style_string(),
957933
{.user_scope_message =
@@ -976,7 +952,7 @@ namespace Core::IO
976952
// Create a group in the dat file format by starting with the section name.
977953
std::stringstream flattened_dat;
978954
flattened_dat << std::quoted(section_name) << " ";
979-
for (const auto& line : in_section(section_name))
955+
for (const auto& line : pimpl_->in_section(section_name))
980956
{
981957
std::string line_str(line.get_as_dat_style_string());
982958
// Split the line into key-value according to the dat file format. Quote keys and values
@@ -1083,7 +1059,7 @@ namespace Core::IO
10831059
auto section = tree.rootref().append_child();
10841060
section << ryml::key(section_name);
10851061
section |= ryml::SEQ;
1086-
for (const auto& line : in_section(section_name))
1062+
for (const auto& line : pimpl_->in_section(section_name))
10871063
{
10881064
section.append_child() = ryml::csubstr(
10891065
line.get_as_dat_style_string().data(), line.get_as_dat_style_string().size());

src/core/io/src/4C_io_input_file.hpp

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,16 @@ namespace Core::IO
4040
* This class encapsulates input files independent of their format.
4141
*
4242
* Objects of this class read the content of a file and grant access to it. The input is not
43-
* yet interpreted in any way. Input files contain different sections. A section either contains
44-
* key-value pairs or a list of arbitrary lines of text. The content is accessed via the
45-
* in_section() function which return InputFile::Fragment objects. These hide what exactly is
46-
* contained and in which format. The content can be matched against an expected InputSpec to
47-
* extract meaningful data.
43+
* yet interpreted in any way. Input files contain different sections. The content can be matched
44+
* against an expected InputSpec via match_section() to extract meaningful data.
4845
*
4946
* Sections may appear in an arbitrary order and each section name must be unique. An exception is
5047
* the special section named "INCLUDES" which can contain a list of other files that should be
5148
* read in addition to the current file.
5249
*
5350
* Three file formats are supported: the custom .dat file format and the standard .yaml (or .yml)
5451
* and .json formats. The format of a file is detected based on its ending. If the ending is not
55-
* one of the above mentioned, the file is assumed to be in the .dat format.
52+
* one of the above-mentioned, the file is assumed to be in the .dat format.
5653
* Included files do not have to use the same format as the including file.
5754
*
5855
* The following example shows the structure of a .dat file:
@@ -86,6 +83,7 @@ namespace Core::IO
8683
* SECTION2:
8784
* - A line with content that is not a key-value pair.
8885
* - It can contain anything.
86+
* - We call these unstructured sections "legacy sections".
8987
* @endcode
9088
*
9189
*
@@ -213,31 +211,10 @@ namespace Core::IO
213211
*/
214212
[[nodiscard]] std::filesystem::path file_for_section(const std::string& section_name) const;
215213

216-
/**
217-
* Get a range of Fragments inside a section. A Fragment always contains meaningful content,
218-
* i.e., something other than whitespace or comments. The usual way to interact with the
219-
* Fragments is as follows:
220-
*
221-
* @code
222-
* for (const auto& input_fragment : input.in_section("section_name"))
223-
* {
224-
* auto parameters = fragment.match(spec);
225-
* }
226-
* @endcode
227-
*
228-
* @return A range of Fragments which encapsulate the content of the section. Use the
229-
* Fragment::match() function to extract the content.
230-
*
231-
* @note This is a collective call that needs to be called on all MPI ranks in the
232-
* communicator associated with this object. Depending on the section size, the content
233-
* might need to be distributed from rank 0 to all other ranks. This happens automatically.
234-
*/
235-
FragmentIteratorRange in_section(const std::string& section_name) const;
236214

237215
/**
238-
* This function is similar to in_section(), but it only returns the lines on rank 0 and
239-
* returns an empty range on all other ranks. This is useful for sections that might be huge
240-
* and are not processed on all ranks.
216+
* Returns the lines in a section on rank 0 and returns an empty range on all other ranks. This
217+
* only works for legacy sections.
241218
*/
242219
FragmentIteratorRange in_section_rank_0_only(const std::string& section_name) const;
243220

@@ -247,7 +224,7 @@ namespace Core::IO
247224
* that you do not need to pass an InputSpec to this function, since the InputFile object
248225
* already knows about the expected format of the section. Nevertheless, this function only
249226
* makes sense for sections with a known InputSpec. Legacy string sections cannot use this
250-
* function and must be processed with in_section() or in_section_rank_0_only().
227+
* function and must be processed with in_section_rank_0_only().
251228
*/
252229
void match_section(const std::string& section_name, InputParameterContainer& container) const;
253230

src/core/io/tests/4C_io_input_file_test.cpp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ namespace
2121
{
2222
using namespace FourC;
2323

24-
void check_section(
24+
void check_section_rank_0_only(
2525
Core::IO::InputFile& input, const std::string& section, const std::vector<std::string>& lines)
2626
{
2727
SCOPED_TRACE("Checking section " + section);
2828
ASSERT_TRUE(input.has_section(section));
29-
auto section_lines = input.in_section(section);
29+
auto section_lines = input.in_section_rank_0_only(section);
3030
std::vector<std::string> section_lines_str;
3131
std::ranges::copy(section_lines | std::views::transform([](const auto& line)
3232
{ return std::string{line.get_as_dat_style_string()}; }),
@@ -57,10 +57,12 @@ namespace
5757
EXPECT_TRUE(input.has_section("EMPTY"));
5858
EXPECT_FALSE(input.has_section("NONEXISTENT SECTION"));
5959

60-
check_section(input, "SECTION WITH SPACES", {"line in section with spaces"});
61-
check_section(input, "SECTION/WITH/SLASHES", {"line in section with slashes"});
62-
check_section(input, "SHORT SECTION", std::vector<std::string>(3, "line in short section"));
63-
check_section(input, "PARTICLES", std::vector<std::string>(30, "line in long section"));
60+
check_section_rank_0_only(input, "SECTION WITH SPACES", {"line in section with spaces"});
61+
check_section_rank_0_only(input, "SECTION/WITH/SLASHES", {"line in section with slashes"});
62+
check_section_rank_0_only(
63+
input, "SHORT SECTION", std::vector<std::string>(3, "line in short section"));
64+
check_section_rank_0_only(
65+
input, "PARTICLES", std::vector<std::string>(30, "line in long section"));
6466
}
6567

6668
TEST(InputFile, HasIncludes)
@@ -86,11 +88,11 @@ namespace
8688
EXPECT_EQ(input.file_for_section("INCLUDED SECTION 1a").filename(), "include1a.dat");
8789
EXPECT_EQ(input.file_for_section("SECTION 1").filename(), "main.dat");
8890

89-
check_section(input, "INCLUDED SECTION 1a", std::vector<std::string>(2, "line"));
90-
check_section(input, "INCLUDED SECTION 1b", std::vector<std::string>(2, "line"));
91-
check_section(input, "INCLUDED SECTION 2", std::vector<std::string>(2, "line"));
92-
check_section(input, "INCLUDED SECTION 3", std::vector<std::string>(2, "line"));
93-
check_section(input, "PARTICLES", std::vector<std::string>(5, "line"));
91+
check_section_rank_0_only(input, "INCLUDED SECTION 1a", std::vector<std::string>(2, "line"));
92+
check_section_rank_0_only(input, "INCLUDED SECTION 1b", std::vector<std::string>(2, "line"));
93+
check_section_rank_0_only(input, "INCLUDED SECTION 2", std::vector<std::string>(2, "line"));
94+
check_section_rank_0_only(input, "INCLUDED SECTION 3", std::vector<std::string>(2, "line"));
95+
check_section_rank_0_only(input, "PARTICLES", std::vector<std::string>(5, "line"));
9496
}
9597

9698
TEST(InputFile, CyclicIncludes)
@@ -122,7 +124,8 @@ namespace
122124
EXPECT_FALSE(input.has_section("EMPTY"));
123125
EXPECT_FALSE(input.has_section("NONEXISTENT SECTION"));
124126

125-
check_section(input, "SECTION WITH LINES", {"first line", "second line", "third line"});
127+
check_section_rank_0_only(
128+
input, "SECTION WITH LINES", {"first line", "second line", "third line"});
126129
}
127130

128131
TEST(InputFile, YamlIncludes)
@@ -146,8 +149,9 @@ namespace
146149
comm};
147150
input.read(input_file_name);
148151

149-
check_section(input, "INCLUDED SECTION 1", std::vector<std::string>(2, "line"));
150-
check_section(input, "SECTION WITH SUBSTRUCTURE", {"MAT 1 THERMO COND 1 2 3 CAPA 2"});
152+
check_section_rank_0_only(input, "INCLUDED SECTION 1", std::vector<std::string>(2, "line"));
153+
check_section_rank_0_only(
154+
input, "SECTION WITH SUBSTRUCTURE", {"MAT 1 THERMO COND 1 2 3 CAPA 2"});
151155

152156
EXPECT_EQ(input.file_for_section("INCLUDED SECTION 2").filename(), "included.yaml");
153157

0 commit comments

Comments
 (0)