Loading [MathJax]/jax/output/HTML-CSS/config.js
PolyFEM
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 solution_frames.emplace_back();
58
60 resolve_output_path(fmt::format(step_name + "{:d}.vtu", t)),
61 *this, sol, pressure, time, dt,
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
118 solution_frames.emplace_back();
119
120 double dt = 1;
121 if (!args["time"].is_null())
122 dt = args["time"]["dt"];
123
125 resolve_output_path(fmt::format("solve_{:d}.vtu", i)),
126 *this, sol, pressure, t, dt,
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 vis_mesh_path,
173 nodes_path,
174 solution_path,
175 stress_path,
176 mises_path,
178
179 if (assembler->name() == "Electrostatics")
180 {
181 std::shared_ptr<assembler::Electrostatics> electrostatics_assembler = std::dynamic_pointer_cast<assembler::Electrostatics>(assembler);
182 double energy = electrostatics_assembler->compute_stored_energy(mesh->is_volume(), n_bases, bases, geom_bases(), ass_vals_cache, 0, sol);
183 double capacitance = 2 * energy;
184 logger().info("Capacitance computation: {}", capacitance);
185 }
186 }
187
188 void State::save_restart_json(const double t0, const double dt, const int t) const
189 {
190 const std::string restart_json_path = args["output"]["restart_json"];
191 if (restart_json_path.empty())
192 return;
193
194 json restart_json;
195 restart_json["root_path"] = root_path();
196 restart_json["common"] = root_path();
197 restart_json["time"] = {{"t0", t0 + dt * t}};
198
199 restart_json["space"] = R"({
200 "remesh": {
201 "collapse": {
202 "abs_max_edge_length": -1,
203 "rel_max_edge_length": -1
204 }
205 }
206 })"_json;
207 restart_json["space"]["remesh"]["collapse"]["abs_max_edge_length"] = std::min(
208 args["space"]["remesh"]["collapse"]["abs_max_edge_length"].get<double>(),
209 starting_min_edge_length * args["space"]["remesh"]["collapse"]["rel_max_edge_length"].get<double>());
210 restart_json["space"]["remesh"]["collapse"]["rel_max_edge_length"] = std::numeric_limits<float>::max();
211
212 std::string rest_mesh_path = args["output"]["data"]["rest_mesh"].get<std::string>();
213 if (!rest_mesh_path.empty())
214 {
215 rest_mesh_path = resolve_output_path(fmt::format(args["output"]["data"]["rest_mesh"], t));
216
217 std::vector<json> patch;
218 if (args["geometry"].is_array())
219 {
220 const std::vector<json> in_geometry = args["geometry"];
221 for (int i = 0; i < in_geometry.size(); ++i)
222 {
223 if (!in_geometry[i]["is_obstacle"].get<bool>())
224 {
225 patch.push_back({
226 {"op", "remove"},
227 {"path", fmt::format("/geometry/{}", i)},
228 });
229 }
230 }
231
232 const int remaining_geometry = in_geometry.size() - patch.size();
233 assert(remaining_geometry >= 0);
234
235 patch.push_back({
236 {"op", "add"},
237 {"path", fmt::format("/geometry/{}", remaining_geometry > 0 ? "0" : "-")},
238 {"value",
239 {
240 // TODO: this does not set the surface selections
241 {"mesh", rest_mesh_path},
242 }},
243 });
244 }
245 else
246 {
247 assert(args["geometry"].is_object());
248 patch.push_back({
249 {"op", "remove"},
250 {"path", "/geometry"},
251 });
252 patch.push_back({
253 {"op", "replace"},
254 {"path", "/geometry"},
255 {"value",
256 {
257 // TODO: this does not set the surface selections
258 {"mesh", rest_mesh_path},
259 }},
260 });
261 }
262
263 restart_json["patch"] = patch;
264 }
265
266 restart_json["input"] = {{
267 "data",
268 {
269 {"state", resolve_output_path(fmt::format(args["output"]["data"]["state"], t))},
270 },
271 }};
272
273 std::ofstream file(resolve_output_path(fmt::format(restart_json_path, t)));
274 file << restart_json;
275 }
276} // namespace polyfem
#define POLYFEM_SCOPED_TIMER(...)
Definition Timer.hpp:10
io::OutRuntimeData timings
runtime statistics
Definition State.hpp:583
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:581
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:573
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:586
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
Definition State.hpp:466
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.
std::vector< io::SolutionFrame > solution_frames
saves the frames in a vector instead of VTU
Definition State.hpp:579
io::OutStatsData stats
Other statistics.
Definition State.hpp:585
std::vector< basis::ElementBases > bases
FE bases, the size is #elements.
Definition State.hpp:171
bool iso_parametric() const
check if using iso parametric bases
Definition State.cpp:462
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 has contact
Definition State.hpp:551
Eigen::VectorXi disc_orders
vector of discretization orders, used when not all elements have the same degree, one per element
Definition State.hpp:190
bool solve_export_to_file
flag to decide if exporting the time dependent solution to files or save it in the solution_frames ar...
Definition State.hpp:577
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:2317
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, std::vector< SolutionFrame > &solution_frames) const
exports everytihng, txt, vtu, etc
Definition OutData.cpp:940
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, std::vector< SolutionFrame > &solution_frames) const
saves the vtu file for time t
Definition OutData.cpp:1114
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 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:2793
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:2560
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:42
nlohmann::json json
Definition Common.hpp:9