Skip to content

Commit ff9394e

Browse files
committed
Change the 4C CLI parser to CLI11
1 parent 83fb9e1 commit ff9394e

22 files changed

+1090
-577
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ four_c_configure_dependency(Backtrace DEFAULT OFF)
149149
four_c_configure_dependency(ryml REQUIRED)
150150
four_c_configure_dependency(magic_enum REQUIRED)
151151
four_c_configure_dependency(ZLIB REQUIRED)
152+
four_c_configure_dependency(CLI11 REQUIRED)
152153
four_c_configure_dependency(Python DEFAULT ON) # not required but useful for most developers
153154
four_c_configure_dependency(pybind11 DEFAULT OFF)
154155

apps/global_full/4C_global_full_io.cpp

Lines changed: 12 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99

1010
#include "4C_global_full_io.hpp"
1111

12+
#include "4C_comm_utils.hpp"
1213
#include "4C_global_data_read.hpp"
1314
#include "4C_global_legacy_module.hpp"
1415
#include "4C_io_pstream.hpp"
16+
#include "4C_utils_exceptions.hpp"
1517

1618
#include <Teuchos_StandardParameterEntryValidators.hpp>
1719
#include <Teuchos_TimeMonitor.hpp>
1820

1921
FOUR_C_NAMESPACE_OPEN
2022

21-
2223
Core::IO::InputFile setup_input_file(const MPI_Comm comm)
2324
{
2425
return Global::set_up_input_file(comm);
@@ -33,7 +34,8 @@ void emit_general_metadata(const Core::IO::YamlNodeRef& root_ref)
3334
/**
3435
* \brief Sets up the parallel output environment.
3536
*/
36-
void setup_parallel_output(const CommandlineArguments& arguments)
37+
void setup_parallel_output(
38+
const CommandlineArguments& arguments, const Core::Communication::Communicators& communicators)
3739
{
3840
using namespace FourC;
3941

@@ -45,21 +47,22 @@ void setup_parallel_output(const CommandlineArguments& arguments)
4547
int oproc = io.get<int>("LIMIT_OUTP_TO_PROC");
4648
auto level = Teuchos::getIntegralValue<Core::IO::Verbositylevel>(io, "VERBOSITY");
4749

48-
Core::IO::cout.setup(screen, file, preGrpID, level, std::move(arguments.comms.local_comm()),
49-
oproc, arguments.comms.group_id(), arguments.output_file_identifier);
50+
Core::IO::cout.setup(screen, file, preGrpID, level, communicators.local_comm(), oproc,
51+
communicators.group_id(), arguments.output_file_identifier);
5052
}
5153

52-
void setup_global_problem(Core::IO::InputFile& input_file, const CommandlineArguments& arguments)
54+
void setup_global_problem(Core::IO::InputFile& input_file, const CommandlineArguments& arguments,
55+
Core::Communication::Communicators& communicators)
5356
{
5457
Global::Problem* problem = Global::Problem::instance();
55-
problem->set_restart_step(arguments.restart_step);
56-
problem->set_communicators(arguments.comms);
58+
problem->set_restart_step(arguments.restart);
59+
problem->set_communicators(communicators);
5760
Global::read_parameter(*problem, input_file);
5861

59-
setup_parallel_output(arguments);
62+
setup_parallel_output(arguments, communicators);
6063

6164
// create control file for output and read restart data if required
62-
problem->open_control_file(arguments.comms.local_comm(), arguments.input_file_name,
65+
problem->open_control_file(communicators.local_comm(), arguments.input_file_name,
6366
arguments.output_file_identifier, arguments.restart_file_identifier);
6467

6568
// input of materials
@@ -108,203 +111,11 @@ double walltime_in_seconds()
108111
1.0e-3;
109112
}
110113

111-
void parse_commandline_arguments(CommandlineArguments& arguments)
112-
{
113-
int group = arguments.comms.group_id();
114-
115-
int restart_group = 0;
116-
int my_rank = Core::Communication::my_mpi_rank(arguments.comms.local_comm());
117-
118-
std::vector<std::string> inout =
119-
parse_input_output_files(arguments.argc, arguments.argv, my_rank);
120-
121-
// number of input/output arguments specified by the user
122-
auto inout_args = int(inout.size());
123-
124-
std::string input_filename;
125-
std::string output_file_identifier;
126-
std::string restart_file_identifier;
127-
// set input file name in each group
128-
switch (arguments.comms.np_type())
129-
{
130-
case Core::Communication::NestedParallelismType::no_nested_parallelism:
131-
input_filename = inout[0];
132-
output_file_identifier = inout[1];
133-
restart_group = 0;
134-
break;
135-
case Core::Communication::NestedParallelismType::every_group_read_input_file:
136-
{
137-
if (inout_args > 4)
138-
FOUR_C_THROW(
139-
"You specified too many arguments ({}). A maximum of four args is allowed", inout_args);
140-
141-
input_filename = inout[0];
142-
// check whether output_file_identifier includes a dash and in case separate the number at the
143-
// end
144-
size_t pos = inout[1].rfind('-');
145-
if (pos != std::string::npos)
146-
{
147-
int number = atoi(inout[1].substr(pos + 1).c_str());
148-
inout[1] = inout[1].substr(0, pos);
149-
output_file_identifier = std::format("{}_group_{}_{}", inout[1], group, number);
150-
}
151-
else
152-
{
153-
output_file_identifier = std::format("{}_group_{}", inout[1], group);
154-
}
155-
restart_group = 0;
156-
}
157-
break;
158-
case Core::Communication::NestedParallelismType::separate_input_files:
159-
if (inout_args % arguments.comms.num_groups() != 0)
160-
FOUR_C_THROW("Each group needs the same number of arguments for input/output.");
161-
inout_args /= arguments.comms.num_groups();
162-
input_filename = inout[group * inout_args];
163-
output_file_identifier = inout[group * inout_args + 1];
164-
restart_group = group;
165-
break;
166-
default:
167-
FOUR_C_THROW(
168-
"-nptype is not correct. Only everyGroupReadInputFile and separateInputFiles "
169-
"are available");
170-
break;
171-
}
172-
173-
if (my_rank == 0)
174-
{
175-
std::cout << "input is read from " << input_filename << std::endl;
176-
}
177-
parse_restart_definition(
178-
inout, inout_args, restart_file_identifier, output_file_identifier, restart_group, arguments);
179-
180-
/// set IO file names and identifiers
181-
arguments.input_file_name = input_filename;
182-
arguments.output_file_identifier = output_file_identifier;
183-
arguments.restart_file_identifier = restart_file_identifier;
184-
}
185-
186-
187-
std::vector<std::string> parse_input_output_files(const int argc, char** argv, const int my_rank)
188-
{
189-
if (argc <= 1)
190-
{
191-
if (my_rank == 0)
192-
{
193-
printf("You forgot to give the input and output file names!\n");
194-
printf("Try again!\n");
195-
}
196-
MPI_Finalize();
197-
exit(EXIT_FAILURE);
198-
}
199-
else if (argc <= 2)
200-
{
201-
if (my_rank == 0)
202-
{
203-
printf("You forgot to give the output file name!\n");
204-
printf("Try again!\n");
205-
}
206-
MPI_Finalize();
207-
exit(EXIT_FAILURE);
208-
}
209-
210-
211-
// parse command line and separate input/output arguments
212-
std::vector<std::string> inout;
213-
for (int i = 1; i < argc; i++)
214-
{
215-
std::string temp = argv[i];
216-
if (temp.substr(0, 1) != "-") inout.push_back(temp);
217-
}
218-
return inout;
219-
}
220-
221-
void parse_restart_definition(const std::vector<std::string>& inout, const int in_out_args,
222-
std::string& restart_file_identifier, const std::string& outfile_identifier,
223-
const int restart_group, CommandlineArguments& arguments)
224-
{
225-
// Global::Problem* problem = Global::Problem::instance();
226-
// bool parameter defining if input argument is given
227-
bool restartIsGiven = false;
228-
bool restartfromIsGiven = false;
229-
230-
// default case is an identical restartfile_identifier and outputfile_identifier
231-
restart_file_identifier = outfile_identifier;
232-
for (int i = 2; i < in_out_args; i++)
233-
{
234-
std::string restart = inout[restart_group * in_out_args + i];
235-
236-
if (restart.substr(0, 8) == "restart=")
237-
{
238-
const std::string option = restart.substr(8, std::string::npos);
239-
int r;
240-
if (option.compare("last_possible") == 0)
241-
{
242-
r = -1; // here we use a negative value to trigger the search in the control file in
243-
// the later step. It does not mean a restart from a negative number is allowed
244-
// from the user point of view.
245-
}
246-
else
247-
{
248-
r = atoi(option.c_str());
249-
if (r < 0) FOUR_C_THROW("Restart number must be a positive value");
250-
}
251-
// tell the global problem about the restart step given in the command line
252-
arguments.restart_step = r;
253-
restartIsGiven = true;
254-
}
255-
else if (restart.substr(0, 12) == "restartfrom=")
256-
{
257-
restart_file_identifier = (restart.substr(12, std::string::npos).c_str());
258-
259-
switch (arguments.comms.np_type())
260-
{
261-
case Core::Communication::NestedParallelismType::no_nested_parallelism:
262-
case Core::Communication::NestedParallelismType::separate_input_files:
263-
// nothing to add to restartfileidentifier
264-
break;
265-
case Core::Communication::NestedParallelismType::every_group_read_input_file:
266-
{
267-
// check whether restartfileidentifier includes a dash and in case separate the number
268-
// at the end
269-
size_t pos = restart_file_identifier.rfind('-');
270-
if (pos != std::string::npos)
271-
{
272-
int number = atoi(restart_file_identifier.substr(pos + 1).c_str());
273-
std::string identifier = restart_file_identifier.substr(0, pos);
274-
restart_file_identifier =
275-
std::format("{}_group_{}_-{}", identifier, arguments.comms.group_id(), number);
276-
}
277-
else
278-
{
279-
restart_file_identifier =
280-
std::format("{}_group_{}", restart_file_identifier, arguments.comms.group_id());
281-
}
282-
}
283-
break;
284-
default:
285-
FOUR_C_THROW(
286-
"-nptype is not correct. Only everyGroupReadInputFile and "
287-
"separateInputFiles are available");
288-
break;
289-
}
290-
291-
restartfromIsGiven = true;
292-
}
293-
}
294-
295-
// throw error in case restartfrom is given but no restart step is specified
296-
if (restartfromIsGiven && !restartIsGiven)
297-
{
298-
FOUR_C_THROW("You need to specify a restart step when using restartfrom.");
299-
}
300-
}
301-
302114
void write_timemonitor(MPI_Comm comm)
303115
{
304116
std::shared_ptr<const Teuchos::Comm<int>> TeuchosComm =
305117
Core::Communication::to_teuchos_comm<int>(comm);
306118
Teuchos::TimeMonitor::summarize(Teuchos::Ptr(TeuchosComm.get()), std::cout, false, true, false);
307119
}
308120

309-
310121
FOUR_C_NAMESPACE_CLOSE

apps/global_full/4C_global_full_io.hpp

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,11 @@
1111
#include "4C_config.hpp"
1212

1313
#include "4C_comm_utils.hpp"
14+
#include "4C_io_command_line_helpers.hpp"
1415
#include "4C_io_input_file.hpp"
1516

1617
FOUR_C_NAMESPACE_OPEN
1718

18-
/**
19-
* Gather some arguments from the command line and store them in a struct. This should be
20-
* changed to a proper parser
21-
*/
22-
struct CommandlineArguments
23-
{
24-
int argc;
25-
char** argv;
26-
27-
std::string input_file_name;
28-
std::string output_file_identifier;
29-
std::string restart_file_identifier;
30-
int restart_step = 0;
31-
32-
Core::Communication::Communicators comms;
33-
};
34-
3519
/**
3620
* \brief Initializes the input file for reading.
3721
* \note Currently, this function is a wrapper around Global::set_up_input_file to keep the main
@@ -52,29 +36,14 @@ void emit_general_metadata(const Core::IO::YamlNodeRef& root_ref);
5236
* \brief Sets up the Global::Problem instance and puts all the parameters from the input file
5337
* there.
5438
*/
55-
void setup_global_problem(Core::IO::InputFile& input_file, const CommandlineArguments& arguments);
56-
39+
void setup_global_problem(Core::IO::InputFile& input_file, const CommandlineArguments& arguments,
40+
Core::Communication::Communicators& communicators);
5741
/**
5842
* \brief Returns the wall time in seconds.
5943
*/
6044
double walltime_in_seconds();
6145

62-
/**
63-
* \brief Parses command line arguments and sets input, output, and restart file identifiers.
64-
*/
65-
void parse_commandline_arguments(CommandlineArguments& arguments);
66-
67-
/**
68-
* \brief Parses input and output files from command line arguments.
69-
*/
70-
std::vector<std::string> parse_input_output_files(const int argc, char** argv, const int my_rank);
7146

72-
/**
73-
* \brief Parses the restart definition from command line arguments.
74-
*/
75-
void parse_restart_definition(const std::vector<std::string>& inout, int in_out_args,
76-
std::string& restart_file_identifier, const std::string& outfile_identifier, int restart_group,
77-
CommandlineArguments& arguments);
7847

7948
/**
8049
* \brief Writes the Teuchos::TimeMonitor information to std::cout

0 commit comments

Comments
 (0)