OGS
ogs_python_module.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include <pybind11/pybind11.h>
5#include <pybind11/stl.h>
6#include <spdlog/spdlog.h>
7#include <tclap/CmdLine.h>
8
9#include <algorithm>
10
14#include "BaseLib/ConfigTree.h"
15#include "BaseLib/DateTools.h"
16#include "BaseLib/Error.h"
17#include "BaseLib/FileTools.h"
18#include "BaseLib/Logging.h"
19#include "BaseLib/RunTime.h"
21#include "InfoLib/GitInfo.h"
22#include "ogs_embedded_python.h"
23
24static constexpr int EXIT_ARGPARSE_FAILURE = 3; // "mangled" TCLAP status
25static constexpr int EXIT_ARGPARSE_EXIT_OK = 2; // "mangled" TCLAP status
26static_assert(EXIT_FAILURE == 1);
27static_assert(EXIT_SUCCESS == 0);
28
29int checkCommandLineArguments(std::vector<std::string>& argv_str)
30{
31 INFO("Parsing the OGS commandline ...");
32 int argc = argv_str.size();
33 char** argv = new char*[argc];
34 for (int i = 0; i < argc; ++i)
35 {
36 argv[i] = argv_str[i].data();
37 }
38
39 CommandLineArguments cli_args;
40 try
41 {
42 cli_args = parseCommandLineArguments(argc, argv, false);
43 }
44 catch (TCLAP::ArgException const& e)
45 {
46 ERR("Parsing the OGS commandline failed: {}", e.what());
47
48 // "mangle" TCLAP's status
50 }
51 catch (TCLAP::ExitException const& e)
52 {
53 if (e.getExitStatus() == 0)
54 {
56 }
57
58 // "mangle" TCLAP's status
60 }
61
62 INFO("Parsing the OGS commandline passed");
63 return EXIT_SUCCESS;
64}
65
66// Needs to be exported, see
67// https://pybind11.readthedocs.io/en/stable/advanced/misc.html#partitioning-code-over-multiple-extension-modules
68class PYBIND11_EXPORT OGSSimulation
69{
70public:
71 explicit OGSSimulation(std::vector<std::string>& argv_str)
72 {
73 int argc = argv_str.size();
74 char** argv = new char*[argc];
75 for (int i = 0; i < argc; ++i)
76 {
77 argv[i] = argv_str[i].data();
78 }
79
80 CommandLineArguments cli_args;
81 try
82 {
83 cli_args = parseCommandLineArguments(argc, argv, false);
84 }
85 catch (TCLAP::ArgException const& e)
86 {
87 std::cerr << "Parsing the OGS commandline failed: " << e.what()
88 << '\n';
89
90 // "mangle" TCLAP's status
91 throw(e);
92 }
93 catch (TCLAP::ExitException const& e)
94 {
95 throw(e);
96 }
97
99
100 DBUG("OGSSimulation::OGSSimulation(std::vector<std::string>&)");
101
102 INFO(
103 "This is OpenGeoSys-6 version {:s}. Log version: {:d}, Log level: "
104 "{:s}.",
106
108
109 {
110 auto const start_time = std::chrono::system_clock::now();
111 auto const time_str = BaseLib::formatDate(start_time);
112 // todo ask Tobias: started vs starts
113 INFO("OGS starts on {:s} in serial mode / Python embedded mode.",
114 time_str);
115 }
116 try
117 {
118 simulation = std::make_unique<Simulation>(argc, argv);
119 simulation->initializeDataStructures(
120 std::move(cli_args.project),
121 std::move(cli_args.xml_patch_file_names),
122 cli_args.reference_path_is_set,
123 std::move(cli_args.reference_path), cli_args.nonfatal,
124 std::move(cli_args.outdir), std::move(cli_args.mesh_dir),
125 std::move(cli_args.script_dir), cli_args.write_prj);
126 }
127 catch (std::exception& e)
128 {
129 ERR("{}", e.what());
130 ogs_status = EXIT_FAILURE;
131 throw(e);
132 }
133 INFO("OpenGeoSys is now initialized.");
134 }
135
137 {
138 BaseLib::RunTime run_time;
139
140 {
141 auto const start_time = std::chrono::system_clock::now();
142 auto const time_str = BaseLib::formatDate(start_time);
143 INFO("OGS started on {:s} in serial mode.", time_str);
144 }
145
146 std::optional<ApplicationsLib::TestDefinition> test_definition{
147 std::nullopt};
148
149 try
150 {
151 run_time.start();
152 bool solver_succeeded = simulation->executeSimulation();
153 simulation->outputLastTimeStep();
154 test_definition = simulation->getTestDefinition();
155
156 if (solver_succeeded)
157 {
158 INFO("[time] Simulation completed. It took {:g} s.",
159 run_time.elapsed());
160 }
161 else
162 {
163 INFO("[time] Simulation failed. It took {:g} s.",
164 run_time.elapsed());
165 }
166 ogs_status = solver_succeeded ? EXIT_SUCCESS : EXIT_FAILURE;
167 }
168 catch (std::exception& e)
169 {
170 ERR("{}", e.what());
171 ogs_status = EXIT_FAILURE;
172 }
173
174 if (ogs_status == EXIT_FAILURE)
175 {
176 auto const end_time = std::chrono::system_clock::now();
177 auto const time_str = BaseLib::formatDate(end_time);
178 ERR("OGS terminated with error on {:s}.", time_str);
179 return EXIT_FAILURE;
180 }
181
182 return Simulation::runTestDefinitions(test_definition);
183 }
184
186 {
187 auto ogs_status = EXIT_SUCCESS;
188 try
189 {
190 bool solver_succeeded = simulation->executeTimeStep();
191 ogs_status = solver_succeeded ? EXIT_SUCCESS : EXIT_FAILURE;
192 }
193 catch (std::exception& e)
194 {
195 ERR("{}", e.what());
196 ogs_status = EXIT_FAILURE;
197 }
198 return ogs_status;
199 }
200
201 double currentTime() const { return simulation->currentTime(); }
202
203 double endTime() const { return simulation->endTime(); }
204
205 OGSMesh& getMesh(std::string const& name)
206 {
207 auto const mesh_it = mesh_mapping.find(name);
208 if (mesh_it != mesh_mapping.end())
209 {
210 INFO("found OGSMesh '{}' with address: {}", name,
211 fmt::ptr(&(mesh_it->second)));
212 return mesh_it->second;
213 }
214
215 auto const& [it, success] =
216 mesh_mapping.insert({name, OGSMesh(simulation->getMesh(name))});
217 if (!success)
218 {
219 OGS_FATAL("Could not access mesh '{}'.", name);
220 }
221 INFO("insert OGSMesh '{}' with address: {}", name,
222 fmt::ptr(&(it->second)));
223 return it->second;
224 }
225
226 std::vector<std::string> getMeshNames() const
227 {
228 return simulation->getMeshNames();
229 }
230
231 void finalize()
232 {
233 simulation->outputLastTimeStep();
234 simulation.reset(nullptr);
235
236 // Check for swallowed ConfigTree errors after Simulation destructor
237 // runs. This catches configuration errors in objects destroyed at end
238 // of scope.
239 try
240 {
242 }
243 catch (std::exception& e)
244 {
245 ERR("{}", e.what());
246 throw;
247 }
248 }
249
250private:
251 int ogs_status = EXIT_SUCCESS;
252
253 std::unique_ptr<Simulation> simulation;
254 std::map<std::string, OGSMesh> mesh_mapping;
255};
256
263PYBIND11_MODULE(OGSSimulator, m)
264{
266 m.attr("__name__") = "ogs.OGSSimulator";
267 m.doc() = "pybind11 ogs plugin";
268
269 m.def("check_command_line_arguments", &checkCommandLineArguments,
270 "check the command line arguments");
271
272 pybind11::class_<OGSSimulation>(m, "OGSSimulation")
273 .def(pybind11::init<std::vector<std::string>&>())
274 .def("current_time", &OGSSimulation::currentTime,
275 "get current OGS time")
276 .def("end_time", &OGSSimulation::endTime, "get end OGS time")
277 .def("execute_simulation", &OGSSimulation::executeSimulation,
278 "execute OGS simulation")
279 .def("execute_time_step", &OGSSimulation::executeTimeStep,
280 "execute OGS time step")
281 .def("mesh", &OGSSimulation::getMesh,
282 pybind11::return_value_policy::automatic_reference,
283 pybind11::arg("name"), "get unstructured grid from ogs")
284 .def("mesh_names", &OGSSimulation::getMeshNames,
285 "get names of all meshes from ogs")
286 .def("close", &OGSSimulation::finalize, "finalize OGS simulation");
287}
CommandLineArguments parseCommandLineArguments(int argc, char *argv[], bool const exit_on_exception)
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
static void assertNoSwallowedErrors()
Asserts that there have not been any errors reported in the destructor.
Count the running time.
Definition RunTime.h:18
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:31
void start()
Start the timer.
Definition RunTime.h:21
std::map< std::string, OGSMesh > mesh_mapping
OGSMesh & getMesh(std::string const &name)
std::unique_ptr< Simulation > simulation
double endTime() const
OGSSimulation(std::vector< std::string > &argv_str)
double currentTime() const
std::vector< std::string > getMeshNames() const
static OGS_EXPORT_SYMBOL int runTestDefinitions(std::optional< ApplicationsLib::TestDefinition > &test_definition)
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:56
std::string formatDate(std::chrono::time_point< std::chrono::system_clock > const &time)
bool createOutputDirectory(std::string const &dir)
GITINFOLIB_EXPORT const std::string ogs_version
static constexpr int EXIT_ARGPARSE_EXIT_OK
int checkCommandLineArguments(std::vector< std::string > &argv_str)
PYBIND11_MODULE(OGSSimulator, m)
static constexpr int EXIT_ARGPARSE_FAILURE
std::vector< std::string > xml_patch_file_names