PolyFEM
Loading...
Searching...
No Matches
StateSolve.cpp
Go to the documentation of this file.
1#include <polyfem/State.hpp>
2
5
6namespace polyfem
7{
8 using namespace assembler;
9 using namespace io;
10 using namespace utils;
11
12 namespace
13 {
14 bool read_initial_x_from_file(
15 const std::string &state_path,
16 const std::string &x_name,
17 const bool reorder,
18 const Eigen::VectorXi &in_node_to_node,
19 const int dim,
20 Eigen::MatrixXd &x)
21 {
22 if (state_path.empty())
23 return false;
24
25 if (!read_matrix(state_path, x_name, x))
26 {
27 logger().debug("Unable to read initial {} from file ({})", x_name, state_path);
28 return false;
29 }
30
31 if (reorder)
32 {
33 const int ndof = in_node_to_node.size() * dim;
34 // only reorder the first ndof rows
35 x.topRows(ndof) = utils::reorder_matrix(x.topRows(ndof), in_node_to_node, -1, dim);
36 }
37
38 return true;
39 }
40
41 bool check_override_shape(const Eigen::MatrixXd &override, const int ndof)
42 {
43 if (override.rows() != ndof)
44 {
45 return false;
46 }
47 if (override.cols() < 1)
48 {
49 return false;
50 }
51 return true;
52 }
53 } // namespace
54
55 void State::init_solve(Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure, const InitialConditionOverride *ic_override)
56 {
57 POLYFEM_SCOPED_TIMER("Setup RHS");
58
60
61 initial_solution(sol, ic_override);
62 if (sol.cols() > 1) // ignore previous solutions
63 sol.conservativeResize(Eigen::NoChange, 1);
64
65 if (mixed_assembler != nullptr)
66 {
67 const int actual_dim = problem->is_scalar() ? 1 : mesh->dimension();
68
69 pressure.resize(0, 0);
70 sol.conservativeResize(rhs.size(), sol.cols());
71 // Zero initial pressure
72 sol.middleRows(n_bases * actual_dim, n_pressure_bases).setZero();
73 sol(sol.size() - 1) = 0;
74
75 sol_to_pressure(sol, pressure);
76 }
77
78 if (problem->is_time_dependent())
79 save_timestep(0, 0, 0, 0, sol, pressure);
80 }
81
82 void State::initial_solution(Eigen::MatrixXd &solution, const InitialConditionOverride *ic_override) const
83 {
84 assert(solve_data.rhs_assembler != nullptr);
85
86 // Runtime override has the highest priority.
87 if (ic_override && ic_override->solution.size() != 0)
88 {
89 if (!check_override_shape(ic_override->solution, ndof()))
90 {
91 log_and_throw_adjoint_error("Invalid initial solution shape ({}, {}). Expect ({}, >=1).",
92 ic_override->solution.rows(),
93 ic_override->solution.cols(),
94 ndof());
95 }
96 logger().info("Using runtime override for initial solution.");
97 solution = ic_override->solution;
98 return;
99 }
100
101 const bool was_solution_loaded = read_initial_x_from_file(
102 resolve_input_path(args["input"]["data"]["state"]), "u",
103 args["input"]["data"]["reorder"], in_node_to_node,
104 mesh->dimension(), solution);
105
106 if (!was_solution_loaded)
107 {
108 if (problem->is_time_dependent())
109 solve_data.rhs_assembler->initial_solution(solution);
110 else
111 {
112 solution.resize(rhs.size(), 1);
113 solution.setZero();
114 }
115 }
116 }
117
118 void State::initial_velocity(Eigen::MatrixXd &velocity, const InitialConditionOverride *ic_override) const
119 {
120 assert(solve_data.rhs_assembler != nullptr);
121
122 // Runtime override has the highest priority.
123 if (ic_override && ic_override->velocity.size() != 0)
124 {
125 if (!check_override_shape(ic_override->velocity, ndof()))
126 {
127 log_and_throw_adjoint_error("Invalid initial velocity shape ({}, {}). Expect ({}, >=1).",
128 ic_override->velocity.rows(),
129 ic_override->velocity.cols(),
130 ndof());
131 }
132 logger().info("Using runtime override for initial velocity.");
133 velocity = ic_override->velocity;
134 return;
135 }
136
137 const bool was_velocity_loaded = read_initial_x_from_file(
138 resolve_input_path(args["input"]["data"]["state"]), "v",
139 args["input"]["data"]["reorder"], in_node_to_node,
140 mesh->dimension(), velocity);
141
142 if (!was_velocity_loaded)
143 solve_data.rhs_assembler->initial_velocity(velocity);
144 }
145
146 void State::initial_acceleration(Eigen::MatrixXd &acceleration, const InitialConditionOverride *ic_override) const
147 {
148 assert(solve_data.rhs_assembler != nullptr);
149
150 if (ic_override != nullptr && ic_override->acceleration.size() != 0)
151 {
152 if (!check_override_shape(ic_override->acceleration, ndof()))
153 {
154 log_and_throw_adjoint_error("Invalid initial acceleration shape ({}, {}). Expect ({}, >=1).",
155 ic_override->acceleration.rows(),
156 ic_override->acceleration.cols(),
157 ndof());
158 }
159 logger().info("Using runtime override for initial acceleration.");
160 acceleration = ic_override->acceleration;
161 return;
162 }
163
164 const bool was_acceleration_loaded = read_initial_x_from_file(
165 resolve_input_path(args["input"]["data"]["state"]), "a",
166 args["input"]["data"]["reorder"], in_node_to_node,
167 mesh->dimension(), acceleration);
168
169 if (!was_acceleration_loaded)
170 solve_data.rhs_assembler->initial_acceleration(acceleration);
171 }
172} // namespace polyfem
int x
#define POLYFEM_SCOPED_TIMER(...)
Definition Timer.hpp:10
Runtime override for initial-condition histories.
Definition State.hpp:90
Eigen::MatrixXd solution
ndof by H (history size) matrix where each col is solution from a time step.
Definition State.hpp:94
Eigen::MatrixXd acceleration
ndof by H (history size) matrix where each col is acceleration from a time step.
Definition State.hpp:102
Eigen::MatrixXd velocity
ndof by H (history size) matrix where each col is velocity from a time step.
Definition State.hpp:98
int n_bases
number of bases
Definition State.hpp:212
int n_pressure_bases
number of pressure bases
Definition State.hpp:214
void sol_to_pressure(Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure)
splits the solution in solution and pressure for mixed problems
Definition State.cpp:375
Eigen::VectorXi in_node_to_node
Inpute nodes (including high-order) to polyfem nodes, only for isoparametric.
Definition State.hpp:571
void initial_velocity(Eigen::MatrixXd &velocity, const InitialConditionOverride *ic_override=nullptr) const
Load or compute the initial velocity.
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
std::unique_ptr< mesh::Mesh > mesh
current mesh, it can be a Mesh2D or Mesh3D
Definition State.hpp:587
std::shared_ptr< assembler::Problem > problem
current problem, it contains rhs and bc
Definition State.hpp:202
json args
main input arguments containing all defaults
Definition State.hpp:135
void initial_acceleration(Eigen::MatrixXd &acceleration, const InitialConditionOverride *ic_override=nullptr) const
Load or compute the initial acceleration.
void initial_solution(Eigen::MatrixXd &solution, const InitialConditionOverride *ic_override=nullptr) const
Load or compute the initial solution.
void init_solve(Eigen::MatrixXd &sol, Eigen::MatrixXd &pressure, const InitialConditionOverride *ic_override=nullptr)
initialize solver
std::shared_ptr< assembler::RhsAssembler > build_rhs_assembler() const
build a RhsAssembler for the problem
Definition State.hpp:282
int ndof() const
Definition State.hpp:309
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.
solver::SolveData solve_data
timedependent stuff cached
Definition State.hpp:375
std::shared_ptr< assembler::MixedAssembler > mixed_assembler
Definition State.hpp:193
Eigen::MatrixXd rhs
System right-hand side.
Definition State.hpp:241
std::shared_ptr< assembler::RhsAssembler > rhs_assembler
bool read_matrix(const std::string &path, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &mat)
Reads a matrix from a file. Determines the file format based on the path's extension.
Definition MatrixIO.cpp:18
Eigen::MatrixXd reorder_matrix(const Eigen::MatrixXd &in, const Eigen::VectorXi &in_to_out, int out_blocks=-1, const int block_size=1)
Reorder row blocks in a matrix.
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44
void log_and_throw_adjoint_error(const std::string &msg)
Definition Logger.cpp:79