21 Eigen::VectorXd get_updated_mesh_nodes(
const VariableToSimulationGroup &variables_to_simulation,
const std::shared_ptr<State> &curr_state,
const Eigen::VectorXd &
x)
24 curr_state->get_vertices(
V);
27 for (
auto &p : variables_to_simulation)
29 for (
const auto &state : p->get_states())
30 if (state.get() != curr_state.get())
34 auto state_variable = p->get_parametrization().eval(
x);
35 auto output_indexing = p->get_output_indexing(
x);
36 for (
int i = 0; i < output_indexing.size(); ++i)
37 X(output_indexing(i)) = state_variable(i);
50 vector<list<int>>
adj;
53 void topologicalSortUtil(
int v, vector<bool> &visited, stack<int> &Stack);
59 void addEdge(
int v,
int w);
62 vector<int> topologicalSort();
71 void Graph::addEdge(
int v,
int w)
77 void Graph::topologicalSortUtil(
int v, vector<bool> &visited,
84 list<int>::iterator i;
85 for (i =
adj[v].begin(); i !=
adj[v].end(); ++i)
87 topologicalSortUtil(*i, visited, Stack);
95 vector<int> Graph::topologicalSort()
100 vector<bool> visited(
V,
false);
104 for (
int i = 0; i <
V; i++)
105 if (visited[i] ==
false)
106 topologicalSortUtil(i, visited, Stack);
110 while (Stack.empty() ==
false)
112 sorted.push_back(Stack.top());
123 variables_to_simulation_(variables_to_simulation),
124 all_states_(all_states),
125 save_freq(args[
"output"][
"save_frequency"]),
126 enable_slim(args[
"solver"][
"advanced"][
"enable_slim"]),
127 smooth_line_search(args[
"solver"][
"advanced"][
"smooth_line_search"]),
128 solve_in_parallel(args[
"solver"][
"advanced"][
"solve_in_parallel"])
132 if (enable_slim && args[
"solver"][
"nonlinear"][
"advanced"][
"apply_gradient_fd"] !=
"None")
133 adjoint_logger().warn(
"SLIM may affect the finite difference result!");
135 if (enable_slim && smooth_line_search)
136 adjoint_logger().warn(
"Both in-line-search SLIM and after-line-search SLIM are ON!");
138 if (args[
"output"][
"solution"] !=
"")
140 solution_ostream.open(args[
"output"][
"solution"].get<std::string>(), std::ofstream::out);
141 if (!solution_ostream.is_open())
145 solve_in_order.clear();
147 Graph G(all_states.size());
148 for (
int k = 0; k < all_states.size(); k++)
150 auto &arg = args[
"states"][k];
151 if (arg[
"initial_guess"].get<int>() >= 0)
152 G.addEdge(arg[
"initial_guess"].get<int>(), k);
155 solve_in_order = G.topologicalSort();
158 active_state_mask.assign(all_states_.size(),
false);
159 for (
int i = 0; i < all_states_.size(); i++)
161 for (
const auto &v2sim : variables_to_simulation_)
163 for (
const auto &state : v2sim->get_states())
165 if (all_states_[i].get() == state.get())
167 active_state_mask[i] =
true;
196 gradv.setZero(
x.size());
206 form_->first_derivative(
x, gradv);
220 bool need_rebuild_basis =
false;
225 need_rebuild_basis =
true;
229 Eigen::MatrixXd X,
V0,
V1;
238 state_->mesh->dimension());
239 state_->get_vertices(
V0);
240 state_->get_elements(
F);
242 Eigen::MatrixXd V_smooth;
255 adjoint_logger().info(
"Found flipped element in LS, step not valid!");
263 return form_->is_step_valid(x0, x1);
268 return form_->is_step_collision_free(x0, x1);
273 return form_->max_step_size(x0, x1);
278 form_->line_search_begin(x0, x1);
283 form_->line_search_end();
290 form_->post_step(data);
299 adjoint_logger().debug(
"Save solution at iteration {} to file...", iter_num);
300 solution_ostream << iter_num <<
": " << std::setprecision(16) << x0.transpose() << std::endl;
309 bool save_vtu =
true;
310 bool save_rest_mesh =
true;
312 std::string vis_mesh_path = state->resolve_output_path(fmt::format(
"opt_state_{:d}_iter_{:d}.vtu",
id, iter_num));
313 std::string mesh_ext = state->mesh->is_volume() ?
".msh" :
".obj";
314 std::string rest_mesh_path = state->resolve_output_path(fmt::format(
"opt_state_{:d}_iter_{:d}" + mesh_ext,
id, iter_num));
319 adjoint_logger().debug(
"Save final vtu to file {} ...", vis_mesh_path);
321 double tend = state->args.value(
"tend", 1.0);
323 if (!state->args[
"time"].is_null())
324 dt = state->args[
"time"][
"dt"];
326 Eigen::MatrixXd sol = state->diff_cached.u(-1);
328 state->out_geom.save_vtu(
332 Eigen::MatrixXd::Zero(state->n_pressure_bases, 1),
335 state->mesh->is_linear(),
336 state->mesh->has_prism(),
337 state->problem->is_scalar()),
338 state->is_contact_enabled());
342 adjoint_logger().debug(
"Save rest mesh to file {} ...", rest_mesh_path);
347 state->get_vertices(
V);
348 state->get_elements(
F);
349 if (state->mesh->is_volume())
358 bool need_rebuild_basis =
false;
365 need_rebuild_basis =
true;
368 if (need_rebuild_basis)
371 state->build_basis();
377 form_->solution_changed(newX);
390 std::vector<Eigen::MatrixXd> V_old_list;
394 state->get_vertices(
V);
395 V_old_list.push_back(
V);
405 Eigen::MatrixXd V_new, V_smooth;
407 state->get_vertices(V_new);
408 state->get_elements(
F);
415 for (
int i = 0; i < V_smooth.rows(); ++i)
416 state->set_mesh_vertex(i, V_smooth.row(i));
430 for (int i = start; i < end; i++)
432 auto state = all_states_[i];
433 if (active_state_mask[i] || state->diff_cached.size() == 0)
435 state->assemble_rhs();
436 state->assemble_mass_mat();
437 Eigen::MatrixXd sol, pressure;
438 state->solve_problem(sol, pressure);
447 Eigen::MatrixXd sol, pressure;
448 for (
int i : solve_in_order)
450 auto state = all_states_[i];
451 if (active_state_mask[i] || state->diff_cached.size() == 0)
453 state->assemble_rhs();
454 state->assemble_mass_mat();
456 state->solve_problem(sol, pressure);
471 obj->solution_changed(
x);
472 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)
bool is_flipped(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F)
Determine if any simplex is inverted or collapses.
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