PolyFEM
Loading...
Searching...
No Matches
FSIInterfaceForm.cpp
Go to the documentation of this file.
2
3#include <cassert>
4
5namespace polyfem::solver
6{
7 namespace
8 {
9 void append_block(
10 const StiffnessMatrix &block,
11 const int row_offset,
12 const int col_offset,
13 const double scale,
14 std::vector<Eigen::Triplet<double>> &entries)
15 {
16 for (int k = 0; k < block.outerSize(); ++k)
17 for (StiffnessMatrix::InnerIterator it(block, k); it; ++it)
18 if (it.value() != 0)
19 entries.emplace_back(
20 row_offset + it.row(), col_offset + it.col(), scale * it.value());
21 }
22 } // namespace
23
25 const int total_size,
26 const int velocity_offset,
27 const int mesh_displacement_offset,
28 const int solid_displacement_offset,
29 const int fluid_multiplier_offset,
30 const int mesh_multiplier_offset,
31 StiffnessMatrix fluid_velocity_trace,
32 StiffnessMatrix fluid_solid_trace,
33 StiffnessMatrix mesh_trace,
34 StiffnessMatrix mesh_solid_trace,
35 const time_integrator::ImplicitTimeIntegrator &fluid_integrator,
36 const time_integrator::ImplicitTimeIntegrator &solid_integrator)
37 : total_size_(total_size),
38 velocity_offset_(velocity_offset),
39 mesh_displacement_offset_(mesh_displacement_offset),
40 solid_displacement_offset_(solid_displacement_offset),
41 fluid_multiplier_offset_(fluid_multiplier_offset),
42 mesh_multiplier_offset_(mesh_multiplier_offset),
43 fluid_velocity_trace_(std::move(fluid_velocity_trace)),
44 fluid_solid_trace_(std::move(fluid_solid_trace)),
45 mesh_trace_(std::move(mesh_trace)),
46 mesh_solid_trace_(std::move(mesh_solid_trace)),
47 fluid_multiplier_mass_(make_multiplier_mass(fluid_velocity_trace_)),
48 mesh_multiplier_mass_(make_multiplier_mass(mesh_trace_)),
49 fluid_integrator_(fluid_integrator),
50 solid_integrator_(solid_integrator)
51 {
52 assert(total_size_ > 0);
53 assert(fluid_velocity_trace_.rows() == fluid_solid_trace_.rows());
54 assert(mesh_trace_.rows() == mesh_solid_trace_.rows());
55 assert(fluid_solid_trace_.cols() == mesh_solid_trace_.cols());
58 }
59
61 {
62 Eigen::VectorXd row_mass = Eigen::VectorXd::Zero(trace.rows());
63 for (int k = 0; k < trace.outerSize(); ++k)
64 for (StiffnessMatrix::InnerIterator it(trace, k); it; ++it)
65 row_mass(it.row()) += std::abs(it.value());
66 std::vector<Eigen::Triplet<double>> entries;
67 entries.reserve(trace.rows());
68 for (int row = 0; row < trace.rows(); ++row)
69 entries.emplace_back(row, row, std::max(row_mass(row), 1e-12));
70 StiffnessMatrix result(trace.rows(), trace.rows());
71 result.setFromTriplets(entries.begin(), entries.end());
72 return result;
73 }
74
75 double FSIInterfaceForm::value_unweighted(const Eigen::VectorXd &x) const
76 {
77 Eigen::VectorXd residual;
79 return residual.squaredNorm();
80 }
81
83 const Eigen::VectorXd &velocity, const Eigen::VectorXd &solid_velocity) const
84 {
85 assert(velocity.size() == fluid_velocity_trace_.cols());
86 assert(solid_velocity.size() == fluid_solid_trace_.cols());
87 return fluid_velocity_trace_ * velocity - fluid_solid_trace_ * solid_velocity;
88 }
89
91 const Eigen::VectorXd &mesh_displacement,
92 const Eigen::VectorXd &solid_displacement) const
93 {
94 assert(mesh_displacement.size() == mesh_trace_.cols());
95 assert(solid_displacement.size() == mesh_solid_trace_.cols());
96 return mesh_trace_ * mesh_displacement - mesh_solid_trace_ * solid_displacement;
97 }
98
100 const Eigen::VectorXd &x, Eigen::VectorXd &residual) const
101 {
102 assert(x.size() == total_size_);
103 const int velocity_size = fluid_velocity_trace_.cols();
104 const int mesh_size = mesh_trace_.cols();
105 const int solid_size = fluid_solid_trace_.cols();
106 const Eigen::VectorXd velocity = x.segment(velocity_offset_, velocity_size);
107 const Eigen::VectorXd mesh_displacement = x.segment(mesh_displacement_offset_, mesh_size);
108 const Eigen::VectorXd solid_displacement = x.segment(solid_displacement_offset_, solid_size);
109 const Eigen::VectorXd fluid_multiplier = x.segment(fluid_multiplier_offset_, fluid_multiplier_size());
110 const Eigen::VectorXd mesh_multiplier = x.segment(mesh_multiplier_offset_, mesh_multiplier_size());
111 const Eigen::VectorXd solid_velocity = solid_integrator_.compute_velocity(solid_displacement);
112
113 residual = Eigen::VectorXd::Zero(total_size_);
114 residual.segment(velocity_offset_, velocity_size) +=
115 fluid_integrator_.acceleration_scaling() * fluid_velocity_trace_.transpose() * fluid_multiplier;
116 residual.segment(solid_displacement_offset_, solid_size) -=
117 solid_integrator_.acceleration_scaling() * fluid_solid_trace_.transpose() * fluid_multiplier;
119 physical_constraint(velocity, solid_velocity);
120
121 residual.segment(mesh_displacement_offset_, mesh_size) += mesh_trace_.transpose() * mesh_multiplier;
122 residual.segment(mesh_multiplier_offset_, mesh_multiplier_size()) =
123 mesh_constraint(mesh_displacement, solid_displacement);
124 }
125
127 const Eigen::VectorXd &, StiffnessMatrix &jacobian) const
128 {
129 std::vector<Eigen::Triplet<double>> entries;
130 entries.reserve(
131 2 * fluid_velocity_trace_.nonZeros() + 2 * fluid_solid_trace_.nonZeros()
132 + 2 * mesh_trace_.nonZeros() + mesh_solid_trace_.nonZeros());
143 jacobian.resize(total_size_, total_size_);
144 jacobian.setFromTriplets(entries.begin(), entries.end());
145 jacobian.makeCompressed();
146 }
147} // namespace polyfem::solver
std::vector< Eigen::Triplet< double > > entries
int x
FSIInterfaceForm(int total_size, int velocity_offset, int mesh_displacement_offset, int solid_displacement_offset, int fluid_multiplier_offset, int mesh_multiplier_offset, StiffnessMatrix fluid_velocity_trace, StiffnessMatrix fluid_solid_trace, StiffnessMatrix mesh_trace, StiffnessMatrix mesh_solid_trace, const time_integrator::ImplicitTimeIntegrator &fluid_integrator, const time_integrator::ImplicitTimeIntegrator &solid_integrator)
const StiffnessMatrix fluid_solid_trace_
const time_integrator::ImplicitTimeIntegrator & solid_integrator_
const StiffnessMatrix fluid_velocity_trace_
void first_derivative_unweighted(const Eigen::VectorXd &x, Eigen::VectorXd &residual) const override
Compute the first derivative of the value wrt x.
Eigen::VectorXd physical_constraint(const Eigen::VectorXd &velocity, const Eigen::VectorXd &solid_velocity) const
double value_unweighted(const Eigen::VectorXd &x) const override
Compute the value of the form.
Eigen::VectorXd mesh_constraint(const Eigen::VectorXd &mesh_displacement, const Eigen::VectorXd &solid_displacement) const
const time_integrator::ImplicitTimeIntegrator & fluid_integrator_
static StiffnessMatrix make_multiplier_mass(const StiffnessMatrix &trace)
void second_derivative_unweighted(const Eigen::VectorXd &x, StiffnessMatrix &jacobian) const override
Compute the second derivative of the value wrt x.
const StiffnessMatrix mesh_solid_trace_
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.
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix
Definition Types.hpp:24