PolyFEM
Loading...
Searching...
No Matches
NLProblem.cpp
Go to the documentation of this file.
1#include "NLProblem.hpp"
2
4
5/*
6m \frac{\partial^2 u}{\partial t^2} = \psi = \text{div}(\sigma[u])\newline
7u^{t+1} = u(t+\Delta t)\approx u(t) + \Delta t \dot u + \frac{\Delta t^2} 2 \ddot u \newline
8= u(t) + \Delta t \dot u + \frac{\Delta t^2}{2} \psi\newline
9M u^{t+1}_h \approx M u^t_h + \Delta t M v^t_h + \frac{\Delta t^2} {2} A u^{t+1}_h \newline
10%
11M (u^{t+1}_h - (u^t_h + \Delta t v^t_h)) - \frac{\Delta t^2} {2} A u^{t+1}_h
12*/
13// mü = ψ = div(σ[u])
14// uᵗ⁺¹ = u(t + Δt) ≈ u(t) + Δtu̇ + ½Δt²ü = u(t) + Δtu̇ + ½Δt²ψ
15// Muₕᵗ⁺¹ ≈ Muₕᵗ + ΔtMvₕᵗ ½Δt²Auₕᵗ⁺¹
16// Root-finding form:
17// M(uₕᵗ⁺¹ - (uₕᵗ + Δtvₕᵗ)) - ½Δt²Auₕᵗ⁺¹ = 0
18
19namespace polyfem::solver
20{
22 const int full_size,
23 const std::vector<int> &boundary_nodes,
24 const std::vector<std::shared_ptr<Form>> &forms)
25 : FullNLProblem(forms),
26 boundary_nodes_(boundary_nodes),
27 full_size_(full_size),
28 reduced_size_(full_size_ - boundary_nodes.size()),
29 t_(0),
30 rhs_assembler_(nullptr),
31 local_boundary_(nullptr),
32 n_boundary_samples_(0)
33 {
35 }
36
38 const int full_size,
39 const std::vector<int> &boundary_nodes,
40 const std::vector<mesh::LocalBoundary> &local_boundary,
41 const int n_boundary_samples,
42 const assembler::RhsAssembler &rhs_assembler,
43 const std::shared_ptr<utils::PeriodicBoundary> &periodic_bc,
44 const double t,
45 const std::vector<std::shared_ptr<Form>> &forms)
46 : FullNLProblem(forms),
47 full_boundary_nodes_(boundary_nodes),
48 boundary_nodes_(periodic_bc ? periodic_bc->full_to_periodic(boundary_nodes) : boundary_nodes),
49 full_size_(full_size),
50 reduced_size_((periodic_bc ? periodic_bc->n_periodic_dof() : full_size) - boundary_nodes_.size()),
51 periodic_bc_(periodic_bc),
52 t_(t),
53 rhs_assembler_(&rhs_assembler),
54 local_boundary_(&local_boundary),
55 n_boundary_samples_(n_boundary_samples)
56 {
57 assert(std::is_sorted(boundary_nodes.begin(), boundary_nodes.end()));
58 assert(boundary_nodes.size() == 0 || (boundary_nodes.front() >= 0 && boundary_nodes.back() < full_size_));
60 }
61
66
67 void NLProblem::update_lagging(const TVector &x, const int iter_num)
68 {
70 }
71
72 void NLProblem::update_quantities(const double t, const TVector &x)
73 {
74 t_ = t;
75 const TVector full = reduced_to_full(x);
76 for (auto &f : forms_)
77 f->update_quantities(t, full);
78 }
79
80 void NLProblem::line_search_begin(const TVector &x0, const TVector &x1)
81 {
83 }
84
85 double NLProblem::max_step_size(const TVector &x0, const TVector &x1)
86 {
88 }
89
90 bool NLProblem::is_step_valid(const TVector &x0, const TVector &x1)
91 {
93 }
94
95 bool NLProblem::is_step_collision_free(const TVector &x0, const TVector &x1)
96 {
98 }
99
100 double NLProblem::value(const TVector &x)
101 {
102 // TODO: removed fearure const bool only_elastic
104 }
105
106 void NLProblem::gradient(const TVector &x, TVector &grad)
107 {
108 TVector full_grad;
110 grad = full_to_reduced_grad(full_grad);
111 }
112
113 void NLProblem::hessian(const TVector &x, THessian &hessian)
114 {
115 THessian full_hessian;
117
119 }
120
121 void NLProblem::solution_changed(const TVector &newX)
122 {
124 }
125
126 void NLProblem::post_step(const polysolve::nonlinear::PostStepData &data)
127 {
128 FullNLProblem::post_step(polysolve::nonlinear::PostStepData(data.iter_num, data.solver_info, reduced_to_full(data.x), reduced_to_full(data.grad)));
129
130 // TODO: add me back
131 // if (state_.args["output"]["advanced"]["save_nl_solve_sequence"])
132 // {
133 // const Eigen::MatrixXd displacements = utils::unflatten(reduced_to_full(x), state_.mesh->dimension());
134 // io::OBJWriter::write(
135 // state_.resolve_output_path(fmt::format("nonlinear_solve_iter{:03d}.obj", iter_num)),
136 // state_.collision_mesh.displace_vertices(displacements),
137 // state_.collision_mesh.edges(), state_.collision_mesh.faces());
138 // }
139 }
140
141 void NLProblem::set_apply_DBC(const TVector &x, const bool val)
142 {
143 TVector full = reduced_to_full(x);
144 for (auto &form : forms_)
145 form->set_apply_DBC(full, val);
146 }
147
148 NLProblem::TVector NLProblem::full_to_reduced(const TVector &full) const
149 {
150 TVector reduced;
152 return reduced;
153 }
154
155 NLProblem::TVector NLProblem::full_to_reduced_grad(const TVector &full) const
156 {
157 TVector reduced;
159 return reduced;
160 }
161
162 NLProblem::TVector NLProblem::reduced_to_full(const TVector &reduced) const
163 {
164 TVector full;
166 return full;
167 }
168
169 Eigen::MatrixXd NLProblem::boundary_values() const
170 {
171 Eigen::MatrixXd result = Eigen::MatrixXd::Zero(full_size(), 1);
172 // rhs_assembler->set_bc(*local_boundary_, boundary_nodes_, n_boundary_samples_, local_neumann_boundary_, result, t_);
173 rhs_assembler_->set_bc(*local_boundary_, full_boundary_nodes_, n_boundary_samples_, std::vector<mesh::LocalBoundary>(), result, Eigen::MatrixXd(), t_);
174 return result;
175 }
176
177 template <class FullMat, class ReducedMat>
178 void NLProblem::full_to_reduced_aux(const std::vector<int> &boundary_nodes, const int full_size, const int reduced_size, const FullMat &full, ReducedMat &reduced) const
179 {
180 using namespace polyfem;
181
182 // Reduced is already at the full size
183 if (full_size == reduced_size || full.size() == reduced_size)
184 {
185 reduced = full;
186 return;
187 }
188
189 assert(full.size() == full_size);
190 assert(full.cols() == 1);
191 reduced.resize(reduced_size, 1);
192
193 Eigen::MatrixXd mid;
194 if (periodic_bc_)
195 mid = periodic_bc_->full_to_periodic(full, false);
196 else
197 mid = full;
198
199 assert(std::is_sorted(boundary_nodes.begin(), boundary_nodes.end()));
200
201 long j = 0;
202 size_t k = 0;
203 for (int i = 0; i < mid.size(); ++i)
204 {
205 if (k < boundary_nodes.size() && boundary_nodes[k] == i)
206 {
207 ++k;
208 continue;
209 }
210
211 assert(j < reduced.size());
212 reduced(j++) = mid(i);
213 }
214 }
215
216 template <class ReducedMat, class FullMat>
217 void NLProblem::reduced_to_full_aux(const std::vector<int> &boundary_nodes, const int full_size, const int reduced_size, const ReducedMat &reduced, const Eigen::MatrixXd &rhs, FullMat &full) const
218 {
219 using namespace polyfem;
220
221 // Full is already at the reduced size
222 if (full_size == reduced_size || full_size == reduced.size())
223 {
224 full = reduced;
225 return;
226 }
227
228 assert(reduced.size() == reduced_size);
229 assert(reduced.cols() == 1);
230 full.resize(full_size, 1);
231
232 assert(std::is_sorted(boundary_nodes.begin(), boundary_nodes.end()));
233
234 long j = 0;
235 size_t k = 0;
236 Eigen::MatrixXd mid(reduced_size + boundary_nodes.size(), 1);
237 for (int i = 0; i < mid.size(); ++i)
238 {
239 if (k < boundary_nodes.size() && boundary_nodes[k] == i)
240 {
241 ++k;
242 mid(i) = rhs(i);
243 continue;
244 }
245
246 mid(i) = reduced(j++);
247 }
248
249 full = periodic_bc_ ? periodic_bc_->periodic_to_full(full_size, mid) : mid;
250 }
251
252 template <class FullMat, class ReducedMat>
253 void NLProblem::full_to_reduced_aux_grad(const std::vector<int> &boundary_nodes, const int full_size, const int reduced_size, const FullMat &full, ReducedMat &reduced) const
254 {
255 using namespace polyfem;
256
257 // Reduced is already at the full size
258 if (full_size == reduced_size || full.size() == reduced_size)
259 {
260 reduced = full;
261 return;
262 }
263
264 assert(full.size() == full_size);
265 assert(full.cols() == 1);
266 reduced.resize(reduced_size, 1);
267
268 Eigen::MatrixXd mid;
269 if (periodic_bc_)
270 mid = periodic_bc_->full_to_periodic(full, true);
271 else
272 mid = full;
273
274 long j = 0;
275 size_t k = 0;
276 for (int i = 0; i < mid.size(); ++i)
277 {
278 if (k < boundary_nodes.size() && boundary_nodes[k] == i)
279 {
280 ++k;
281 continue;
282 }
283
284 reduced(j++) = mid(i);
285 }
286 }
287
288 void NLProblem::full_hessian_to_reduced_hessian(const THessian &full, THessian &reduced) const
289 {
290 // POLYFEM_SCOPED_TIMER("\tfull hessian to reduced hessian");
291 THessian mid = full;
292
293 if (periodic_bc_)
294 periodic_bc_->full_to_periodic(mid);
295
296 if (current_size() < full_size())
297 utils::full_to_reduced_matrix(mid.rows(), mid.rows() - boundary_nodes_.size(), boundary_nodes_, mid, reduced);
298 else
299 reduced = mid;
300 }
301} // namespace polyfem::solver
double val
Definition Assembler.cpp:86
int x
void set_bc(const std::vector< mesh::LocalBoundary > &local_boundary, const std::vector< int > &bounday_nodes, const int resolution, const std::vector< mesh::LocalBoundary > &local_neumann_boundary, Eigen::MatrixXd &rhs, const Eigen::MatrixXd &displacement=Eigen::MatrixXd(), const double t=1) const
virtual double max_step_size(const TVector &x0, const TVector &x1) override
virtual void init_lagging(const TVector &x)
virtual void hessian(const TVector &x, THessian &hessian) override
virtual bool is_step_collision_free(const TVector &x0, const TVector &x1)
std::vector< std::shared_ptr< Form > > forms_
virtual void post_step(const polysolve::nonlinear::PostStepData &data) override
virtual void update_lagging(const TVector &x, const int iter_num)
virtual bool is_step_valid(const TVector &x0, const TVector &x1) override
virtual double value(const TVector &x) override
virtual void solution_changed(const TVector &new_x) override
virtual void gradient(const TVector &x, TVector &gradv) override
virtual void line_search_begin(const TVector &x0, const TVector &x1) override
const int full_size_
Size of the full problem.
Definition NLProblem.hpp:72
void line_search_begin(const TVector &x0, const TVector &x1) override
Definition NLProblem.cpp:80
void full_to_reduced_aux_grad(const std::vector< int > &boundary_nodes, const int full_size, const int reduced_size, const FullMat &full, ReducedMat &reduced) const
virtual bool is_step_valid(const TVector &x0, const TVector &x1) override
Definition NLProblem.cpp:90
NLProblem(const int full_size, const std::vector< int > &boundary_nodes, const std::vector< std::shared_ptr< Form > > &forms)
Definition NLProblem.cpp:21
virtual void post_step(const polysolve::nonlinear::PostStepData &data) override
virtual TVector full_to_reduced_grad(const TVector &full) const
const std::vector< mesh::LocalBoundary > * local_boundary_
Definition NLProblem.hpp:92
const assembler::RhsAssembler * rhs_assembler_
Definition NLProblem.hpp:91
virtual TVector full_to_reduced(const TVector &full) const
virtual void update_quantities(const double t, const TVector &x)
Definition NLProblem.cpp:72
virtual void gradient(const TVector &x, TVector &gradv) override
void reduced_to_full_aux(const std::vector< int > &boundary_nodes, const int full_size, const int reduced_size, const ReducedMat &reduced, const Eigen::MatrixXd &rhs, FullMat &full) const
void init_lagging(const TVector &x) override
Definition NLProblem.cpp:62
const std::vector< int > full_boundary_nodes_
Definition NLProblem.hpp:69
virtual bool is_step_collision_free(const TVector &x0, const TVector &x1) override
Definition NLProblem.cpp:95
virtual TVector reduced_to_full(const TVector &reduced) const
void full_to_reduced_aux(const std::vector< int > &boundary_nodes, const int full_size, const int reduced_size, const FullMat &full, ReducedMat &reduced) const
void update_lagging(const TVector &x, const int iter_num) override
Definition NLProblem.cpp:67
virtual Eigen::MatrixXd boundary_values() const
virtual void full_hessian_to_reduced_hessian(const THessian &full, THessian &reduced) const
virtual double value(const TVector &x) override
virtual double max_step_size(const TVector &x0, const TVector &x1) override
Definition NLProblem.cpp:85
std::shared_ptr< utils::PeriodicBoundary > periodic_bc_
Definition NLProblem.hpp:75
virtual void hessian(const TVector &x, THessian &hessian) override
void solution_changed(const TVector &new_x) override
void set_apply_DBC(const TVector &x, const bool val)
const std::vector< int > boundary_nodes_
Definition NLProblem.hpp:70
void full_to_reduced_matrix(const int full_size, const int reduced_size, const std::vector< int > &removed_vars, const StiffnessMatrix &full, StiffnessMatrix &reduced)
Map a full size matrix to a reduced one by dropping rows and columns.