27 template <
int dim,
int spacedim,
class LacType>
31 "LinearViscoElasticity")
33 , constants_0(
"/LinearViscoElasticity/Constants 0",
34 {
"mu",
"lambda",
"eta",
"kappa"},
36 {
"First Lame coefficient",
37 "Second Lame coefficient",
40 , constants_1(
"/LinearViscoElasticity/Constants 1",
41 {
"mu",
"lambda",
"eta",
"kappa"},
43 {
"First Lame coefficient",
44 "Second Lame coefficient",
48 , eulerian_mapping(this->dof_handler,
"/LinearViscoElasticity/Mapping")
50 this->add_parameter(
"Material ids of region 0", material_ids_0);
51 this->add_parameter(
"Material ids of region 1", material_ids_1);
53 this->output_results_call_back.connect([&]() { postprocess(); });
54 this->check_consistency_call_back.connect([&]() {
58 "This code won't produce correct results in transient simulations. "
59 "Run the wave_equation code instead."));
62 auto all_m = material_ids_0;
63 all_m.insert(material_ids_1.begin(), material_ids_1.end());
66 (material_ids_0.size() + material_ids_1.size()),
67 ExcMessage(
"You cannot assign the same material id to two "
68 "different regions"));
78 this->setup_system_call_back.connect([&]() {
80 if (current_cycle == 0)
82 current_displacement_locally_relevant.reinit(
83 this->locally_relevant_solution);
84 current_displacement.reinit(this->solution);
85 eulerian_mapping.initialize(current_displacement,
86 current_displacement_locally_relevant);
90 this->advance_time_call_back.connect(
91 [&](
const auto &t,
const auto &dt,
const auto &n) {
92 this->current_time = t;
94 this->current_cycle = n;
97 this->add_data_vector.connect([&](
auto &d) {
98 d.add_data_vector(current_displacement_locally_relevant,
101 dealii::DataOut<dim, spacedim>::type_dof_data);
107 template <
int dim,
int spacedim,
class LacType>
114 this->
triangulation, this->finite_element().tensor_degree() + 1);
122 this->finite_element(),
127 CopyData copy(this->finite_element().n_dofs_per_cell());
132 for (
const auto &cell : this->dof_handler.active_cell_iterators())
133 if (cell->is_locally_owned())
135 auto &cell_matrix = copy.matrices[0];
136 auto &cell_rhs = copy.vectors[0];
138 cell->get_dof_indices(copy.local_dof_indices[0]);
140 const auto &fe_values = scratch.reinit(cell);
141 const auto &mapped_fe_values = mapped_scratch.reinit(cell);
146 scratch.extract_local_dof_values(
147 "Wn", this->current_displacement_locally_relevant);
148 const auto &div_Wn = scratch.get_divergences(
"Wn", displacement);
150 scratch.get_symmetric_gradients(
"Wn", displacement);
153 (material_ids_0.find(cell->material_id()) != material_ids_0.end()) ?
157 static const auto identity = unit_symmetric_tensor<spacedim>();
159 for (
const unsigned int q_index :
160 fe_values.quadrature_point_indices())
161 for (
const unsigned int i : fe_values.dof_indices())
163 const auto x = mapped_fe_values.quadrature_point(q_index);
167 fe_values[displacement].symmetric_gradient(i, q_index);
171 mapped_fe_values[displacement].symmetric_gradient(i, q_index);
173 for (
const unsigned int j : fe_values.dof_indices())
177 fe_values[displacement].symmetric_gradient(j, q_index);
179 fe_values[displacement].divergence(j, q_index);
181 const auto P_el = this->dt * 2 * c[
"mu"] * eps_W +
185 mapped_fe_values[displacement].symmetric_gradient(
189 mapped_fe_values[displacement].divergence(j, q_index);
191 const auto sigma_vis =
192 2 * c[
"eta"] * eps_u + c[
"kappa"] * div_u *
identity;
195 (scalar_product(sigma_vis, eps_v) *
196 mapped_fe_values.JxW(q_index) +
197 scalar_product(P_el, eps_V) *
198 fe_values.JxW(q_index));
201 const auto Pn = 2 * c[
"mu"] * eps_Wn[q_index] +
202 c[
"lambda"] * div_Wn[q_index] *
identity;
205 (-scalar_product(Pn, eps_V) * fe_values.JxW(q_index) +
206 mapped_fe_values.shape_value(i, q_index) *
207 this->forcing_term.value(x,
208 this->finite_element()
209 .system_to_component_index(i)
211 fe_values.JxW(q_index));
213 this->constraints.distribute_local_to_global(
216 copy.local_dof_indices[0],
226 template <
int dim,
int spacedim,
class LacType>
231 const auto A = linear_operator<VectorType>(this->matrix.block(0, 0));
232 this->preconditioner.initialize(this->matrix.block(0, 0));
234 this->solution.block(0) = Ainv * this->rhs.block(0);
235 this->constraints.distribute(this->solution);
236 this->locally_relevant_solution = this->solution;
237 current_displacement.sadd(1.0, dt, this->solution);
238 current_displacement_locally_relevant = current_displacement;
243 template <
int dim,
int spacedim,
class LacType>
250 this->
triangulation, this->finite_element().tensor_degree() + 1);
257 this->finite_element(),
262 static std::ofstream outfile(
"visco_elastic_energies.txt");
263 if (current_cycle == 0)
265 <<
"# t \t E_pot[0] \t E_pot[1] \t Diss[0] \t Diss[1] \t Ext[0] \t Ext[1]"
269 std::vector<double> potential_energy(2, 0.0);
270 std::vector<double> dissipation(2, 0.0);
271 std::vector<double> external_energy(2, 0.0);
273 for (
const auto &cell : this->dof_handler.active_cell_iterators())
274 if (cell->is_locally_owned())
276 const auto &fe_values = scratch.reinit(cell);
277 const auto &mapped_fe_values = mapped_scratch.reinit(cell);
279 scratch.extract_local_dof_values(
280 "Wn", this->current_displacement_locally_relevant);
281 mapped_scratch.extract_local_dof_values(
282 "Un", this->locally_relevant_solution);
284 const auto &div_Wn = scratch.get_divergences(
"Wn", displacement);
286 scratch.get_symmetric_gradients(
"Wn", displacement);
289 const auto &un = mapped_scratch.get_values(
"Un", displacement);
291 mapped_scratch.get_divergences(
"Un", displacement);
293 mapped_scratch.get_symmetric_gradients(
"Un", displacement);
296 material_ids_0.find(cell->material_id()) != material_ids_0.end() ?
301 (
id == 0 ? constants_0 : constants_1);
303 for (
const unsigned int q_index :
304 fe_values.quadrature_point_indices())
306 potential_energy[id] +=
307 c[
"mu"] * scalar_product(eps_Wn[q_index], eps_Wn[q_index]) +
308 0.5 * c[
"lambda"] * div_Wn[q_index] * div_Wn[q_index] *
309 fe_values.JxW(q_index);
312 c[
"eta"] * scalar_product(eps_un[q_index], eps_un[q_index]) +
313 0.5 * c[
"kappa"] * div_un[q_index] * div_un[q_index] *
314 mapped_fe_values.JxW(q_index);
316 for (
unsigned int i = 0; i < spacedim; ++i)
317 external_energy[
id] +=
319 this->forcing_term.value(
320 mapped_fe_values.quadrature_point(q_index), i) *
321 mapped_fe_values.JxW(q_index);
327 this->mpi_communicator,
330 this->mpi_communicator,
333 this->mpi_communicator,
336 outfile << current_time <<
" \t " << potential_energy[0] <<
" \t "
337 << potential_energy[1] <<
" \t " << dissipation[0] <<
" \t "
338 << dissipation[1] <<
" \t "
339 << external_energy[0] + external_energy[1] << std::endl;
Construct a LinearProblem.
typename LinearProblem< dim, spacedim, LacType >::CopyData CopyData
typename LinearProblem< dim, spacedim, LacType >::ScratchData ScratchData
virtual void solve() override
Make sure we initialize the right type of linear solver.
void postprocess()
Compute energy integrals.
virtual void assemble_system() override
Explicitly assemble the LinearViscoElasticity problem.
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
T sum(const T &t, const MPI_Comm mpi_communicator)
PDEs::LinearViscoElasticity< dim, spacedim, LAC::LATrilinos > LinearViscoElasticity
We collect in this namespace all PDEs that are relevant to Fluid Structure Interaction Problems.
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation