pi-DoMUS: Parallel Deal.II MUltiphysics Solver
ale_navier_stokes.h
Go to the documentation of this file.
1 
5 #ifndef _dynamic_navier_stokes_h_
6 #define _dynamic_navier_stokes_h_
7 
9 
10 #include <deal.II/fe/fe_values.h>
15 
19 
20 #include <deal.II/lac/solver_cg.h>
22 
23 #include <deal2lkit/fe_values_cache.h>
24 #include <deal2lkit/parsed_function.h>
25 
26 // for DOFUtilities::inner
27 using namespace DOFUtilities;
28 
29 template <int dim>
30 class ALENavierStokes : public NonConservativeInterface<dim,dim,dim+dim+1, ALENavierStokes<dim> >
31 {
32 public:
33  typedef FEValuesCache<dim,dim> Scratch;
34  typedef Assembly::CopyData::piDoMUSPreconditioner<dim,dim> CopyPreconditioner;
35  typedef Assembly::CopyData::piDoMUSSystem<dim,dim> CopySystem;
38 
39  /* specific and useful functions for this very problem */
41 
42  void declare_parameters (ParameterHandler &prm);
43  void parse_parameters_call_back ();
44 
45  /* these functions MUST have the follwowing names
46  * because they are called by the NonConservativeInterface class
47  */
48 
49  template<typename Number>
50  void preconditioner_residual(const typename DoFHandler<dim>::active_cell_iterator &,
51  Scratch &,
52  CopyPreconditioner &,
53  std::vector<Number> &local_residual) const;
54  template<typename Number>
55  void system_residual(const typename DoFHandler<dim>::active_cell_iterator &,
56  Scratch &,
57  CopySystem &,
58  std::vector<Number> &local_residual) const;
59 
60 
61 
62  virtual void compute_system_operators(const DoFHandler<dim> &,
65  const std::vector<shared_ptr<MAT> >,
67  LinearOperator<VEC> &) const;
68 
69  template<typename Number>
71  Scratch &,
72  CopyPreconditioner &,
73  std::vector<std::vector<Number> > &) const
74  {};
75 
76 private:
77  double eta;
78  double rho;
79 
80  mutable shared_ptr<TrilinosWrappers::PreconditionJacobi> P00_preconditioner;
81  mutable shared_ptr<TrilinosWrappers::PreconditionAMG> P11_preconditioner;
82  mutable shared_ptr<TrilinosWrappers::PreconditionJacobi> P22_preconditioner;
83 };
84 
85 template<int dim>
87  NonConservativeInterface<dim,dim,dim+dim+1,ALENavierStokes<dim> >("ALE Navier Stokes",
88  "FESystem[FE_Q(2)^d-FE_Q(2)^d-FE_Q(1)]",
89  "d,d,u,u,p",
90  "1,0,0; 1,1,1; 0,0,1",
91  "1,0,0; 0,1,0; 0,0,1",
92  "1,1,0")
93 {};
94 
95 
96 template <int dim>
97 template<typename Number>
99  Scratch &fe_cache,
100  CopyPreconditioner &data,
101  std::vector<Number> &local_residual) const
102 {
103  Number alpha = this->alpha;
104  fe_cache.reinit(cell);
105 
106  fe_cache.cache_local_solution_vector("solution", *this->solution, alpha);
107  fe_cache.cache_local_solution_vector("solution_dot", *this->solution_dot, alpha);
108 
109  this->fix_solution_dot_derivative(fe_cache, alpha);
110 
111  const FEValuesExtractors::Vector velocity(dim);
112  const FEValuesExtractors::Vector displacement(0);
113  const FEValuesExtractors::Scalar pressure(2*dim);
114 
115  auto &us = fe_cache.get_values( "solution", "u", velocity, alpha);
116  auto &grad_us = fe_cache.get_gradients( "solution", "grad_u", velocity, alpha);
117  auto &us_dot = fe_cache.get_values( "solution_dot", "u_dot", velocity, alpha);
118  auto &grad_ds = fe_cache.get_gradients( "solution", "grad_d", displacement, alpha);
119  auto &ps = fe_cache.get_values( "solution", "p", pressure, alpha);
120 
121  const unsigned int n_q_points = ps.size();
122 
123  // Jacobian:
124  auto &JxW = fe_cache.get_JxW_values();
125 
126  // Init residual to 0
127  for (unsigned int i=0; i<local_residual.size(); ++i)
128  local_residual[i] = 0;
129 
130  auto &fev = fe_cache.get_current_fe_values();
131  for (unsigned int q=0; q<n_q_points; ++q)
132  {
133  for (unsigned int i=0; i<local_residual.size(); ++i)
134  {
135  // test functions:
136  auto v = fev[velocity ].value(i,q);
137  auto grad_v = fev[velocity ].gradient(i,q);
138  auto grad_e = fev[displacement].gradient(i,q);
139  auto m = fev[pressure ].value(i,q);
140 
141  // variables:
142  const Tensor<1, dim, Number> &u = us[q];
143  const Tensor<1, dim, Number> &u_dot = us_dot[q];
144  const Tensor<2, dim, Number> &grad_u = grad_us[q];
145  const Tensor<2, dim, Number> &grad_d = grad_ds[q];
146  const Number &p = ps[q];
147 
148  // compute residual:
149  local_residual[i] += (rho * inner(u_dot,v) +
150  eta * inner(grad_u,grad_v) +
151  inner(grad_d,grad_e) +
152  (1./eta)*p*m)*JxW[q];
153  }
154  }
155 }
156 
157 template <int dim>
158 template<typename Number>
160  Scratch &fe_cache,
161  CopySystem &data,
162  std::vector<Number> &local_residual) const
163 {
164  Number alpha = this->alpha;
165  fe_cache.reinit(cell);
166 
167  fe_cache.cache_local_solution_vector("solution", *this->solution, alpha);
168  fe_cache.cache_local_solution_vector("solution_dot", *this->solution_dot, alpha);
169 
170  this->fix_solution_dot_derivative(fe_cache, alpha);
171 
172  const FEValuesExtractors::Vector velocity(dim);
173  const FEValuesExtractors::Vector displacement(0);
174  const FEValuesExtractors::Scalar pressure(2*dim);
175 
176 
177  // velocity:
178  auto &us = fe_cache.get_values( "solution", "u", velocity, alpha);
179  auto &grad_us = fe_cache.get_gradients( "solution", "grad_u", velocity, alpha);
180  auto &div_us = fe_cache.get_divergences( "solution", "div_u", velocity, alpha);
181  auto &sym_grad_us = fe_cache.get_symmetric_gradients( "solution", "u", velocity, alpha);
182  auto &us_dot = fe_cache.get_values( "solution_dot", "u_dot", velocity, alpha);
183 
184  // displacement:
185  auto &ds = fe_cache.get_values( "solution", "d", displacement, alpha);
186  auto &grad_ds = fe_cache.get_gradients( "solution", "grad_d", displacement, alpha);
187  auto &div_ds = fe_cache.get_divergences( "solution", "div_d", displacement, alpha);
188  auto &Fs = fe_cache.get_deformation_gradients( "solution", "Fd", displacement, alpha);
189  auto &ds_dot = fe_cache.get_values( "solution_dot", "d_dot", displacement, alpha);
190 
191  // pressure:
192  auto &ps = fe_cache.get_values( "solution", "p", pressure, alpha);
193 
194  // Jacobian:
195  auto &JxW = fe_cache.get_JxW_values();
196 
197  const unsigned int n_q_points = ps.size();
198 
199  // Init residual to 0
200  for (unsigned int i=0; i<local_residual.size(); ++i)
201  local_residual[i] = 0;
202 
203  auto &fev = fe_cache.get_current_fe_values();
204  for (unsigned int q=0; q<n_q_points; ++q)
205  {
206  for (unsigned int i=0; i<local_residual.size(); ++i)
207  {
208  // test functions:
209  // velocity:
210  auto v = fev[velocity ].value(i,q);
211  auto grad_v = fev[velocity ].gradient(i,q);
212  auto div_v = fev[velocity ].divergence(i,q);
213  // displacement:
214  auto grad_e = fev[displacement].gradient(i,q);
215  // pressure:
216  auto m = fev[pressure ].value(i,q);
217 
218  // variables:
219  // velocity:
220  const Tensor<1, dim, Number> &u = us[q];
221  const Number &div_u = div_us[q];
222  const Tensor<1, dim, Number> &u_dot = us_dot[q];
223  const Tensor<2, dim, Number> &grad_u = grad_us[q];
224  const Tensor <2, dim, Number> &sym_grad_u = sym_grad_us[q];
225  // displacement
226  const Tensor<1, dim, Number> &d = ds[q];
227  const Tensor<1, dim, Number> &d_dot = ds_dot[q];
228  const Tensor<2, dim, Number> &grad_d = grad_ds[q];
229  const Number &div_d = div_ds[q];
230  const Tensor <2, dim, Number> &F = Fs[q];
231  Number J = determinant(F);
232  const Tensor <2, dim, Number> &F_inv = invert(F);
233  const Tensor <2, dim, Number> &Ft_inv = transpose(F_inv);
234 
235  // pressure:
236  const Number &p = ps[q];
237 
238  // others:
239  auto J_ale = J; // jacobian of ALE transformation
240  // auto div_u_ale = (J_ale * (F_inv * u) );
242  for (unsigned int i = 0; i<dim; ++i)
243  Id[i][i] = p;
244 
245  Number my_rho = rho;
246  const Tensor <2, dim, Number> sigma = - Id + my_rho * ( grad_u * F_inv + ( Ft_inv * transpose(grad_u) ) ) ;
247 
248  local_residual[i] += (
249  // time derivative term
250  rho*inner( u_dot * J_ale , v )
251  //
252  + inner( grad_u * ( F_inv * ( u - d_dot ) ) * J_ale , v )
253  //
254  + inner( J_ale * sigma * Ft_inv, grad_v)
255  // stiffness matrix
256  // + eta*inner(sym_grad_u,grad_v)
257 
258  // "stiffness" od the displacement
259  + eta * inner( grad_d , grad_e )
260  // divergence free constriant
261  - p * m
262  // pressure term
263  - p * div_v
264  )
265  * JxW[q];
266  }
267  }
268 }
269 
270 
271 template <int dim>
273 {
275  this->add_parameter(prm, &eta, "eta [Pa s]", "1.0", Patterns::Double(0.0));
276  this->add_parameter(prm, &rho, "rho [Kg m^-d]", "1.0", Patterns::Double(0.0));
277 }
278 
279 template <int dim>
281 {
283 }
284 
285 
286 template <int dim>
287 void
290  const TrilinosWrappers::BlockSparseMatrix &preconditioner_matrix,
291  const std::vector<shared_ptr<MAT> >,
292  LinearOperator<VEC> &system_op,
293  LinearOperator<VEC> &prec_op) const
294 {
295 
296  std::vector<std::vector<bool> > constant_modes;
297  FEValuesExtractors::Vector velocity_components(dim);
298  DoFTools::extract_constant_modes (dh, dh.get_fe().component_mask(velocity_components),
299  constant_modes);
300 
301  P00_preconditioner.reset (new TrilinosWrappers::PreconditionJacobi());
302  P11_preconditioner.reset (new TrilinosWrappers::PreconditionAMG());
303  P22_preconditioner.reset (new TrilinosWrappers::PreconditionJacobi());
304 
306  Amg_data.constant_modes = constant_modes;
307  Amg_data.elliptic = true;
308  Amg_data.higher_order_elements = true;
309  Amg_data.smoother_sweeps = 2;
310  Amg_data.aggregation_threshold = 0.02;
311 
312  P00_preconditioner ->initialize (preconditioner_matrix.block(0,0));
313  P11_preconditioner ->initialize (preconditioner_matrix.block(1,1), Amg_data);
314  P22_preconditioner ->initialize (preconditioner_matrix.block(2,2));
315 
316  // SYSTEM MATRIX:
317 
318  std::array<std::array<LinearOperator<TrilinosWrappers::MPI::Vector>, 3>, 3> S;
319  for (unsigned int i = 0; i<3; ++i)
320  for (unsigned int j = 0; j<3; ++j)
321  S[i][j] = linear_operator< TrilinosWrappers::MPI::Vector >( matrix.block(i,j) );
322 
323  // S[1][1] = null_operator(S[1][1]); // d v
324  S[0][2] = null_operator(S[0][2]); // d p
325  S[2][0] = null_operator(S[2][0]); // p d
326  S[2][2] = null_operator(S[2][2]); // p p
327 
329  // auto tmp = LinearOperator<TrilinosWrappers::MPI::BlockVector>( S );
330  // system_op = static_cast<LinearOperator<TrilinosWrappers::MPI::BlockVector> &>(tmp);
331  std::array<std::array<LinearOperator<TrilinosWrappers::MPI::Vector>, 3>, 3> P;
332  for (unsigned int i = 0; i<3; ++i)
333  for (unsigned int j = 0; j<3; ++j)
334  P[i][j] = linear_operator< TrilinosWrappers::MPI::Vector >( preconditioner_matrix.block(i,j) );
335  // PRECONDITIONER MATRIX:
336 
337  static ReductionControl solver_control_pre(5000, 1e-8);
338  static SolverCG<TrilinosWrappers::MPI::Vector> solver_CG(solver_control_pre);
339 
340  for (unsigned int i = 0; i<3; ++i)
341  for (unsigned int j = 0; j<3; ++j)
342  if (i!=j)
343  P[i][j] = null_operator< TrilinosWrappers::MPI::Vector >(P[i][j]);
344 
345  // P[0][0] = identity_operator< TrilinosWrappers::MPI::Vector >(S[0][0].reinit_domain_vector);
346  // P[1][1] = identity_operator< TrilinosWrappers::MPI::Vector >(S[1][1].reinit_domain_vector);
347  // P[2][2] = identity_operator< TrilinosWrappers::MPI::Vector >(S[2][2].reinit_domain_vector);
348  // for (unsigned int i=0; i<3; ++i)
349 
350  P[0][0] = linear_operator<
351  dealii::TrilinosWrappers::MPI::Vector,
352  dealii::TrilinosWrappers::MPI::Vector,
354  //dealii::LinearOperator<dealii::TrilinosWrappers::MPI::Vector,
355  // dealii::TrilinosWrappers::MPI::Vector>,
357  >( preconditioner_matrix.block(0,0), *P00_preconditioner );
358  // P[1][1] = linear_operator< >( matrix.block(1,1), *P11_preconditioner );
359  // P[2][2] = linear_operator< >( matrix.block(1,1), *P22_preconditioner );
360 
361 
362  // P[0][0] = inverse_operator< >( S[0][0],
363 // solver_CG,
364 // *P00_preconditioner);
365  // TrilinosWrappers::MPI::Vector u,v;
366  // P[0][0].reinit_domain_vector(u, true);
367  // P[0][0].reinit_domain_vector(v, true);
368  // std::cout << "vmult... " << std::flush <<std::endl;
369  // P[0][0].vmult(u,v);
370  P[1][1] = inverse_operator< >( S[1][1],
371  solver_CG,
372  *P11_preconditioner);
373  // P[2][2] = S[2][2];
374  P[2][2] = inverse_operator< >( S[2][2],
375  solver_CG,
376  *P22_preconditioner);
377 
378 
379  // const LinearOperator< typename Solver::vector_type, typename Solver::vector_type > &op, Solver &solver, const Preconditioner &preconditioner)
380  prec_op = block_forward_substitution< >(
383  // identity_operator < TrilinosWrappers::MPI::BlockVector >( system_op.reinit_range_vector );
384 }
385 
386 
387 template class ALENavierStokes <2>;
388 
389 #endif
390 
TrilinosWrappers::BlockSparseMatrix MAT
Definition: ale_navier_stokes.h:37
virtual void compute_system_operators(const DoFHandler< dim > &, const TrilinosWrappers::BlockSparseMatrix &, const TrilinosWrappers::BlockSparseMatrix &, const std::vector< shared_ptr< MAT > >, LinearOperator< VEC > &, LinearOperator< VEC > &) const
Definition: ale_navier_stokes.h:288
void system_residual(const typename DoFHandler< dim >::active_cell_iterator &, Scratch &, CopySystem &, std::vector< Number > &local_residual) const
Definition: ale_navier_stokes.h:159
LinearOperator< Range, Domain > linear_operator(const Matrix &matrix)
Assembly::CopyData::piDoMUSPreconditioner< dim, dim > CopyPreconditioner
Definition: ale_navier_stokes.h:34
std::vector< std::vector< bool > > constant_modes
void preconditioner_residual(const typename DoFHandler< dim >::active_cell_iterator &, Scratch &, CopyPreconditioner &, std::vector< Number > &local_residual) const
Definition: ale_navier_stokes.h:98
LinearOperator< Range, Domain > null_operator(const LinearOperator< Range, Domain > &op)
ALENavierStokes()
Definition: ale_navier_stokes.h:86
void declare_parameters(ParameterHandler &prm)
Definition: ale_navier_stokes.h:272
FEValuesCache< dim, dim > Scratch
Definition: ale_navier_stokes.h:33
void aux_matrix_residuals(const typename DoFHandler< dim >::active_cell_iterator &, Scratch &, CopyPreconditioner &, std::vector< std::vector< Number > > &) const
Definition: ale_navier_stokes.h:70
BlockType & block(const unsigned int row, const unsigned int column)
ComponentMask component_mask(const FEValuesExtractors::Scalar &scalar) const
Definition: ale_navier_stokes.h:30
Assembly::CopyData::piDoMUSSystem< dim, dim > CopySystem
Definition: ale_navier_stokes.h:35
void parse_parameters_call_back()
Definition: ale_navier_stokes.h:280
Definition: non_conservative.h:19
void extract_constant_modes(const DoFHandlerType &dof_handler, const ComponentMask &component_mask, std::vector< std::vector< bool > > &constant_modes)
TrilinosWrappers::MPI::BlockVector VEC
Definition: ale_navier_stokes.h:36
const FiniteElement< dim, dim > & get_fe() const