PolyFEM
Loading...
Searching...
No Matches
StateOutput.cpp
Go to the documentation of this file.
1#include <polyfem/State.hpp>
2
5
7
8#include <filesystem>
9
10namespace polyfem
11{
12 void State::compute_errors(const Eigen::MatrixXd &sol)
13 {
14 if (!args["output"]["advanced"]["compute_error"])
15 return;
16
17 double tend = 0;
18
19 if (!args["time"].is_null())
20 {
21 tend = args["time"]["tend"];
22 }
23
25 }
26
27 std::string State::root_path() const
28 {
29 if (utils::is_param_valid(args, "root_path"))
30 return args["root_path"].get<std::string>();
31 return "";
32 }
33
34 std::string State::resolve_input_path(const std::string &path, const bool only_if_exists) const
35 {
36 return utils::resolve_path(path, root_path(), only_if_exists);
37 }
38
39 std::string State::resolve_output_path(const std::string &path) const
40 {
41 if (output_dir.empty() || path.empty() || std::filesystem::path(path).is_absolute())
42 {
43 return path;
44 }
45 return std::filesystem::weakly_canonical(std::filesystem::path(output_dir) / path).string();
46 }
47
48 void State::save_timestep(const double time, const int t, const double t0, const double dt, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
49 {
50 if (args["output"]["advanced"]["save_time_sequence"] && !(t % args["output"]["paraview"]["skip_frame"].get<int>()))
51 {
52 logger().trace("Saving VTU...");
53 POLYFEM_SCOPED_TIMER("Saving VTU");
54 const std::string step_name = args["output"]["advanced"]["timestep_prefix"];
55
57 resolve_output_path(fmt::format(step_name + "{:d}.vtu", t)),
58 *this, sol, pressure, time, dt,
60 mesh->is_linear(),
61 mesh->has_prism(),
62 problem->is_scalar()),
64
66 resolve_output_path(args["output"]["paraview"]["file_name"]),
67 [step_name](int i) { return fmt::format(step_name + "{:d}.vtm", i); },
68 t, t0, dt, args["output"]["paraview"]["skip_frame"].get<int>());
69 }
70 }
71
72 void State::save_json(const Eigen::MatrixXd &sol)
73 {
74 const std::string out_path = resolve_output_path(args["output"]["json"]);
75 if (!out_path.empty())
76 {
77 std::ofstream out(out_path);
78 if (!out.is_open())
79 {
80 logger().error("Unable to save simulation JSON to {}", out_path);
81 return;
82 }
83 save_json(sol, out);
84 out.close();
85 }
86 }
87
88 void State::save_json(const Eigen::MatrixXd &sol, std::ostream &out)
89 {
90 if (!mesh)
91 {
92 logger().error("Load the mesh first!");
93 return;
94 }
95 if (sol.size() <= 0)
96 {
97 logger().error("Solve the problem first!");
98 return;
99 }
100
101 logger().info("Saving json...");
102
103 using json = nlohmann::json;
104 json j;
107 assembler->name(), iso_parametric(), args["output"]["advanced"]["sol_at_node"],
108 j);
109 out << j.dump(4) << std::endl;
110 }
111
112 void State::save_subsolve(const int i, const int t, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
113 {
114 if (!args["output"]["advanced"]["save_solve_sequence_debug"].get<bool>())
115 return;
116
117 double dt = 1;
118 if (!args["time"].is_null())
119 dt = args["time"]["dt"];
120
122 resolve_output_path(fmt::format("solve_{:d}.vtu", i)),
123 *this, sol, pressure, t, dt,
125 mesh->is_linear(),
126 mesh->has_prism(),
127 problem->is_scalar()),
129 }
130
131 void State::export_data(const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
132 {
133 if (!mesh)
134 {
135 logger().error("Load the mesh first!");
136 return;
137 }
138 if (n_bases <= 0)
139 {
140 logger().error("Build the bases first!");
141 return;
142 }
143 // if (rhs.size() <= 0)
144 // {
145 // logger().error("Assemble the rhs first!");
146 // return;
147 // }
148 if (sol.size() <= 0)
149 {
150 logger().error("Solve the problem first!");
151 return;
152 }
153
154 // Export vtu mesh of solution + wire mesh of deformed input
155 // + mesh colored with the bases
156 const std::string vis_mesh_path = resolve_output_path(args["output"]["paraview"]["file_name"]);
157 const std::string nodes_path = resolve_output_path(args["output"]["data"]["nodes"]);
158 const std::string solution_path = resolve_output_path(args["output"]["data"]["solution"]);
159 const std::string stress_path = resolve_output_path(args["output"]["data"]["stress_mat"]);
160 const std::string mises_path = resolve_output_path(args["output"]["data"]["mises"]);
161
162 double tend = args.value("tend", 1.0);
163 double dt = 1;
164 if (!args["time"].is_null())
165 dt = args["time"]["dt"];
166
168 *this, sol, pressure,
169 !args["time"].is_null(),
170 tend, dt,
172 mesh->is_linear(),
173 mesh->has_prism(),
174 problem->is_scalar()),
175 vis_mesh_path,
176 nodes_path,
177 solution_path,
178 stress_path,
179 mises_path,
181
182 if (assembler->name() == "Electrostatics")
183 {
184 std::shared_ptr<assembler::Electrostatics> electrostatics_assembler = std::dynamic_pointer_cast<assembler::Electrostatics>(assembler);
185 double energy = electrostatics_assembler->compute_stored_energy(mesh->is_volume(), n_bases, bases, geom_bases(), ass_vals_cache, 0, sol);
186 double capacitance = 2 * energy;
187 logger().info("Capacitance computation: {}", capacitance);
188 }
189 }
190
191 void State::save_restart_json(const double t0, const double dt, const int t) const
192 {
193 const std::string restart_json_path = args["output"]["restart_json"];
194 if (restart_json_path.empty())
195 return;
196
197 json restart_json;
198 restart_json["root_path"] = root_path();
199 restart_json["common"] = root_path();
200 restart_json["time"] = {{"t0", t0 + dt * t}};
201
202 restart_json["space"] = R"({
203 "remesh": {
204 "collapse": {
205 "abs_max_edge_length": -1,
206 "rel_max_edge_length": -1
207 }
208 }
209 })"_json;
210 restart_json["space"]["remesh"]["collapse"]["abs_max_edge_length"] = std::min(
211 args["space"]["remesh"]["collapse"]["abs_max_edge_length"].get<double>(),
212 starting_min_edge_length * args["space"]["remesh"]["collapse"]["rel_max_edge_length"].get<double>());
213 restart_json["space"]["remesh"]["collapse"]["rel_max_edge_length"] = std::numeric_limits<float>::max();
214
215 std::string rest_mesh_path = args["output"]["data"]["rest_mesh"].get<std::string>();
216 if (!rest_mesh_path.empty())
217 {
218 rest_mesh_path = resolve_output_path(fmt::format(args["output"]["data"]["rest_mesh"], t));
219
220 std::vector<json> patch;
221 if (args["geometry"].is_array())
222 {
223 const std::vector<json> in_geometry = args["geometry"];
224 for (int i = 0; i < in_geometry.size(); ++i)
225 {
226 if (!in_geometry[i]["is_obstacle"].get<bool>())
227 {
228 patch.push_back({
229 {"op", "remove"},
230 {"path", fmt::format("/geometry/{}", i)},
231 });
232 }
233 }
234
235 const int remaining_geometry = in_geometry.size() - patch.size();
236 assert(remaining_geometry >= 0);
237
238 patch.push_back({
239 {"op", "add"},
240 {"path", fmt::format("/geometry/{}", remaining_geometry > 0 ? "0" : "-")},
241 {"value",
242 {
243 // TODO: this does not set the surface selections
244 {"mesh", rest_mesh_path},
245 }},
246 });
247 }
248 else
249 {
250 assert(args["geometry"].is_object());
251 patch.push_back({
252 {"op", "remove"},
253 {"path", "/geometry"},
254 });
255 patch.push_back({
256 {"op", "replace"},
257 {"path", "/geometry"},
258 {"value",
259 {
260 // TODO: this does not set the surface selections
261 {"mesh", rest_mesh_path},
262 }},
263 });
264 }
265
266 restart_json["patch"] = patch;
267 }
268
269 restart_json["input"] = {{
270 "data",
271 {
272 {"state", resolve_output_path(fmt::format(args["output"]["data"]["state"], t))},
273 },
274 }};
275
276 std::ofstream file(resolve_output_path(fmt::format(restart_json_path, t)));
277 file << restart_json;
278 }
279} // namespace polyfem
#define POLYFEM_SCOPED_TIMER(...)
Definition Timer.hpp:10
io::OutRuntimeData timings
runtime statistics
Definition State.hpp:590
int n_bases
number of bases
Definition State.hpp:178
int n_pressure_bases
number of pressure bases
Definition State.hpp:180
assembler::AssemblyValsCache ass_vals_cache
used to store assembly values for small problems
Definition State.hpp:196
const std::vector< basis::ElementBases > & geom_bases() const
Get a constant reference to the geometry mapping bases.
Definition State.hpp:223
std::string root_path() const
Get the root path for the state (e.g., args["root_path"] or ".")
std::shared_ptr< assembler::Assembler > assembler
assemblers
Definition State.hpp:155
void compute_errors(const Eigen::MatrixXd &sol)
computes all errors
void save_subsolve(const int i, const int t, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
saves a subsolve when save_solve_sequence_debug is true
io::OutGeometryData out_geom
visualization stuff
Definition State.hpp:588
std::string resolve_output_path(const std::string &path) const
Resolve output path relative to output_dir if the path is not absolute.
std::string output_dir
Directory for output files.
Definition State.hpp:586
void save_timestep(const double time, const int t, const double t0, const double dt, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
saves a timestep
void save_json(const Eigen::MatrixXd &sol, std::ostream &out)
saves the output statistic to a stream
double starting_min_edge_length
Definition State.hpp:593
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
Definition State.hpp:471
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
Definition State.hpp:168
json args
main input arguments containing all defaults
Definition State.hpp:101
void save_restart_json(const double t0, const double dt, const int t) const
Save a JSON sim file for restarting the simulation at time t.
io::OutStatsData stats
Other statistics.
Definition State.hpp:592
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
Definition State.hpp:171
Eigen::VectorXi disc_ordersq
Definition State.hpp:190
bool iso_parametric() const
check if using iso parametric bases
Definition State.cpp:461
void export_data(const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure)
saves all data on the disk according to the input params
std::string resolve_input_path(const std::string &path, const bool only_if_exists=false) const
Resolve input path relative to root_path() if the path is not absolute.
bool is_contact_enabled() const
does the simulation have contact
Definition State.hpp:556
Eigen::VectorXi disc_orders
vector of discretization orders, used when not all elements have the same degree, one per element
Definition State.hpp:190
void save_pvd(const std::string &name, const std::function< std::string(int)> &vtu_names, int time_steps, double t0, double dt, int skip_frame=1) const
save a PVD of a time dependent simulation
Definition OutData.cpp:2562
void save_vtu(const std::string &path, const State &state, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure, const double t, const double dt, const ExportOptions &opts, const bool is_contact_enabled) const
saves the vtu file for time t
Definition OutData.cpp:1247
void export_data(const State &state, const Eigen::MatrixXd &sol, const Eigen::MatrixXd &pressure, const bool is_time_dependent, const double tend_in, const double dt, const ExportOptions &opts, const std::string &vis_mesh_path, const std::string &nodes_path, const std::string &solution_path, const std::string &stress_path, const std::string &mises_path, const bool is_contact_enabled) const
exports everytihng, txt, vtu, etc
Definition OutData.cpp:1059
void save_json(const nlohmann::json &args, const int n_bases, const int n_pressure_bases, const Eigen::MatrixXd &sol, const mesh::Mesh &mesh, const Eigen::VectorXi &disc_orders, const Eigen::VectorXi &disc_ordersq, const assembler::Problem &problem, const OutRuntimeData &runtime, const std::string &formulation, const bool isoparametric, const int sol_at_node_id, nlohmann::json &j)
saves the output statistic to a json object
Definition OutData.cpp:3043
void compute_errors(const int n_bases, const std::vector< polyfem::basis::ElementBases > &bases, const std::vector< polyfem::basis::ElementBases > &gbases, const polyfem::mesh::Mesh &mesh, const assembler::Problem &problem, const double tend, const Eigen::MatrixXd &sol)
compute errors
Definition OutData.cpp:2805
std::string resolve_path(const std::string &path, const std::string &input_file_path, const bool only_if_exists=false)
bool is_param_valid(const json &params, const std::string &key)
Determine if a key exists and is non-null in a json object.
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44
nlohmann::json json
Definition Common.hpp:9