71 #ifndef _pidomus_navier_stokes_h_
72 #define _pidomus_navier_stokes_h_
82 template <
int dim,
int spacedim=dim,
typename LAC=LATrilinos>
95 template <
typename EnergyType,
typename Res
idualType>
99 FEValuesCache<dim,spacedim> &scratch,
100 std::vector<EnergyType> &energies,
101 std::vector<std::vector<ResidualType>> &residuals,
102 bool compute_only_system_terms)
const;
107 const std::vector<shared_ptr<LATrilinos::BlockMatrix>>,
129 std::string non_linear_term;
134 bool linearize_in_time;
139 std::string prec_name;
184 double CG_solver_tolerance;
189 double GMRES_solver_tolerance;
194 int amg_smoother_sweeps;
199 double amg_aggregation_threshold;
209 bool amg_higher_order_elements;
214 int amg_p_smoother_sweeps;
219 double amg_p_aggregation_threshold;
226 mutable shared_ptr<TrilinosWrappers::PreconditionAMG>
228 mutable shared_ptr<TrilinosWrappers::PreconditionAMG>
229 Amg_preconditioner_2;
230 mutable shared_ptr<TrilinosWrappers::PreconditionJacobi>
231 jacobi_preconditioner;
234 template <
int dim,
int spacedim,
typename LAC>
239 "Navier Stokes Interface",
242 "FESystem[FE_Q(2)^d-FE_Q(1)]",
246 convection(convection),
253 template <
int dim,
int spacedim,
typename LAC>
258 declare_parameters(prm);
259 this->add_parameter(prm, &prec_name,
"Preconditioner",
"default",
261 "Available preconditioners: \n"
262 " - default -> S^-1 = nu * Mp^-1 \n"
263 " - identity -> S^-1 = identity \n"
264 " - low-nu -> S^-1 = rho * alpha * Ap^-1 \n"
265 " - cah-cha -> S^-1 = nu * Mp^-1 + rho * alpha * Ap^-1 ");
266 this->add_parameter(prm, &dynamic,
267 "Enable dynamic term (\\partial_t u)",
"true",
269 "Enable the dynamic term of the equation.");
270 this->add_parameter(prm, &convection,
271 "Enable convection term ((\\nabla u)u)",
"true",
273 "Enable the convection term of the equation. Set it false if you want to solve Stokes Equation.");
274 this->add_parameter(prm, &non_linear_term,
"Non linear term",
"grad_linear",
276 "Available options: \n"
277 " fully_non_linear\n"
281 this->add_parameter(prm, &linearize_in_time,
282 "Linearize using time",
"true",
284 "If true use the solution of the previous time step\n"
285 "to linearize the non-linear term, otherwise use the\n" "solution of the previous step (of an iterative methos).");
286 this->add_parameter(prm, &gamma,
287 "div-grad stabilization parameter",
"0.0",
290 this->add_parameter(prm, &gamma_p,
291 "p-q stabilization parameter",
"0.0",
294 this->add_parameter(prm, &rho,
295 "rho [kg m^3]",
"1.0",
298 this->add_parameter(prm, &nu,
302 this->add_parameter(prm, &invert_Ap,
304 this->add_parameter(prm, &invert_Mp,
306 this->add_parameter(prm, &CG_solver_tolerance,
307 "CG Solver tolerance",
"1e-8",
309 this->add_parameter(prm, &GMRES_solver_tolerance,
310 "GMRES Solver tolerance",
"1e-8",
312 this->add_parameter(prm, &amg_smoother_sweeps,
314 this->add_parameter(prm, &amg_aggregation_threshold,
316 this->add_parameter(prm, &amg_elliptic,
318 this->add_parameter(prm, &amg_higher_order_elements,
320 this->add_parameter(prm, &amg_p_smoother_sweeps,
322 this->add_parameter(prm, &amg_p_aggregation_threshold,
324 this->add_parameter(prm, &amg_p_elliptic,
328 template <
int dim,
int spacedim,
typename LAC>
332 if (prec_name ==
"default")
334 else if (prec_name ==
"low-nu")
336 else if (prec_name ==
"cah-cha")
347 template <
int dim,
int spacedim,
typename LAC>
351 couplings[0] =
"1,1;1,0";
352 couplings[1] =
"0,0;0,1";
353 couplings[2] =
"0,0;0,1";
356 template <
int dim,
int spacedim,
typename LAC>
357 template <
typename EnergyType,
typename Res
idualType>
361 FEValuesCache<dim,spacedim> &fe_cache,
362 std::vector<EnergyType> &,
363 std::vector<std::vector<ResidualType> > &residual,
364 bool compute_only_system_terms)
const
369 ResidualType et = this->alpha;
372 this->reinit (et, cell, fe_cache);
375 auto &us = fe_cache.get_values(
"solution",
"u", velocity, et);
376 auto &div_us = fe_cache.get_divergences(
"solution",
"div_u", velocity,et);
377 auto &grad_us = fe_cache.get_gradients(
"solution",
"grad_u", velocity,et);
378 auto &sym_grad_us = fe_cache.get_symmetric_gradients(
"solution",
"sym_grad_u", velocity,et);
379 auto &us_dot = fe_cache.get_values(
"solution_dot",
"u_dot", velocity, et);
381 auto &u_olds = fe_cache.get_values(
"explicit_solution",
"u", velocity, dummy);
382 auto &grad_u_olds = fe_cache.get_gradients(
"explicit_solution",
"grad_u", velocity, dummy);
384 fe_cache.cache_local_solution_vector(
"prev_solution", *this->solution, dummy);
385 auto &u_prevs = fe_cache.get_values(
"prev_solution",
"u", velocity, dummy);
386 auto &grad_u_prevs = fe_cache.get_gradients(
"prev_solution",
"grad_u", velocity, dummy);
389 auto &ps = fe_cache.get_values(
"solution",
"p", pressure, et);
390 auto &ps_dot = fe_cache.get_values(
"solution_dot",
"p_dot", pressure, et);
391 auto &grad_ps = fe_cache.get_gradients(
"solution",
"grad_p", pressure, et);
393 const unsigned int n_quad_points = us.size();
394 auto &JxW = fe_cache.get_JxW_values();
396 auto &fev = fe_cache.get_current_fe_values();
398 for (
unsigned int quad=0; quad<n_quad_points; ++quad)
400 const ResidualType &p = ps[quad];
401 const ResidualType &p_dot = ps_dot[quad];
407 const ResidualType &div_u = div_us[quad];
415 for (
unsigned int i=0; i<residual[0].size(); ++i)
418 auto v = fev[velocity ].value(i,quad);
419 auto div_v = fev[velocity ].divergence(i,quad);
420 auto grad_v = fev[ velocity ].gradient(i,quad);
421 auto sym_grad_v = fev[ velocity ].symmetric_gradient(i,quad);
424 auto q = fev[ pressure ].value(i,quad);
425 auto grad_q = fev[ pressure ].gradient(i,quad);
429 ResidualType res = 0.0;
433 res += rho * u_dot * v;
441 if (linearize_in_time)
448 gradoldu=grad_u_prev;
452 if (non_linear_term==
"fully_non_linear")
453 Np_term = grad_u * u;
454 else if (non_linear_term==
"grad_linear")
455 Np_term = gradoldu * u;
456 else if (non_linear_term==
"u_linear")
457 Np_term = grad_u * oldu;
458 else if (non_linear_term==
"RHS")
459 Np_term = gradoldu * oldu;
461 res += rho * scalar_product(Np_term,v);
465 res += gamma * div_u * div_v;
468 res += nu * scalar_product(sym_grad_u, sym_grad_v);
476 residual[0][i] += res * JxW[q];
479 if (!compute_only_system_terms && compute_Mp)
480 residual[1][i] += p * q * JxW[q];
483 if (!compute_only_system_terms && compute_Ap)
484 residual[2][i] += grad_p * grad_q * JxW[q];
487 (void)compute_only_system_terms;
491 template <
int dim,
int spacedim,
typename LAC>
495 const std::vector<shared_ptr<LATrilinos::BlockMatrix>> matrices,
499 auto aplha = this->alpha;
501 typedef LATrilinos::VectorType::BlockType BVEC;
504 static ReductionControl solver_control_cg(matrices[0]->m(), CG_solver_tolerance);
507 static ReductionControl solver_control_gmres(matrices[0]->m(), GMRES_solver_tolerance);
512 auto A = linear_operator<BVEC>( matrices[0]->block(0,0) );
513 auto Bt = linear_operator<BVEC>( matrices[0]->block(0,1) );
514 auto B = linear_operator<BVEC>( matrices[0]->block(1,0) );
515 auto C = linear_operator<BVEC>( matrices[0]->block(1,1) );
519 C = linear_operator<BVEC>( matrices[1]->block(1,1) );
524 system_op = block_operator<2, 2, VEC>({{
530 std::vector<std::vector<bool>> constant_modes;
536 Amg_data.elliptic = amg_elliptic;
537 Amg_data.higher_order_elements = amg_higher_order_elements;
538 Amg_data.smoother_sweeps = amg_smoother_sweeps;
539 Amg_data.aggregation_threshold = amg_aggregation_threshold;
541 std::vector<std::vector<bool> > constant_modes_p;
547 Amg_data_p.elliptic = amg_p_elliptic;
548 Amg_data_p.smoother_sweeps = amg_p_smoother_sweeps;
549 Amg_data_p.aggregation_threshold = amg_p_aggregation_threshold;
553 Amg_preconditioner->initialize (matrices[0]->block(0,0), Amg_data);
561 Mp = linear_operator<BVEC>( matrices[1]->block(1,1) );
563 jacobi_preconditioner->initialize (matrices[1]->block(1,1), 1.4);
568 Mp = linear_operator<BVEC>( matrices[2]->block(1,1) );
570 Amg_preconditioner_2->initialize (matrices[2]->block(1,1), Amg_data_p);
577 Ap_inv = linear_operator<BVEC>(matrices[2]->block(1,1), *Amg_preconditioner_2);
584 if (prec_name==
"default")
585 Schur_inv = (gamma + nu) * Mp_inv;
586 else if (prec_name==
"low-nu")
587 Schur_inv = aplha * rho * Ap_inv;
588 else if (prec_name==
"identity")
590 else if (prec_name==
"cha-cha")
591 Schur_inv = (gamma + nu) * Mp_inv + aplha * rho * Ap_inv;
594 P01 = A_inv * Bt * Schur_inv;
596 P11 = -1 * Schur_inv;
598 prec_op = block_operator<2, 2, VEC>({{
Definition: lac_type.h:33
void declare_parameters(ParameterHandler &prm)
Definition: navier_stokes.h:255
std::vector< std::vector< bool > > constant_modes
This interface solves a Navier Stokes Equation: where .
Definition: navier_stokes.h:83
ActiveSelector::active_cell_iterator active_cell_iterator
void set_matrix_couplings(std::vector< std::string > &couplings) const
Definition: navier_stokes.h:349
This is the class that users should derive from.
Definition: pde_system_interface.h:46
void compute_system_operators(const DoFHandler< dim, spacedim > &, const std::vector< shared_ptr< LATrilinos::BlockMatrix >>, LinearOperator< LATrilinos::VectorType > &, LinearOperator< LATrilinos::VectorType > &) const
Definition: navier_stokes.h:493
LinearOperator< Range, Domain > null_operator(const LinearOperator< Range, Domain > &op)
void parse_parameters_call_back()
Definition: navier_stokes.h:330
LinearOperator< typename Solver::vector_type, typename Solver::vector_type > inverse_operator(const LinearOperator< typename Solver::vector_type, typename Solver::vector_type > &op, Solver &solver, const Preconditioner &preconditioner)
LinearOperator< Range, Range > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
~NavierStokes()
Definition: navier_stokes.h:89
void energies_and_residuals(const typename DoFHandler< dim, spacedim >::active_cell_iterator &cell, FEValuesCache< dim, spacedim > &scratch, std::vector< EnergyType > &energies, std::vector< std::vector< ResidualType >> &residuals, bool compute_only_system_terms) const
NavierStokes(bool dynamic, bool convection)
Definition: navier_stokes.h:236
const FiniteElement< dim, spacedim > & get_fe() const