20 Eigen::VectorXd get_updated_mesh_nodes(
const VariableToSimulationGroup &variables_to_simulation,
const std::shared_ptr<State> &curr_state,
const Eigen::VectorXd &
x)
23 curr_state->get_vertices(
V);
26 for (
auto &p : variables_to_simulation)
28 for (
const auto &state : p->get_states())
29 if (state.get() != curr_state.get())
33 auto state_variable = p->get_parametrization().eval(
x);
34 auto output_indexing = p->get_output_indexing(
x);
35 for (
int i = 0; i < output_indexing.size(); ++i)
36 X(output_indexing(i)) = state_variable(i);
49 vector<list<int>>
adj;
52 void topologicalSortUtil(
int v, vector<bool> &visited, stack<int> &Stack);
58 void addEdge(
int v,
int w);
61 vector<int> topologicalSort();
70 void Graph::addEdge(
int v,
int w)
76 void Graph::topologicalSortUtil(
int v, vector<bool> &visited,
83 list<int>::iterator i;
84 for (i =
adj[v].begin(); i !=
adj[v].end(); ++i)
86 topologicalSortUtil(*i, visited, Stack);
94 vector<int> Graph::topologicalSort()
99 vector<bool> visited(
V,
false);
103 for (
int i = 0; i <
V; i++)
104 if (visited[i] ==
false)
105 topologicalSortUtil(i, visited, Stack);
109 while (Stack.empty() ==
false)
111 sorted.push_back(Stack.top());
122 variables_to_simulation_(variables_to_simulation),
123 all_states_(all_states),
124 save_freq(args[
"output"][
"save_frequency"]),
125 enable_slim(args[
"solver"][
"advanced"][
"enable_slim"]),
126 smooth_line_search(args[
"solver"][
"advanced"][
"smooth_line_search"]),
127 solve_in_parallel(args[
"solver"][
"advanced"][
"solve_in_parallel"])
131 if (enable_slim && args[
"solver"][
"nonlinear"][
"advanced"][
"apply_gradient_fd"] !=
"None")
132 adjoint_logger().warn(
"SLIM may affect the finite difference result!");
134 if (enable_slim && smooth_line_search)
135 adjoint_logger().warn(
"Both in-line-search SLIM and after-line-search SLIM are ON!");
137 if (args[
"output"][
"solution"] !=
"")
139 solution_ostream.open(args[
"output"][
"solution"].get<std::string>(), std::ofstream::out);
140 if (!solution_ostream.is_open())
144 solve_in_order.clear();
146 Graph G(all_states.size());
147 for (
int k = 0; k < all_states.size(); k++)
149 auto &arg = args[
"states"][k];
150 if (arg[
"initial_guess"].get<int>() >= 0)
151 G.addEdge(arg[
"initial_guess"].get<int>(), k);
154 solve_in_order = G.topologicalSort();
157 active_state_mask.assign(all_states_.size(),
false);
158 for (
int i = 0; i < all_states_.size(); i++)
160 for (
const auto &v2sim : variables_to_simulation_)
162 for (
const auto &state : v2sim->get_states())
164 if (all_states_[i].get() == state.get())
166 active_state_mask[i] =
true;
195 gradv.setZero(
x.size());
205 form_->first_derivative(
x, gradv);
219 bool need_rebuild_basis =
false;
224 need_rebuild_basis =
true;
228 Eigen::MatrixXd X,
V0,
V1;
237 state_->mesh->dimension());
238 state_->get_vertices(
V0);
239 state_->get_elements(
F);
241 Eigen::MatrixXd V_smooth;
254 adjoint_logger().info(
"Found flipped element in LS, step not valid!");
262 return form_->is_step_valid(x0, x1);
267 return form_->is_step_collision_free(x0, x1);
272 return form_->max_step_size(x0, x1);
277 form_->line_search_begin(x0, x1);
282 form_->line_search_end();
289 form_->post_step(data);
298 adjoint_logger().debug(
"Save solution at iteration {} to file...", iter_num);
299 solution_ostream << iter_num <<
": " << std::setprecision(16) << x0.transpose() << std::endl;
308 bool save_vtu =
true;
309 bool save_rest_mesh =
true;
311 std::string vis_mesh_path = state->resolve_output_path(fmt::format(
"opt_state_{:d}_iter_{:d}.vtu",
id, iter_num));
312 std::string mesh_ext = state->mesh->is_volume() ?
".msh" :
".obj";
313 std::string rest_mesh_path = state->resolve_output_path(fmt::format(
"opt_state_{:d}_iter_{:d}" + mesh_ext,
id, iter_num));
318 adjoint_logger().debug(
"Save final vtu to file {} ...", vis_mesh_path);
320 double tend = state->args.value(
"tend", 1.0);
322 if (!state->args[
"time"].is_null())
323 dt = state->args[
"time"][
"dt"];
325 Eigen::MatrixXd sol = state->diff_cached.u(-1);
327 state->out_geom.save_vtu(
331 Eigen::MatrixXd::Zero(state->n_pressure_bases, 1),
334 state->is_contact_enabled(),
335 state->solution_frames);
339 adjoint_logger().debug(
"Save rest mesh to file {} ...", rest_mesh_path);
344 state->get_vertices(
V);
345 state->get_elements(
F);
346 if (state->mesh->is_volume())
355 bool need_rebuild_basis =
false;
362 need_rebuild_basis =
true;
365 if (need_rebuild_basis)
368 state->build_basis();
374 form_->solution_changed(newX);
387 std::vector<Eigen::MatrixXd> V_old_list;
391 state->get_vertices(
V);
392 V_old_list.push_back(
V);
402 Eigen::MatrixXd V_new, V_smooth;
404 state->get_vertices(V_new);
405 state->get_elements(
F);
412 for (
int i = 0; i < V_smooth.rows(); ++i)
413 state->set_mesh_vertex(i, V_smooth.row(i));
427 for (int i = start; i < end; i++)
429 auto state = all_states_[i];
430 if (active_state_mask[i] || state->diff_cached.size() == 0)
432 state->assemble_rhs();
433 state->assemble_mass_mat();
434 Eigen::MatrixXd sol, pressure;
435 state->solve_problem(sol, pressure);
444 Eigen::MatrixXd sol, pressure;
445 for (
int i : solve_in_order)
447 auto state = all_states_[i];
448 if (active_state_mask[i] || state->diff_cached.size() == 0)
450 state->assemble_rhs();
451 state->assemble_mass_mat();
453 state->solve_problem(sol, pressure);
468 obj->solution_changed(
x);
469 if (obj->value(
x) > 0)
vector< list< int > > adj
#define POLYFEM_SCOPED_TIMER(...)
static void write(const std::string &path, const mesh::Mesh &mesh, const bool binary)
saves the mesh
static bool write(const std::string &path, const Eigen::MatrixXd &v, const Eigen::MatrixXi &e, const Eigen::MatrixXi &f)
bool after_line_search_custom_operation(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
double max_step_size(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
void gradient(const Eigen::VectorXd &x, Eigen::VectorXd &gradv) override
std::ofstream solution_ostream
const bool smooth_line_search
void save_to_file(const int iter_num, const Eigen::VectorXd &x0)
bool stop(const TVector &x) override
bool is_step_valid(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
std::vector< std::shared_ptr< AdjointForm > > stopping_conditions_
void hessian(const Eigen::VectorXd &x, StiffnessMatrix &hessian) override
void post_step(const polysolve::nonlinear::PostStepData &data) override
AdjointNLProblem(std::shared_ptr< AdjointForm > form, const VariableToSimulationGroup &variables_to_simulation, const std::vector< std::shared_ptr< State > > &all_states, const json &args)
void line_search_end() override
void solution_changed(const Eigen::VectorXd &new_x) override
bool is_step_collision_free(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
double value(const Eigen::VectorXd &x) override
std::vector< std::shared_ptr< State > > all_states_
std::shared_ptr< AdjointForm > form_
const VariableToSimulationGroup variables_to_simulation_
void line_search_begin(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) override
const bool solve_in_parallel
A collection of VariableToSimulation.
bool apply_slim(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &V_new, Eigen::MatrixXd &V_smooth, const int max_iters)
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
void maybe_parallel_for(int size, const std::function< void(int, int, int)> &partial_for)
spdlog::logger & adjoint_logger()
Retrieves the current logger for adjoint.
void log_and_throw_adjoint_error(const std::string &msg)
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix