PolyFEM
Loading...
Searching...
No Matches
NavierStokesFSIForm.cpp
Go to the documentation of this file.
2
4
5#include <algorithm>
6#include <cassert>
7
8namespace polyfem::solver
9{
10 namespace
11 {
12 bool same_quadrature(const quadrature::Quadrature &a, const quadrature::Quadrature &b)
13 {
14 return a.points.rows() == b.points.rows()
15 && a.points.cols() == b.points.cols()
16 && a.weights.size() == b.weights.size()
17 && (a.points - b.points).norm() < 1e-14
18 && (a.weights - b.weights).norm() < 1e-14;
19 }
20 } // namespace
21
23 const int total_size,
24 const int n_velocity_bases,
25 const int n_pressure_bases,
26 const int n_mesh_displacement_bases,
27 const int multiplier_offset,
28 const int dim,
29 const std::vector<basis::ElementBases> &pressure_bases,
30 const std::vector<basis::ElementBases> &mesh_displacement_bases,
31 const std::vector<basis::ElementBases> &geom_bases,
32 const assembler::AssemblyValsCache &pressure_cache,
33 const assembler::AssemblyValsCache &mesh_displacement_cache,
34 const bool is_volume)
35 : total_size_(total_size),
36 dim_(dim),
37 n_pressure_bases_(n_pressure_bases),
38 n_mesh_displacement_bases_(n_mesh_displacement_bases),
39 pressure_offset_(n_velocity_bases * dim),
40 mesh_displacement_offset_(pressure_offset_ + n_pressure_bases),
41 multiplier_offset_(multiplier_offset),
42 pressure_bases_(pressure_bases),
43 mesh_displacement_bases_(mesh_displacement_bases),
44 geom_bases_(geom_bases),
45 pressure_cache_(pressure_cache),
46 mesh_displacement_cache_(mesh_displacement_cache),
47 is_volume_(is_volume)
48 {
49 assert(dim_ == 2 || dim_ == 3);
50 assert(n_pressure_bases_ > 0);
52 assert(multiplier_offset_ >= mesh_displacement_offset_ + n_mesh_displacement_bases * dim);
53 assert(total_size_ == multiplier_offset_ + 1);
54 assert(pressure_bases_.size() == mesh_displacement_bases_.size());
55 assert(pressure_bases_.size() == geom_bases_.size());
56 }
57
58 double NavierStokesFSIAveragePressureForm::value_unweighted(const Eigen::VectorXd &) const
59 {
60 log_and_throw_error("NavierStokesFSIAveragePressureForm is a residual form and has no value()");
61 }
62
64 const Eigen::VectorXd &x,
65 Eigen::VectorXd &weights,
66 Eigen::MatrixXd &weight_derivative) const
67 {
68 assert(x.size() == total_size_);
69 const int mesh_ndof = n_mesh_displacement_bases_ * dim_;
70 weights = Eigen::VectorXd::Zero(n_pressure_bases_);
71 weight_derivative = Eigen::MatrixXd::Zero(n_pressure_bases_, mesh_ndof);
72 Eigen::VectorXd volume_derivative = Eigen::VectorXd::Zero(mesh_ndof);
73 double volume = 0;
74
75 for (int e = 0; e < int(geom_bases_.size()); ++e)
76 {
77 assembler::ElementAssemblyValues pressure_vals, displacement_vals;
80
82 pressure_vals.quadrature.weights.size() >= displacement_vals.quadrature.weights.size()
83 ? pressure_vals.quadrature
84 : displacement_vals.quadrature;
85 if (!same_quadrature(pressure_vals.quadrature, quadrature))
86 {
87 pressure_vals.compute(e, is_volume_, quadrature.points, pressure_bases_[e], geom_bases_[e]);
88 pressure_vals.quadrature = quadrature;
89 }
90 if (!same_quadrature(displacement_vals.quadrature, quadrature))
91 {
92 displacement_vals.compute(e, is_volume_, quadrature.points, mesh_displacement_bases_[e], geom_bases_[e]);
93 displacement_vals.quadrature = quadrature;
94 }
95
96 Eigen::VectorXd local_displacement = Eigen::VectorXd::Zero(
97 int(displacement_vals.basis_values.size()) * dim_);
98 for (int a = 0; a < int(displacement_vals.basis_values.size()); ++a)
99 for (int c = 0; c < dim_; ++c)
100 for (const auto &global : displacement_vals.basis_values[a].global)
101 local_displacement(a * dim_ + c) +=
102 global.val * x(mesh_displacement_offset_ + global.index * dim_ + c);
103
104 for (int q = 0; q < quadrature.weights.size(); ++q)
105 {
106 Eigen::MatrixXd F = Eigen::MatrixXd::Identity(dim_, dim_);
107 for (int a = 0; a < int(displacement_vals.basis_values.size()); ++a)
108 {
109 const Eigen::RowVectorXd grad =
110 displacement_vals.basis_values[a].grad.row(q) * displacement_vals.jac_it[q];
111 for (int c = 0; c < dim_; ++c)
112 F.row(c) += local_displacement(a * dim_ + c) * grad;
113 }
114 const double J = F.determinant();
115 assert(J > 0);
116 const Eigen::MatrixXd F_inv = F.inverse();
117 const double reference_weight = pressure_vals.det(q) * quadrature.weights(q);
118 volume += reference_weight * J;
119
120 for (int a = 0; a < int(displacement_vals.basis_values.size()); ++a)
121 {
122 const Eigen::RowVectorXd spatial_grad =
123 displacement_vals.basis_values[a].grad.row(q) * displacement_vals.jac_it[q] * F_inv;
124 for (int c = 0; c < dim_; ++c)
125 {
126 const double local_dJ = J * spatial_grad(c);
127 for (const auto &displacement_global : displacement_vals.basis_values[a].global)
128 {
129 const int displacement_dof = displacement_global.index * dim_ + c;
130 const double dJ = displacement_global.val * local_dJ;
131 volume_derivative(displacement_dof) += reference_weight * dJ;
132 for (int i = 0; i < int(pressure_vals.basis_values.size()); ++i)
133 for (const auto &pressure_global : pressure_vals.basis_values[i].global)
134 weight_derivative(pressure_global.index, displacement_dof) +=
135 pressure_global.val * pressure_vals.basis_values[i].val(q)
136 * reference_weight * dJ;
137 }
138 }
139 }
140
141 for (int i = 0; i < int(pressure_vals.basis_values.size()); ++i)
142 for (const auto &pressure_global : pressure_vals.basis_values[i].global)
143 weights(pressure_global.index) += pressure_global.val
144 * pressure_vals.basis_values[i].val(q) * reference_weight * J;
145 }
146 }
147
148 assert(volume > 0);
149 weight_derivative =
150 (weight_derivative * volume - weights * volume_derivative.transpose()) / (volume * volume);
151 weights /= volume;
152 }
153
155 const Eigen::VectorXd &x, Eigen::VectorXd &residual) const
156 {
157 Eigen::VectorXd weights;
158 Eigen::MatrixXd weight_derivative;
159 compute_constraint(x, weights, weight_derivative);
160 const Eigen::VectorXd pressure = x.segment(pressure_offset_, n_pressure_bases_);
161 const double multiplier = x(multiplier_offset_);
162 residual = Eigen::VectorXd::Zero(total_size_);
163 residual.segment(pressure_offset_, n_pressure_bases_) = multiplier * weights;
164 residual(multiplier_offset_) = weights.dot(pressure);
165 }
166
168 const Eigen::VectorXd &x, StiffnessMatrix &jacobian) const
169 {
170 Eigen::VectorXd weights;
171 Eigen::MatrixXd weight_derivative;
172 compute_constraint(x, weights, weight_derivative);
173 const Eigen::VectorXd pressure = x.segment(pressure_offset_, n_pressure_bases_);
174 const double multiplier = x(multiplier_offset_);
175 std::vector<Eigen::Triplet<double>> entries;
176 entries.reserve(2 * n_pressure_bases_
179 for (int i = 0; i < n_pressure_bases_; ++i)
180 {
181 entries.emplace_back(pressure_offset_ + i, multiplier_offset_, weights(i));
182 entries.emplace_back(multiplier_offset_, pressure_offset_ + i, weights(i));
183 for (int j = 0; j < n_mesh_displacement_bases_ * dim_; ++j)
184 {
185 const double value = weight_derivative(i, j);
186 if (value != 0)
187 entries.emplace_back(pressure_offset_ + i, mesh_displacement_offset_ + j, multiplier * value);
188 }
189 }
190 for (int j = 0; j < n_mesh_displacement_bases_ * dim_; ++j)
191 {
192 const double value = pressure.dot(weight_derivative.col(j));
193 if (value != 0)
195 }
196 jacobian.resize(total_size_, total_size_);
197 jacobian.setFromTriplets(entries.begin(), entries.end());
198 jacobian.makeCompressed();
199 }
200
202 const int total_size,
203 const int n_velocity_bases,
204 const int n_pressure_bases,
205 const int n_mesh_displacement_bases,
206 const std::vector<basis::ElementBases> &velocity_bases,
207 const std::vector<basis::ElementBases> &pressure_bases,
208 const std::vector<basis::ElementBases> &mesh_displacement_bases,
209 const std::vector<basis::ElementBases> &geom_bases,
210 const assembler::AssemblyValsCache &velocity_cache,
211 const assembler::AssemblyValsCache &pressure_cache,
212 const assembler::AssemblyValsCache &mesh_displacement_cache,
213 std::vector<std::shared_ptr<assembler::MultiSpacesNLAssembler>> assemblers,
214 const time_integrator::ImplicitTimeIntegrator *velocity_time_integrator,
215 const time_integrator::ImplicitTimeIntegrator *mesh_displacement_time_integrator,
216 const double t,
217 const double dt,
218 const bool is_volume,
219 BodyForceEvaluator body_force_evaluator)
220 : total_size_(total_size),
221 dim_(assemblers.empty() ? -1 : assemblers.front()->size()),
222 n_bases_({{n_velocity_bases, n_pressure_bases, n_mesh_displacement_bases}}),
223 components_({{dim_, 1, dim_}}),
224 global_offsets_({{0, n_velocity_bases * dim_, n_velocity_bases * dim_ + n_pressure_bases}}),
225 global_sizes_({{n_velocity_bases * dim_, n_pressure_bases, n_mesh_displacement_bases * dim_}}),
226 bases_({{std::cref(velocity_bases), std::cref(pressure_bases), std::cref(mesh_displacement_bases)}}),
227 geom_bases_(geom_bases),
228 caches_({{std::cref(velocity_cache), std::cref(pressure_cache), std::cref(mesh_displacement_cache)}}),
229 assemblers_(std::move(assemblers)),
230 velocity_time_integrator_(velocity_time_integrator),
231 mesh_displacement_time_integrator_(mesh_displacement_time_integrator),
232 t_(t),
233 dt_(dt),
234 is_volume_(is_volume),
235 body_force_evaluator_(std::move(body_force_evaluator))
236 {
237 assert(dim_ == 2 || dim_ == 3);
238 assert(!assemblers_.empty());
239 assert(velocity_bases.size() == pressure_bases.size());
240 assert(velocity_bases.size() == mesh_displacement_bases.size());
241 assert(velocity_bases.size() == geom_bases.size());
242 assert(total_size_ >= global_offsets_[2] + global_sizes_[2]);
243 x_prev_ = Eigen::VectorXd::Zero(total_size_);
244 }
245
247 const int element, SpaceValues &vals, QuadratureVector &da) const
248 {
249 for (int s = 0; s < 3; ++s)
250 caches_[s].get().compute(element, is_volume_, bases_[s].get()[element], geom_bases_[element], vals[s]);
251
252 int selected = 0;
253 for (int s = 1; s < 3; ++s)
254 if (vals[s].quadrature.weights.size() > vals[selected].quadrature.weights.size())
255 selected = s;
256 const quadrature::Quadrature quadrature = vals[selected].quadrature;
257 for (int s = 0; s < 3; ++s)
258 {
259 if (!same_quadrature(vals[s].quadrature, quadrature))
260 {
261 vals[s].compute(element, is_volume_, quadrature.points, bases_[s].get()[element], geom_bases_[element]);
262 vals[s].quadrature = quadrature;
263 }
264 }
265 da = vals[0].det.array() * quadrature.weights.array();
266 }
267
269 const Eigen::VectorXd &x,
271 const int components,
272 const int global_offset) const
273 {
274 Eigen::VectorXd local = Eigen::VectorXd::Zero(int(vals.basis_values.size()) * components);
275 for (int i = 0; i < int(vals.basis_values.size()); ++i)
276 for (int c = 0; c < components; ++c)
277 for (const auto &global : vals.basis_values[i].global)
278 local(i * components + c) += global.val * x(global_offset + global.index * components + c);
279 return local;
280 }
281
283 const SpaceValues &vals,
284 const LocalCoefficients &x,
285 const LocalCoefficients &x_prev,
286 const QuadratureVector &da,
287 const Eigen::VectorXd &velocity_tilde,
288 const Eigen::VectorXd &mesh_velocity) const
289 {
291 Data::Values value_refs = {std::cref(vals[0]), std::cref(vals[1]), std::cref(vals[2])};
292 Data::Coefficients x_refs = {std::cref(x[0]), std::cref(x[1]), std::cref(x[2])};
293 Data::Coefficients prev_refs = {std::cref(x_prev[0]), std::cref(x_prev[1]), std::cref(x_prev[2])};
294 return Data(
295 std::move(value_refs), std::move(x_refs), std::move(prev_refs),
296 t_, dt_, da, velocity_tilde, mesh_velocity,
299 velocity_time_integrator_ != nullptr,
301 }
302
304 const SpaceValues &vals, const Eigen::VectorXd &local, Eigen::VectorXd &global) const
305 {
306 int local_offset = 0;
307 for (int s = 0; s < 3; ++s)
308 {
309 for (int i = 0; i < int(vals[s].basis_values.size()); ++i)
310 for (int c = 0; c < components_[s]; ++c)
311 for (const auto &mapping : vals[s].basis_values[i].global)
312 global(global_offsets_[s] + mapping.index * components_[s] + c) += mapping.val * local(local_offset + i * components_[s] + c);
313 local_offset += int(vals[s].basis_values.size()) * components_[s];
314 }
315 }
316
318 const SpaceValues &vals,
319 const int row_space,
320 const int col_space,
321 const Eigen::MatrixXd &local,
322 std::vector<Eigen::Triplet<double>> &entries) const
323 {
324 const int row_components = components_[row_space];
325 const int col_components = components_[col_space];
326 assert(local.rows() == int(vals[row_space].basis_values.size()) * row_components);
327 assert(local.cols() == int(vals[col_space].basis_values.size()) * col_components);
328 for (int i = 0; i < int(vals[row_space].basis_values.size()); ++i)
329 for (int rc = 0; rc < row_components; ++rc)
330 for (int j = 0; j < int(vals[col_space].basis_values.size()); ++j)
331 for (int cc = 0; cc < col_components; ++cc)
332 {
333 const double value = local(i * row_components + rc, j * col_components + cc);
334 if (value == 0)
335 continue;
336 for (const auto &row : vals[row_space].basis_values[i].global)
337 for (const auto &col : vals[col_space].basis_values[j].global)
338 entries.emplace_back(
339 global_offsets_[row_space] + row.index * row_components + rc,
340 global_offsets_[col_space] + col.index * col_components + cc,
341 row.val * col.val * value);
342 }
343 }
344
346 const Eigen::VectorXd &x, Eigen::VectorXd &residual) const
347 {
348 assert(x.size() == total_size_);
349 residual = Eigen::VectorXd::Zero(total_size_);
350
351 Eigen::VectorXd velocity_tilde = Eigen::VectorXd::Zero(velocity_ndof());
353 {
354 velocity_tilde = velocity_time_integrator_->x_tilde();
356 velocity_tilde_updater_(t_, x.segment(global_offsets_[0], global_sizes_[0]), velocity_tilde);
357 }
358 Eigen::VectorXd mesh_velocity = Eigen::VectorXd::Zero(mesh_displacement_ndof());
361 x.segment(global_offsets_[2], global_sizes_[2]));
362
363 for (int e = 0; e < int(geom_bases_.size()); ++e)
364 {
368 LocalCoefficients local_x, local_prev;
369 for (int s = 0; s < 3; ++s)
370 {
371 local_x[s] = gather(x, vals[s], components_[s], global_offsets_[s]);
372 local_prev[s] = gather(x_prev_, vals[s], components_[s], global_offsets_[s]);
373 }
374 const Eigen::VectorXd local_velocity_tilde = gather(velocity_tilde, vals[0], dim_, 0);
375 const Eigen::VectorXd local_mesh_velocity = gather(mesh_velocity, vals[2], dim_, 0);
376 const auto data = make_data(vals, local_x, local_prev, da, local_velocity_tilde, local_mesh_velocity);
377 Eigen::VectorXd local_residual = Eigen::VectorXd::Zero(
378 local_x[0].size() + local_x[1].size() + local_x[2].size());
379 for (const auto &assembler : assemblers_)
380 local_residual += assembler->assemble_gradient(data);
381 scatter_local_residual(vals, local_residual, residual);
382 }
383 }
384
385 double NavierStokesFSIForm::value_unweighted(const Eigen::VectorXd &x) const
386 {
387 Eigen::VectorXd residual;
389 return residual.squaredNorm();
390 }
391
393 const Eigen::VectorXd &x, StiffnessMatrix &jacobian) const
394 {
395 assert(x.size() == total_size_);
396 std::vector<Eigen::Triplet<double>> entries;
397
398 Eigen::VectorXd velocity_tilde = Eigen::VectorXd::Zero(velocity_ndof());
400 {
401 velocity_tilde = velocity_time_integrator_->x_tilde();
403 velocity_tilde_updater_(t_, x.segment(global_offsets_[0], global_sizes_[0]), velocity_tilde);
404 }
405 Eigen::VectorXd mesh_velocity = Eigen::VectorXd::Zero(mesh_displacement_ndof());
408 x.segment(global_offsets_[2], global_sizes_[2]));
409
410 for (int e = 0; e < int(geom_bases_.size()); ++e)
411 {
415 LocalCoefficients local_x, local_prev;
416 for (int s = 0; s < 3; ++s)
417 {
418 local_x[s] = gather(x, vals[s], components_[s], global_offsets_[s]);
419 local_prev[s] = gather(x_prev_, vals[s], components_[s], global_offsets_[s]);
420 }
421 const Eigen::VectorXd local_velocity_tilde = gather(velocity_tilde, vals[0], dim_, 0);
422 const Eigen::VectorXd local_mesh_velocity = gather(mesh_velocity, vals[2], dim_, 0);
423 const auto data = make_data(vals, local_x, local_prev, da, local_velocity_tilde, local_mesh_velocity);
424
425 for (const int row_space : {0, 1})
426 for (const int col_space : {0, 1, 2})
427 {
428 Eigen::MatrixXd block = Eigen::MatrixXd::Zero(local_x[row_space].size(), local_x[col_space].size());
429 for (const auto &assembler : assemblers_)
430 block += assembler->assemble_hessian(data, row_space, col_space);
431 scatter_local_block(vals, row_space, col_space, block, entries);
432 }
433 }
434
435 jacobian.resize(total_size_, total_size_);
436 jacobian.setFromTriplets(entries.begin(), entries.end());
437 jacobian.makeCompressed();
438 }
439
440 void NavierStokesFSIForm::update_quantities(const double t, const Eigen::VectorXd &x)
441 {
442 t_ = t;
443 if (x.size() == total_size_)
444 x_prev_ = x;
445 }
446
447 bool NavierStokesFSIForm::has_valid_ale_mapping(const Eigen::VectorXd &x) const
448 {
449 for (int e = 0; e < int(geom_bases_.size()); ++e)
450 {
454 const Eigen::VectorXd local_d = gather(x, vals[2], dim_, global_offsets_[2]);
455 for (int q = 0; q < da.size(); ++q)
456 {
457 Eigen::MatrixXd F = Eigen::MatrixXd::Identity(dim_, dim_);
458 for (int a = 0; a < int(vals[2].basis_values.size()); ++a)
459 {
460 const Eigen::RowVectorXd grad = vals[2].basis_values[a].grad.row(q) * vals[2].jac_it[q];
461 for (int c = 0; c < dim_; ++c)
462 F.row(c) += local_d(a * dim_ + c) * grad;
463 }
464 if (!(F.determinant() > 1e-8))
465 return false;
466 }
467 }
468 return true;
469 }
470
471 bool NavierStokesFSIForm::is_step_valid(const Eigen::VectorXd &, const Eigen::VectorXd &x1) const
472 {
473 return has_valid_ale_mapping(x1);
474 }
475} // namespace polyfem::solver
QuadratureVector da
Definition Assembler.cpp:26
ElementAssemblyValues vals
Definition Assembler.cpp:25
Quadrature quadrature
std::vector< Eigen::Triplet< double > > entries
Eigen::MatrixXd F_inv
double J
std::vector< std::pair< int, double > > weights
int x
Caches basis evaluation and geometric mapping at every element.
void compute(const int el_index, const bool is_volume, const basis::ElementBases &basis, const basis::ElementBases &gbasis, ElementAssemblyValues &vals) const
retrieves cached basis evaluation and geometric for the given element if it doesn't exist,...
stores per element basis values at given quadrature points and geometric mapping
void compute(const int el_index, const bool is_volume, const Eigen::MatrixXd &pts, const basis::ElementBases &basis, const basis::ElementBases &gbasis)
computes the per element values at the local (ref el) points (pts) sets basis_values,...
std::vector< Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 3, 3 > > jac_it
virtual double value(const Eigen::VectorXd &x) const
Compute the value of the form multiplied with the weigth.
Definition Form.hpp:26
bool project_to_psd_
If true, the form's second derivative is projected to be positive semidefinite.
Definition Form.hpp:147
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
const std::vector< basis::ElementBases > & mesh_displacement_bases_
const assembler::AssemblyValsCache & pressure_cache_
void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &residual) const override
Compute the first derivative of the value wrt x.
void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &jacobian) const override
Compute the second derivative of the value wrt x.
const std::vector< basis::ElementBases > & geom_bases_
void compute_constraint(const Eigen::VectorXd &x, Eigen::VectorXd &weights, Eigen::MatrixXd &weight_derivative) const
const assembler::AssemblyValsCache & mesh_displacement_cache_
const std::vector< basis::ElementBases > & pressure_bases_
NavierStokesFSIAveragePressureForm(int total_size, int n_velocity_bases, int n_pressure_bases, int n_mesh_displacement_bases, int multiplier_offset, int dim, const std::vector< basis::ElementBases > &pressure_bases, const std::vector< basis::ElementBases > &mesh_displacement_bases, const std::vector< basis::ElementBases > &geom_bases, const assembler::AssemblyValsCache &pressure_cache, const assembler::AssemblyValsCache &mesh_displacement_cache, bool is_volume)
bool is_step_valid(const Eigen::VectorXd &x0, const Eigen::VectorXd &x1) const override
Determine if a step from solution x0 to solution x1 is allowed.
void update_quantities(double t, const Eigen::VectorXd &x) override
Update time-dependent fields.
const time_integrator::ImplicitTimeIntegrator * mesh_displacement_time_integrator_
assembler::NavierStokesFSIAssemblerData make_data(const SpaceValues &vals, const LocalCoefficients &x, const LocalCoefficients &x_prev, const QuadratureVector &da, const Eigen::VectorXd &velocity_tilde, const Eigen::VectorXd &mesh_velocity) const
void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &residual) const override
Compute the first derivative of the value wrt x.
std::array< Eigen::VectorXd, 3 > LocalCoefficients
NavierStokesFSIForm(int total_size, int n_velocity_bases, int n_pressure_bases, int n_mesh_displacement_bases, const std::vector< basis::ElementBases > &velocity_bases, const std::vector< basis::ElementBases > &pressure_bases, const std::vector< basis::ElementBases > &mesh_displacement_bases, const std::vector< basis::ElementBases > &geom_bases, const assembler::AssemblyValsCache &velocity_cache, const assembler::AssemblyValsCache &pressure_cache, const assembler::AssemblyValsCache &mesh_displacement_cache, std::vector< std::shared_ptr< assembler::MultiSpacesNLAssembler > > assemblers, const time_integrator::ImplicitTimeIntegrator *velocity_time_integrator, const time_integrator::ImplicitTimeIntegrator *mesh_displacement_time_integrator, double t, double dt, bool is_volume, BodyForceEvaluator body_force_evaluator={})
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
bool has_valid_ale_mapping(const Eigen::VectorXd &x) const
const std::vector< std::shared_ptr< assembler::MultiSpacesNLAssembler > > assemblers_
const std::vector< basis::ElementBases > & geom_bases_
const std::array< std::reference_wrapper< const std::vector< basis::ElementBases > >, 3 > bases_
const std::array< std::reference_wrapper< const assembler::AssemblyValsCache >, 3 > caches_
void compute_element_values(int element, SpaceValues &vals, QuadratureVector &da) const
void scatter_local_residual(const SpaceValues &vals, const Eigen::VectorXd &local, Eigen::VectorXd &global) const
Eigen::VectorXd gather(const Eigen::VectorXd &x, const assembler::ElementAssemblyValues &vals, int components, int global_offset) const
void scatter_local_block(const SpaceValues &vals, int row_space, int col_space, const Eigen::MatrixXd &local, std::vector< Eigen::Triplet< double > > &entries) const
std::array< assembler::ElementAssemblyValues, 3 > SpaceValues
const time_integrator::ImplicitTimeIntegrator * velocity_time_integrator_
assembler::NavierStokesFSIAssemblerData::BodyForceEvaluator BodyForceEvaluator
void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &jacobian) const override
Compute the second derivative of the value wrt x.
Implicit time integrator of a second order ODE (equivently a system of coupled first order ODEs).
virtual Eigen::VectorXd compute_velocity(const Eigen::VectorXd &x) const =0
Compute the current velocity given the current solution and using the stored previous solution(s).
virtual double dv_dx(const unsigned prev_ti=0) const =0
Compute the derivative of the velocity with respect to the solution.
virtual double acceleration_scaling() const =0
Compute the acceleration scaling used to scale forces when integrating a second order ODE.
virtual Eigen::VectorXd x_tilde() const =0
Compute the predicted solution to be used in the inertia term .
int norm
Definition p_bases.py:265
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, MAX_QUAD_POINTS, 1 > QuadratureVector
Definition Types.hpp:17
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24