https://mooseframework.inl.gov
LinearAssemblySegregatedSolve.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "FEProblem.h"
12 #include "SegregatedSolverUtils.h"
13 #include "LinearSystem.h"
14 #include "Executioner.h"
15 
16 using namespace libMesh;
17 
20 {
22 
23  params.addParam<std::vector<SolverSystemName>>(
24  "active_scalar_systems", {}, "The solver system for each active scalar advection equation.");
25 
26  /*
27  * Parameters to control the solution of each scalar advection system
28  */
29  params.addParam<std::vector<Real>>("active_scalar_equation_relaxation",
30  std::vector<Real>(),
31  "The relaxation which should be used for the active scalar "
32  "equations. (=1 for no relaxation, "
33  "diagonal dominance will still be enforced)");
34 
35  params.addParam<MultiMooseEnum>("active_scalar_petsc_options",
37  "Singleton PETSc options for the active scalar equation(s)");
38  params.addParam<MultiMooseEnum>(
39  "active_scalar_petsc_options_iname",
41  "Names of PETSc name/value pairs for the active scalar equation(s)");
42  params.addParam<std::vector<std::string>>(
43  "active_scalar_petsc_options_value",
44  "Values of PETSc name/value pairs (must correspond with \"petsc_options_iname\" for the "
45  "active scalar equation(s)");
46  params.addParam<std::vector<Real>>(
47  "active_scalar_absolute_tolerance",
48  std::vector<Real>(),
49  "The absolute tolerance(s) on the normalized residual(s) of the active scalar equation(s).");
50  params.addRangeCheckedParam<Real>("active_scalar_l_tol",
51  1e-5,
52  "0.0<=active_scalar_l_tol & active_scalar_l_tol<1.0",
53  "The relative tolerance on the normalized residual in the "
54  "linear solver of the active scalar equation(s).");
55  params.addRangeCheckedParam<Real>("active_scalar_l_abs_tol",
56  1e-10,
57  "0.0<active_scalar_l_abs_tol",
58  "The absolute tolerance on the normalized residual in the "
59  "linear solver of the active scalar equation(s).");
60  params.addParam<unsigned int>(
61  "active_scalar_l_max_its",
62  10000,
63  "The maximum allowed iterations in the linear solver of the turbulence equation.");
64 
65  params.addParamNamesToGroup(
66  "active_scalar_systems active_scalar_equation_relaxation active_scalar_petsc_options "
67  "active_scalar_petsc_options_iname "
68  "active_scalar_petsc_options_value active_scalar_petsc_options_value "
69  "active_scalar_absolute_tolerance "
70  "active_scalar_l_tol active_scalar_l_abs_tol active_scalar_l_max_its",
71  "Active Scalars Equations");
72 
73  /*
74  * Flags to optionally skip solving subsets of the thermal-hydraulics system (useful when
75  * recovering a converged solution and only advancing scalar transport for example).
76  */
77  params.addParam<bool>(
78  "should_solve_momentum", true, "Whether we should solve the momentum predictor/corrector.");
79  params.addParam<bool>(
80  "should_solve_pressure", true, "Whether we should solve the pressure corrector.");
81  params.addParam<bool>(
82  "should_solve_energy", true, "Whether we should solve the fluid energy equation.");
83  params.addParam<bool>(
84  "should_solve_solid_energy", true, "Whether we should solve the solid energy equation.");
85  params.addParam<bool>("should_solve_turbulence",
86  true,
87  "Whether we should solve the turbulence surrogate equations.");
88  params.addParam<bool>(
89  "should_solve_passive_scalars", true, "Whether we should solve passive scalar equations.");
90  params.addParam<bool>(
91  "should_solve_active_scalars", true, "Whether we should solve active scalar equations.");
92  params.addParam<bool>("should_solve_pm_radiation",
93  true,
94  "Whether we should solve participating media radiation equations.");
95  params.addParamNamesToGroup("should_solve_momentum should_solve_pressure should_solve_energy "
96  "should_solve_solid_energy should_solve_turbulence "
97  "should_solve_passive_scalars should_solve_active_scalars",
98  "Solve control");
99 
100  /*
101  * Parameters to control the conjugate heat transfer
102  */
104 
105  return params;
106 }
107 
109  : SIMPLESolveBase(ex),
110  _pressure_sys_number(_problem.linearSysNum(getParam<SolverSystemName>("pressure_system"))),
111  _pressure_system(_problem.getLinearSystem(_pressure_sys_number)),
112  _energy_sys_number(_has_energy_system
113  ? _problem.linearSysNum(getParam<SolverSystemName>("energy_system"))
114  : libMesh::invalid_uint),
115  _energy_system(_has_energy_system ? &_problem.getLinearSystem(_energy_sys_number) : nullptr),
116  _solid_energy_sys_number(
117  _has_solid_energy_system
118  ? _problem.linearSysNum(getParam<SolverSystemName>("solid_energy_system"))
119  : libMesh::invalid_uint),
120  _solid_energy_system(
121  _has_solid_energy_system ? &_problem.getLinearSystem(_solid_energy_sys_number) : nullptr),
122  _should_solve_momentum(getParam<bool>("should_solve_momentum")),
123  _should_solve_pressure(getParam<bool>("should_solve_pressure")),
124  _should_solve_energy(getParam<bool>("should_solve_energy")),
125  _should_solve_solid_energy(getParam<bool>("should_solve_solid_energy")),
126  _should_solve_turbulence(getParam<bool>("should_solve_turbulence")),
127  _should_solve_passive_scalars(getParam<bool>("should_solve_passive_scalars")),
128  _should_solve_active_scalars(getParam<bool>("should_solve_active_scalars")),
129  _should_solve_pm_radiation(getParam<bool>("should_solve_pm_radiation")),
130  _active_scalar_system_names(getParam<std::vector<SolverSystemName>>("active_scalar_systems")),
131  _has_active_scalar_systems(!_active_scalar_system_names.empty()),
132  _active_scalar_equation_relaxation(
133  getParam<std::vector<Real>>("active_scalar_equation_relaxation")),
134  _active_scalar_l_abs_tol(getParam<Real>("active_scalar_l_abs_tol")),
135  _active_scalar_absolute_tolerance(
136  getParam<std::vector<Real>>("active_scalar_absolute_tolerance")),
137  _cht(ex.parameters())
138 {
140  paramError("should_solve_momentum",
141  "Pressure correction requires solving the momentum equations.");
143  paramError("should_solve_pressure",
144  "Solving momentum without a pressure corrector is not supported.");
146  paramError("should_solve_solid_energy",
147  "Solid energy solve cannot be enabled when the fluid energy solve is disabled.");
148 
149  // We fetch the systems and their numbers for the momentum equations only if we solve them
151  for (auto system_i : index_range(_momentum_system_names))
152  {
155  _systems_to_solve.push_back(_momentum_systems.back());
156  }
157 
160 
163 
166  // and for the turbulence surrogate equations
168  for (auto system_i : index_range(_turbulence_system_names))
169  {
170  _turbulence_system_numbers.push_back(
172  _turbulence_systems.push_back(
174  }
175 
176  // and for the passive scalar equations
178  for (auto system_i : index_range(_passive_scalar_system_names))
179  {
182  _passive_scalar_systems.push_back(
185  _systems_to_solve.push_back(_passive_scalar_systems.back());
186  }
187 
188  // and for the participating media radiation equations
190  for (auto system_i : index_range(_pm_radiation_system_names))
191  {
194  _pm_radiation_systems.push_back(
196  _systems_to_solve.push_back(_pm_radiation_systems.back());
197  }
198 
199  // and for the active scalar equations
201  for (auto system_i : index_range(_active_scalar_system_names))
202  {
205  _active_scalar_systems.push_back(
207  _systems_to_solve.push_back(_active_scalar_systems.back());
208 
209  const auto & active_scalar_petsc_options =
210  getParam<MultiMooseEnum>("active_scalar_petsc_options");
211  const auto & active_scalar_petsc_pair_options = getParam<MooseEnumItem, std::string>(
212  "active_scalar_petsc_options_iname", "active_scalar_petsc_options_value");
214  active_scalar_petsc_options, "", *this, _active_scalar_petsc_options);
215  Moose::PetscSupport::addPetscPairsToPetscOptions(active_scalar_petsc_pair_options,
216  _problem.mesh().dimension(),
217  "",
218  *this,
220 
222  getParam<Real>("active_scalar_l_tol");
224  getParam<Real>("active_scalar_l_abs_tol");
226  getParam<unsigned int>("active_scalar_l_max_its");
227  }
228 
230  paramError("active_scalar_equation_relaxation",
231  "Should be the same size as the number of systems");
232 
233  // We disable the prefix here for the time being, the segregated solvers use a different approach
234  // for setting the petsc parameters
235  for (auto & system : _systems_to_solve)
236  system->system().prefix_with_name(false);
237 
238  // Link CHT objects, this will also do some error checking
239  // Make a copy for compatibility. These could change in the future
240  // Convert _pm_radiation_systems to std::vector<SystemBase *>
241  if (_cht.enabled())
242  {
244  paramError("should_solve_energy",
245  "Conjugate heat transfer requires solving the fluid energy equation.");
247  paramError("should_solve_solid_energy",
248  "Conjugate heat transfer requires solving the solid energy equation.");
249 
250  std::vector<SystemBase *> pm_radiation_systems_base(_pm_radiation_systems.begin(),
251  _pm_radiation_systems.end());
252 
253  _cht.linkEnergySystems(_solid_energy_system, _energy_system, pm_radiation_systems_base);
254  }
255 }
256 
257 void
259 {
261  return;
262 
263  _rc_uo =
264  const_cast<RhieChowMassFlux *>(&getUserObject<RhieChowMassFlux>("rhie_chow_user_object"));
267 
268  // Initialize the face velocities in the RC object
269  if (!_app.isRecovering())
272 }
273 
274 std::vector<std::pair<unsigned int, Real>>
276 {
277  // Temporary storage for the (flux-normalized) residuals from
278  // different momentum components
279  std::vector<std::pair<unsigned int, Real>> its_normalized_residuals;
280 
281  LinearImplicitSystem & momentum_system_0 =
282  libMesh::cast_ref<LinearImplicitSystem &>(_momentum_systems[0]->system());
283 
284  PetscLinearSolver<Real> & momentum_solver =
285  libMesh::cast_ref<PetscLinearSolver<Real> &>(*momentum_system_0.get_linear_solver());
286 
287  // Solve the momentum equations.
288  // TO DO: These equations are VERY similar. If we can store the differences (things coming from
289  // BCs for example) separately, it is enough to construct one matrix.
290  for (const auto system_i : index_range(_momentum_systems))
291  {
293 
294  // We will need the right hand side and the solution of the next component
295  LinearImplicitSystem & momentum_system =
296  libMesh::cast_ref<LinearImplicitSystem &>(_momentum_systems[system_i]->system());
297 
298  NumericVector<Number> & solution = *(momentum_system.solution);
299  NumericVector<Number> & rhs = *(momentum_system.rhs);
300  SparseMatrix<Number> & mmat = *(momentum_system.matrix);
301 
302  auto diff_diagonal = solution.zero_clone();
303 
304  // We assemble the matrix and the right hand side
305  _problem.computeLinearSystemSys(momentum_system, mmat, rhs, /*compute_grads*/ true);
306 
307  // Still need to relax the right hand side with the same vector
308  NS::FV::relaxMatrix(mmat, _momentum_equation_relaxation, *diff_diagonal);
309  NS::FV::relaxRightHandSide(rhs, solution, *diff_diagonal);
310 
311  // The normalization factor depends on the right hand side so we need to recompute it for this
312  // component
313  Real norm_factor = NS::FV::computeNormalizationFactor(solution, mmat, rhs);
314 
315  // Very important, for deciding the convergence, we need the unpreconditioned
316  // norms in the linear solve
317  LibmeshPetscCall(KSPSetNormType(momentum_solver.ksp(), KSP_NORM_UNPRECONDITIONED));
318  // Solve this component. We don't update the ghosted solution yet, that will come at the end
319  // of the corrector step. Also setting the linear tolerances and maximum iteration counts.
321  momentum_solver.set_solver_configuration(_momentum_linear_control);
322 
323  // We solve the equation
324  auto its_resid_pair = momentum_solver.solve(mmat, mmat, solution, rhs);
325  momentum_system.update();
326 
327  // We will reuse the preconditioner for every momentum system
328  if (system_i == 0)
329  momentum_solver.reuse_preconditioner(true);
330 
331  // Save the normalized residual
332  its_normalized_residuals.push_back(
333  std::make_pair(its_resid_pair.first, momentum_solver.get_initial_residual() / norm_factor));
334 
335  if (_print_fields)
336  {
337  _console << " matrix when we solve " << std::endl;
338  mmat.print();
339  _console << " rhs when we solve " << std::endl;
340  rhs.print();
341  _console << " velocity solution component " << system_i << std::endl;
342  solution.print();
343  _console << "Norm factor " << norm_factor << std::endl;
344  _console << Moose::stringify(momentum_solver.get_initial_residual()) << std::endl;
345  }
346 
347  // Printing residuals
348  _console << " Momentum equation:"
349  << (_momentum_systems.size() > 1
350  ? std::string(" Component ") + std::to_string(system_i + 1) + std::string(" ")
351  : std::string(" "))
352  << COLOR_GREEN << its_normalized_residuals[system_i].second << COLOR_DEFAULT
353  << " Linear its: " << its_normalized_residuals[system_i].first << std::endl;
354  }
355 
356  for (const auto system_i : index_range(_momentum_systems))
357  {
358  LinearImplicitSystem & momentum_system =
359  libMesh::cast_ref<LinearImplicitSystem &>(_momentum_systems[system_i]->system());
360  _momentum_systems[system_i]->setSolution(*(momentum_system.current_local_solution));
361  _momentum_systems[system_i]->copyPreviousNonlinearSolutions();
362  }
363 
364  // We reset this to ensure the preconditioner is recomputed new time we go to the momentum
365  // predictor
366  momentum_solver.reuse_preconditioner(false);
367 
368  return its_normalized_residuals;
369 }
370 
371 void
373 {
374  if (_cht.enabled())
375  {
378  }
379 }
380 
381 std::pair<unsigned int, Real>
383 {
385 
386  // We will need some members from the linear system
387  LinearImplicitSystem & pressure_system =
388  libMesh::cast_ref<LinearImplicitSystem &>(_pressure_system.system());
389 
390  // We will need the solution, the right hand side and the matrix
391  NumericVector<Number> & current_local_solution = *(pressure_system.current_local_solution);
392  NumericVector<Number> & solution = *(pressure_system.solution);
393  SparseMatrix<Number> & mmat = *(pressure_system.matrix);
394  NumericVector<Number> & rhs = *(pressure_system.rhs);
395 
396  // Fetch the linear solver from the system
397  PetscLinearSolver<Real> & pressure_solver =
398  libMesh::cast_ref<PetscLinearSolver<Real> &>(*pressure_system.get_linear_solver());
399 
400  _problem.computeLinearSystemSys(pressure_system, mmat, rhs, false);
401 
402  if (_print_fields)
403  {
404  _console << "Pressure matrix" << std::endl;
405  mmat.print();
406  }
407 
408  // We compute the normalization factors based on the fluxes
409  Real norm_factor = NS::FV::computeNormalizationFactor(solution, mmat, rhs);
410 
411  // We need the non-preconditioned norm to be consistent with the norm factor
412  LibmeshPetscCall(KSPSetNormType(pressure_solver.ksp(), KSP_NORM_UNPRECONDITIONED));
413 
414  // Setting the linear tolerances and maximum iteration counts
417 
418  if (_pin_pressure)
420  pressure_system.update();
421 
422  auto its_res_pair = pressure_solver.solve(mmat, mmat, solution, rhs);
423  pressure_system.update();
424 
425  if (_print_fields)
426  {
427  _console << " rhs when we solve pressure " << std::endl;
428  rhs.print();
429  _console << " Pressure " << std::endl;
430  solution.print();
431  _console << "Norm factor " << norm_factor << std::endl;
432  }
433 
434  _pressure_system.setSolution(current_local_solution);
435 
436  const auto residuals =
437  std::make_pair(its_res_pair.first, pressure_solver.get_initial_residual() / norm_factor);
438 
439  _console << " Pressure equation: " << COLOR_GREEN << residuals.second << COLOR_DEFAULT
440  << " Linear its: " << residuals.first << std::endl;
441 
442  return residuals;
443 }
444 
445 std::pair<unsigned int, Real>
447 {
449 
450  // We will need some members from the linear system
451  LinearImplicitSystem & system =
452  libMesh::cast_ref<LinearImplicitSystem &>(_solid_energy_system->system());
453 
454  // We will need the solution, the right hand side and the matrix
455  NumericVector<Number> & current_local_solution = *(system.current_local_solution);
456  NumericVector<Number> & solution = *(system.solution);
457  SparseMatrix<Number> & mmat = *(system.matrix);
458  NumericVector<Number> & rhs = *(system.rhs);
459 
460  // Fetch the linear solver from the system
461  PetscLinearSolver<Real> & solver =
462  libMesh::cast_ref<PetscLinearSolver<Real> &>(*system.get_linear_solver());
463 
464  _problem.computeLinearSystemSys(system, mmat, rhs, false);
465 
466  if (_print_fields)
467  {
468  _console << "Solid energy matrix" << std::endl;
469  mmat.print();
470  }
471 
472  // We compute the normalization factors based on the fluxes
473  Real norm_factor = NS::FV::computeNormalizationFactor(solution, mmat, rhs);
474 
475  // We need the non-preconditioned norm to be consistent with the norm factor
476  LibmeshPetscCall(KSPSetNormType(solver.ksp(), KSP_NORM_UNPRECONDITIONED));
477 
478  // Setting the linear tolerances and maximum iteration counts
481 
482  auto its_res_pair = solver.solve(mmat, mmat, solution, rhs);
483  system.update();
484 
485  if (_print_fields)
486  {
487  _console << " rhs when we solve solid energy " << std::endl;
488  rhs.print();
489  _console << " Solid energy " << std::endl;
490  solution.print();
491  _console << "Norm factor " << norm_factor << std::endl;
492  }
493 
494  _solid_energy_system->setSolution(current_local_solution);
495 
496  const auto residuals =
497  std::make_pair(its_res_pair.first, solver.get_initial_residual() / norm_factor);
498 
499  _console << " Solid energy equation: " << COLOR_GREEN << residuals.second << COLOR_DEFAULT
500  << " Linear its: " << residuals.first << std::endl;
501 
502  return residuals;
503 }
504 
505 std::pair<unsigned int, Real>
506 LinearAssemblySegregatedSolve::correctVelocity(const bool subtract_updated_pressure,
507  const bool recompute_face_mass_flux,
508  const SolverParams & solver_params)
509 {
510  // Compute the coupling fields between the momentum and pressure equations.
511  // The first argument makes sure the pressure gradient is staged at the first
512  // iteration
513  _rc_uo->computeHbyA(subtract_updated_pressure, _print_fields);
514 
515  // We set the preconditioner/controllable parameters for the pressure equations through
516  // petsc options. Linear tolerances will be overridden within the solver.
518 
519  // Solve the pressure corrector
520  const auto residuals = solvePressureCorrector();
521 
522  // Compute the face velocity which is used in the advection terms. In certain
523  // segregated solver algorithms (like PISO) this is only done on the last iteration.
524  if (recompute_face_mass_flux)
526 
527  auto & pressure_current_solution = *(_pressure_system.system().current_local_solution.get());
528  auto & pressure_old_solution = *(_pressure_system.solutionPreviousNewton());
529 
530  // Relax the pressure update for the next momentum predictor
532  pressure_current_solution, pressure_old_solution, _pressure_variable_relaxation);
533 
534  // Overwrite old solution
535  pressure_old_solution = pressure_current_solution;
536  _pressure_system.setSolution(pressure_current_solution);
537 
538  // We recompute the updated pressure gradient
540 
541  // Reconstruct the cell velocity as well to accelerate convergence
543 
544  return residuals;
545 }
546 
547 std::pair<unsigned int, Real>
549  LinearSystem & system,
550  const Real relaxation_factor,
551  SolverConfiguration & solver_config,
552  const Real absolute_tol,
553  const Real field_relaxation,
554  const Real min_value_limiter)
555 {
556  _problem.setCurrentLinearSystem(system_num);
557 
558  // We will need some members from the implicit linear system
559  LinearImplicitSystem & li_system = libMesh::cast_ref<LinearImplicitSystem &>(system.system());
560 
561  // We will need the solution, the right hand side and the matrix
562  NumericVector<Number> & current_local_solution = *(li_system.current_local_solution);
563  NumericVector<Number> & solution = *(li_system.solution);
564  SparseMatrix<Number> & mmat = *(li_system.matrix);
565  NumericVector<Number> & rhs = *(li_system.rhs);
566 
567  // We need a vector that stores the (diagonal_relaxed-original_diagonal) vector
568  auto diff_diagonal = solution.zero_clone();
569 
570  // Fetch the linear solver from the system
571  PetscLinearSolver<Real> & linear_solver =
572  libMesh::cast_ref<PetscLinearSolver<Real> &>(*li_system.get_linear_solver());
573 
574  _problem.computeLinearSystemSys(li_system, mmat, rhs, true);
575 
576  // Go and relax the system matrix and the right hand side
577  NS::FV::relaxMatrix(mmat, relaxation_factor, *diff_diagonal);
578  NS::FV::relaxRightHandSide(rhs, solution, *diff_diagonal);
579 
580  if (_print_fields)
581  {
582  _console << system.name() << " system matrix" << std::endl;
583  mmat.print();
584  }
585 
586  // We compute the normalization factors based on the fluxes
587  Real norm_factor = NS::FV::computeNormalizationFactor(solution, mmat, rhs);
588 
589  // We need the non-preconditioned norm to be consistent with the norm factor
590  LibmeshPetscCall(KSPSetNormType(linear_solver.ksp(), KSP_NORM_UNPRECONDITIONED));
591 
592  // Setting the linear tolerances and maximum iteration counts
593  solver_config.real_valued_data["abs_tol"] = absolute_tol * norm_factor;
594  linear_solver.set_solver_configuration(solver_config);
595 
596  // Solve the system and update current local solution
597  auto its_res_pair = linear_solver.solve(mmat, mmat, solution, rhs);
598  li_system.update();
599 
600  if (_print_fields)
601  {
602  _console << " rhs when we solve " << system.name() << std::endl;
603  rhs.print();
604  _console << system.name() << " solution " << std::endl;
605  solution.print();
606  _console << " Norm factor " << norm_factor << std::endl;
607  }
608 
609  // Limiting scalar solution
610  if (min_value_limiter != std::numeric_limits<Real>::min())
611  NS::FV::limitSolutionUpdate(current_local_solution, min_value_limiter);
612 
613  // Relax the field update for the next momentum predictor
614  if (field_relaxation != 1.0)
615  {
616  auto & old_local_solution = *(system.solutionPreviousNewton());
617  NS::FV::relaxSolutionUpdate(current_local_solution, old_local_solution, field_relaxation);
618 
619  // Update old solution, only needed if relaxing the field
620  old_local_solution = current_local_solution;
621  }
622 
623  system.setSolution(current_local_solution);
624 
625  const auto residuals =
626  std::make_pair(its_res_pair.first, linear_solver.get_initial_residual() / norm_factor);
627 
628  _console << " Advected system: " << system.name() << " " << COLOR_GREEN << residuals.second
629  << COLOR_DEFAULT << " Linear its: " << residuals.first << std::endl;
630 
631  return residuals;
632 }
633 
634 bool
636 {
637  // Do not solve if problem is set not to
638  if (!_problem.shouldSolve())
639  return true;
640 
641  // Dummy solver parameter file which is needed for switching petsc options
642  SolverParams solver_params;
643  solver_params._type = Moose::SolveType::ST_LINEAR;
644  solver_params._line_search = Moose::LineSearchType::LS_NONE;
645 
646  // Initialize the SIMPLE iteration counter
647  unsigned int simple_iteration_counter = 0;
648 
649  // We set up the residual storage and the corresponding tolerances.
650  ResidualStorage residual_storage = setupResidualStorage();
651  auto & ns_residuals = residual_storage.ns_residuals;
652  auto & ns_abs_tols = residual_storage.ns_abs_tols;
653  const auto & momentum_indices = residual_storage.momentum_indices;
654  const auto pressure_index = residual_storage.pressure_index;
655  const auto energy_index = residual_storage.energy_index;
656  const auto solid_energy_index = residual_storage.solid_energy_index;
657  const auto & active_scalar_indices = residual_storage.active_scalar_indices;
658  const auto & turbulence_indices = residual_storage.turbulence_indices;
659  const auto & pm_radiation_indices = residual_storage.pm_radiation_indices;
660 
661  bool converged = residual_storage.converged;
662 
663  // Loop until converged or hit the maximum allowed iteration number
666 
667  while (simple_iteration_counter < _num_iterations && !converged)
668  {
669  simple_iteration_counter++;
670 
671  // We set the preconditioner/controllable parameters through petsc options. Linear
672  // tolerances will be overridden within the solver. In case of a segregated momentum
673  // solver, we assume that every velocity component uses the same preconditioner
676 
677  // Initialize pressure gradients, after this we just reuse the last ones from each
678  // iteration
679  if (_should_solve_pressure && simple_iteration_counter == 1)
681 
682  _console << "Iteration " << simple_iteration_counter << " Initial residual norms:" << std::endl;
683 
684  // Solve the momentum predictor step
686  {
687  auto momentum_residual = solveMomentumPredictor();
688  for (const auto system_i : index_range(momentum_residual))
689  ns_residuals[momentum_indices[system_i]] = momentum_residual[system_i];
690  }
691 
692  // Now we correct the velocity, this function depends on the method, it differs for
693  // SIMPLE/PIMPLE, this returns the pressure errors
695  ns_residuals[pressure_index] = correctVelocity(true, true, solver_params);
696 
697  // If we have an energy equation, solve it here.We assume the material properties in the
698  // Navier-Stokes equations depend on temperature, therefore we can not solve for temperature
699  // outside of the velocity-pressure loop
701  {
702  // If there is no CHT specified this will just do go once through this block
704  while (!_cht.converged())
705  {
706  if (_cht.enabled())
708 
709  // We set the preconditioner/controllable parameters through petsc options. Linear
710  // tolerances will be overridden within the solver.
712  ns_residuals[energy_index] = solveAdvectedSystem(_energy_sys_number,
717 
719  {
720  // We set the preconditioner/controllable parameters through petsc options. Linear
721  // tolerances will be overridden within the solver.
723  for (const auto i : index_range(_pm_radiation_system_names))
724  {
725  ns_residuals[pm_radiation_indices[i]] =
731  }
732  }
733 
735  {
736  // For now we only update gradients if cht is needed, might change in the future
737  if (_cht.enabled())
738  {
741  }
742 
743  // We set the preconditioner/controllable parameters through petsc options. Linear
744  // tolerances will be overridden within the solver.
746  ns_residuals[solid_energy_index] = solveSolidEnergy();
747 
748  // For now we only update gradients if cht is needed, might change in the future
749  if (_cht.enabled())
751  }
752 
753  if (_cht.enabled())
754  {
757  }
758 
760  }
761  if (_cht.enabled())
763  }
764 
765  // If we have active scalar equations, solve them here in case they depend on temperature
766  // or they affect the fluid properties such that they must be solved concurrently with
767  // pressure and velocity
769  {
771 
772  // We set the preconditioner/controllable parameters through petsc options. Linear
773  // tolerances will be overridden within the solver.
775  for (const auto i : index_range(_active_scalar_system_names))
776  ns_residuals[active_scalar_indices[i]] =
782  }
783 
784  // If we have turbulence equations, solve them here.
785  // The turbulent viscosity depends on the value of the turbulence surrogate variables
787  {
788  // We set the preconditioner/controllable parameters through petsc options. Linear
789  // tolerances will be overridden within the solver.
791  for (const auto i : index_range(_turbulence_system_names))
792  {
793  ns_residuals[turbulence_indices[i]] =
801  }
802  }
803 
805 
806  converged = NS::FV::converged(ns_residuals, ns_abs_tols);
807  }
808 
809  // If we have passive scalar equations, solve them here. We assume the material properties in
810  // the Navier-Stokes equations do not depend on passive scalars, as they are passive, therefore
811  // we solve outside of the velocity-pressure loop
814  {
815  // The reason why we need more than one iteration is due to the matrix relaxation
816  // which can be used to stabilize the equations
817  bool passive_scalar_converged = false;
818  unsigned int ps_iteration_counter = 0;
819 
820  _console << "Passive scalar iteration " << ps_iteration_counter
821  << " Initial residual norms:" << std::endl;
822 
823  while (ps_iteration_counter < _num_iterations && !passive_scalar_converged)
824  {
825  ps_iteration_counter++;
826  std::vector<std::pair<unsigned int, Real>> scalar_residuals(
827  _passive_scalar_system_names.size(), std::make_pair(0, 1.0));
828  std::vector<Real> scalar_abs_tols;
829  for (const auto scalar_tol : _passive_scalar_absolute_tolerance)
830  scalar_abs_tols.push_back(scalar_tol);
831 
832  // We set the preconditioner/controllable parameters through petsc options. Linear
833  // tolerances will be overridden within the solver.
835  for (const auto i : index_range(_passive_scalar_system_names))
836  scalar_residuals[i] = solveAdvectedSystem(_passive_scalar_system_numbers[i],
841 
842  passive_scalar_converged = NS::FV::converged(scalar_residuals, scalar_abs_tols);
843  }
844 
845  // Both flow and scalars must converge
846  converged = passive_scalar_converged && converged;
847  }
848 
850 
851  return converged;
852 }
853 
856 {
857  ResidualStorage storage;
858 
859  // Residual store: position in this vector defines the ordering used by NS::FV::converged()
860  // Each entry holds (linear its, normalized residual) for one system
862  for ([[maybe_unused]] const auto system_i : index_range(_momentum_systems))
863  {
864  storage.momentum_indices.push_back(storage.ns_residuals.size());
865  storage.ns_residuals.push_back(std::make_pair(0, 1.0));
866  storage.ns_abs_tols.push_back(_momentum_absolute_tolerance);
867  }
868 
870  {
871  storage.pressure_index = storage.ns_residuals.size();
872  storage.ns_residuals.push_back(std::make_pair(0, 1.0));
873  storage.ns_abs_tols.push_back(_pressure_absolute_tolerance);
874  }
875 
877  {
878  storage.energy_index = storage.ns_residuals.size();
879  storage.ns_residuals.push_back(std::make_pair(0, 1.0));
880  storage.ns_abs_tols.push_back(_energy_absolute_tolerance);
881  }
882 
884  {
885  storage.solid_energy_index = storage.ns_residuals.size();
886  storage.ns_residuals.push_back(std::make_pair(0, 1.0));
888  }
889 
891  for (const auto i : index_range(_active_scalar_system_names))
892  {
893  storage.active_scalar_indices.push_back(storage.ns_residuals.size());
894  storage.ns_residuals.push_back(std::make_pair(0, 1.0));
895  storage.ns_abs_tols.push_back(_active_scalar_absolute_tolerance[i]);
896  }
897 
899  for (const auto i : index_range(_turbulence_system_names))
900  {
901  storage.turbulence_indices.push_back(storage.ns_residuals.size());
902  storage.ns_residuals.push_back(std::make_pair(0, 1.0));
903  storage.ns_abs_tols.push_back(_turbulence_absolute_tolerance[i]);
904  }
905 
907  for (const auto i : index_range(_pm_radiation_system_names))
908  {
909  storage.pm_radiation_indices.push_back(storage.ns_residuals.size());
910  storage.ns_residuals.push_back(std::make_pair(0, 1.0));
911  storage.ns_abs_tols.push_back(_pm_radiation_absolute_tolerance[i]);
912  }
913 
914  storage.converged = storage.ns_residuals.empty();
915  return storage;
916 }
MultiMooseEnum getCommonPetscKeys()
void relaxMatrix(SparseMatrix< Number > &matrix_in, const Real relaxation_parameter, NumericVector< Number > &diff_diagonal)
Relax the matrix to ensure diagonal dominance, we hold onto the difference in diagonals for later use...
bool shouldSolve() const
const std::vector< Real > _active_scalar_equation_relaxation
The user-defined relaxation parameter(s) for the active scalar equation(s)
FEProblemBase & _problem
SIMPLESolverConfiguration _momentum_linear_control
Options for the linear solver of the momentum equation.
void addPetscFlagsToPetscOptions(const MultiMooseEnum &petsc_flags, std::string prefix, const ParallelParamObject &param_object, PetscOptions &petsc_options)
SIMPLESolverConfiguration _turbulence_linear_control
Options for the linear solver of the turbulence equation(s)
const Real _energy_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in energy.
void updateCHTBoundaryCouplingFields(const NS::CHTSide side)
Update the coupling fields for.
Definition: CHTHandler.C:392
const unsigned int _num_iterations
The maximum number of momentum-pressure iterations.
User object responsible for determining the face fluxes using the Rhie-Chow interpolation in a segreg...
SIMPLESolverConfiguration _energy_linear_control
Options for the linear solver of the energy equation.
const unsigned int invalid_uint
std::vector< Real > ns_abs_tols
Absolute tolerances matching ns_residuals.
void paramError(const std::string &param, Args... args) const
const bool _print_fields
Debug parameter which allows printing the coupling and solution vectors/matrices. ...
Moose::PetscSupport::PetscOptions _turbulence_petsc_options
Options which hold the petsc settings for the turbulence equation(s)
SIMPLESolverConfiguration _pm_radiation_linear_control
Options for the linear solver of the participating media radiation equation(s)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const Real _solid_energy_l_abs_tol
Absolute linear tolerance for the energy equations.
const bool _has_energy_system
Boolean for easy check if a fluid energy system shall be solved or not.
Moose::LineSearchType _line_search
Real computeNormalizationFactor(const NumericVector< Number > &solution, const SparseMatrix< Number > &mat, const NumericVector< Number > &rhs)
Compute a normalization factor which is applied to the linear residual to determine convergence...
void addPetscPairsToPetscOptions(const std::vector< std::pair< MooseEnumItem, std::string >> &petsc_pair_options, const unsigned int mesh_dimension, std::string prefix, const ParallelParamObject &param_object, PetscOptions &petsc_options)
SIMPLESolverConfiguration _active_scalar_linear_control
Options for the linear solver of the active scalar equation(s)
std::vector< Real > _turbulence_field_relaxation
The user-defined relaxation parameter(s) for the turbulence field(s)
const Real _passive_scalar_l_abs_tol
Absolute linear tolerance for the passive scalar equation(s).
std::pair< unsigned int, Real > solveSolidEnergy()
Solve an equation which contains the solid energy conservation.
std::vector< LinearSystem * > _passive_scalar_systems
Pointer(s) to the system(s) corresponding to the passive scalar equation(s)
void resetIntegratedFluxes()
Reset the heat fluxes to 0.
Definition: CHTHandler.C:488
Moose::PetscSupport::PetscOptions _solid_energy_petsc_options
Options which hold the petsc settings for the fluid energy equation.
const Real _momentum_equation_relaxation
The user-defined relaxation parameter for the momentum equation.
virtual std::unique_ptr< NumericVector< T > > zero_clone() const=0
const bool _has_turbulence_systems
Boolean for easy check if a turbulence scalar systems shall be solved or not.
void computeFaceMassFlux()
Update the values of the face velocities in the containers.
std::vector< unsigned int > _turbulence_system_numbers
std::size_t solid_energy_index
Index of the solid energy equation in ns_residuals.
static InputParameters validParams()
void printIntegratedFluxes() const
Print the integrated heat fluxes.
Definition: CHTHandler.C:476
Definition: NS.h:201
LinearSystem * _solid_energy_system
Pointer to the linear system corresponding to the solid energy equation.
std::pair< unsigned int, Real > solveAdvectedSystem(const unsigned int system_num, LinearSystem &system, const Real relaxation_factor, libMesh::SolverConfiguration &solver_config, const Real abs_tol, const Real field_relaxation=1.0, const Real min_value_limiter=std::numeric_limits< Real >::min())
Solve an equation which contains an advection term that depends on the solution of the segregated Nav...
NumericVector< Number > * rhs
const Real _momentum_l_abs_tol
Absolute linear tolerance for the momentum equation(s).
Aggregated storage for residuals, tolerances, and indices used in convergence checks.
void setSolution(const NumericVector< Number > &soln)
const bool _has_active_scalar_systems
Boolean for easy check if a active scalar systems shall be solved or not.
virtual std::pair< unsigned int, Real > solve(SparseMatrix< T > &matrix_in, NumericVector< T > &solution_in, NumericVector< T > &rhs_in, const std::optional< double > tol=std::nullopt, const std::optional< unsigned int > m_its=std::nullopt) override
const Real _active_scalar_l_abs_tol
Absolute linear tolerance for the active scalar equation(s).
virtual LinearSolver< Number > * get_linear_solver() const override
void initializeCHTCouplingFields()
Initialize the coupling fields for the conjugate heat transfer routines.
Definition: CHTHandler.C:371
RhieChowMassFlux * _rc_uo
Pointer to the segregated RhieChow interpolation object.
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
void relaxRightHandSide(NumericVector< Number > &rhs_in, const NumericVector< Number > &solution_in, const NumericVector< Number > &diff_diagonal)
Relax the right hand side of an equation, this needs to be called once and the system matrix has been...
std::map< std::string, Real > real_valued_data
void setupConjugateHeatTransferContainers()
Set up the boundary condition pairs, functor maps, and every other necessary structure for the conjug...
Definition: CHTHandler.C:291
virtual std::pair< unsigned int, Real > correctVelocity(const bool subtract_updated_pressure, const bool recompute_face_mass_flux, const SolverParams &solver_params)
Computes new velocity field based on computed pressure gradients.
std::vector< unsigned int > _pm_radiation_system_numbers
void computeGradients()
void resetCHTConvergence()
Reset the convergence data.
Definition: CHTHandler.h:158
bool converged(const std::vector< std::pair< unsigned int, Real >> &residuals, const std::vector< Real > &abs_tolerances)
Based on the residuals, determine if the iterative process converged or not.
const Real _pressure_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in pressure.
const Real _pressure_variable_relaxation
The user-defined relaxation parameter for the pressure variable.
std::size_t energy_index
Index of the energy equation in ns_residuals.
virtual void computeLinearSystemSys(libMesh::LinearImplicitSystem &sys, libMesh::SparseMatrix< libMesh::Number > &system_matrix, NumericVector< libMesh::Number > &rhs, const bool compute_gradients=true)
const Real _momentum_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in momentum.
const std::vector< SolverSystemName > & _pm_radiation_system_names
The names of the participating media radiation systems.
virtual const std::string & name() const
const std::vector< SolverSystemName > & _passive_scalar_system_names
The names of the passive scalar systems.
const unsigned int _solid_energy_sys_number
The number of the system corresponding to the solid energy equation.
std::vector< LinearSystem * > _active_scalar_systems
Pointer(s) to the system(s) corresponding to the active scalar equation(s)
SIMPLESolverConfiguration _passive_scalar_linear_control
Options for the linear solver of the passive scalar equation(s)
void computeHbyA(const bool with_updated_pressure, const bool verbose)
Computes the inverse of the diagonal (1/A) of the system matrix plus the H/A components for the press...
virtual void execute(const ExecFlagType &exec_type)
Moose::PetscSupport::PetscOptions _energy_petsc_options
Options which hold the petsc settings for the fluid energy equation.
std::vector< std::size_t > turbulence_indices
Indices of turbulence surrogate equations in ns_residuals.
LinearSystem & _pressure_system
Reference to the linear system corresponding to the pressure equation.
std::vector< unsigned int > _momentum_system_numbers
The number(s) of the system(s) corresponding to the momentum equation(s)
SIMPLESolverConfiguration _pressure_linear_control
Options for the linear solver of the pressure equation.
MultiMooseEnum getCommonPetscFlags()
void linkEnergySystems(SystemBase *solid_energy_system, SystemBase *fluid_energy_system, std::vector< SystemBase *> pm_radiation_systems)
Link energy systems.
Definition: CHTHandler.C:91
LinearSystem * _energy_system
Pointer to the linear system corresponding to the fluid energy equation.
const unsigned int _energy_sys_number
The number of the system corresponding to the energy equation.
void incrementCHTIterators()
Increment CHT iterators in the loop.
Definition: CHTHandler.h:164
const bool _has_pm_radiation_systems
Boolean for easy check if participating media radiation systems shall be solved or not...
Moose::PetscSupport::PetscOptions _passive_scalar_petsc_options
Options which hold the petsc settings for the passive scalar equation(s)
virtual unsigned int dimension() const
std::map< std::string, int > int_valued_data
bool converged() const
Check if CHT iteration converged.
Definition: CHTHandler.C:495
ResidualStorage setupResidualStorage() const
Build residual/tolerance vectors and associated indices for all enabled systems.
virtual std::unique_ptr< SparseMatrix< T > > zero_clone() const=0
void linkMomentumPressureSystems(const std::vector< LinearSystem *> &momentum_systems, const LinearSystem &pressure_system, const std::vector< unsigned int > &momentum_system_numbers)
Update the momentum system-related information.
Moose::PetscSupport::PetscOptions _momentum_petsc_options
Options which hold the petsc settings for the momentum equation.
const Real _pressure_l_abs_tol
Absolute linear tolerance for the pressure equation.
const std::vector< Real > _passive_scalar_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in passive scalars.
std::unique_ptr< NumericVector< Number > > solution
dof_id_type _pressure_pin_dof
The dof ID where the pressure needs to be pinned.
void computeCellVelocity()
Update the cell values of the velocity variables.
Moose::SolveType _type
const std::vector< SolverSystemName > & _turbulence_system_names
The names of the turbulence systems.
const std::vector< Real > _pm_radiation_equation_relaxation
The user-defined relaxation parameter(s) for the participating media radiation equation(s) ...
virtual bool solve() override
Performs the momentum pressure coupling.
virtual void print(std::ostream &os=libMesh::out) const
const bool _pin_pressure
If the pressure needs to be pinned.
const Real _energy_l_abs_tol
Absolute linear tolerance for the energy equations.
const std::vector< Real > _pm_radiation_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in participating media radiation...
std::string stringify(const T &t)
void petscSetOptions(const PetscOptions &po, const SolverParams &solver_params, FEProblemBase *const problem=nullptr)
std::vector< std::size_t > momentum_indices
Indices of momentum equations in ns_residuals.
void sumIntegratedFluxes()
Sum the integrated fluxes over all processors.
Definition: CHTHandler.C:465
virtual void linkRhieChowUserObject() override
Fetch the Rhie Chow user object that is reponsible for determining face velocities and mass flux...
LinearSystem & getLinearSystem(unsigned int sys_num)
void set_solver_configuration(SolverConfiguration &solver_configuration)
const std::vector< Real > _turbulence_equation_relaxation
The user-defined relaxation parameter(s) for the turbulence equation(s)
const std::vector< SolverSystemName > & _momentum_system_names
The names of the momentum systems.
std::vector< LinearSystem * > _turbulence_systems
Pointer(s) to the system(s) corresponding to the turbulence equation(s)
const ExecFlagType EXEC_NONLINEAR
const Real _pm_radiation_l_abs_tol
Absolute linear tolerance for the participating media radiation equation(s).
const std::vector< Real > _passive_scalar_equation_relaxation
The user-defined relaxation parameter(s) for the passive scalar equation(s)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< SolverSystemName > & _active_scalar_system_names
The names of the active scalar systems.
MooseApp & _app
const Real _energy_equation_relaxation
The user-defined relaxation parameter for the energy equation.
SparseMatrix< Number > * matrix
void setCurrentLinearSystem(unsigned int sys_num)
std::vector< LinearSystem * > _systems_to_solve
Shortcut to every linear system that we solve for here.
const Real _pressure_pin_value
The value we want to enforce for pressure.
virtual std::vector< std::pair< unsigned int, Real > > solveMomentumPredictor() override
Solve a momentum predictor step with a fixed pressure field.
const Real _turbulence_l_abs_tol
Absolute linear tolerance for the turbulence equation(s).
virtual MooseMesh & mesh() override
unsigned int linearSysNum(const LinearSystemName &linear_sys_name) const override
void deduceCHTBoundaryCoupling()
Run error checks and make sure everything works.
Definition: CHTHandler.C:106
virtual std::pair< unsigned int, Real > solvePressureCorrector() override
Solve a pressure corrector step.
Moose::PetscSupport::PetscOptions _active_scalar_petsc_options
Options which hold the petsc settings for the active scalar equation(s)
std::unique_ptr< NumericVector< Number > > current_local_solution
virtual const NumericVector< Number > * solutionPreviousNewton() const
Solve class serving as a base class for the two SIMPLE solvers that operate with different assembly a...
const bool _has_passive_scalar_systems
Boolean for easy check if a passive scalar systems shall be solved or not.
const std::vector< Real > _active_scalar_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in active scalars.
virtual bool enabled() const override final
Check if CHT treatment is needed.
Definition: CHTHandler.h:152
std::size_t pressure_index
Index of the pressure equation in ns_residuals.
bool converged
This will be an initial indicator if we have something to solve.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
const ConsoleStream _console
static InputParameters validParams()
Definition: CHTHandler.C:25
const Real _solid_energy_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in solid energy.
std::vector< unsigned int > _active_scalar_system_numbers
SIMPLESolverConfiguration _solid_energy_linear_control
Options for the linear solver of the energy equation.
std::vector< LinearSystem * > _momentum_systems
Pointer(s) to the system(s) corresponding to the momentum equation(s)
const bool _continue_on_max_its
If solve should continue if maximum number of iterations is hit.
Moose::PetscSupport::PetscOptions _pm_radiation_petsc_options
Options which hold the petsc settings for the participating media radiation equation(s) ...
std::vector< std::size_t > active_scalar_indices
Indices of active scalar equations in ns_residuals.
std::vector< Real > _turbulence_field_min_limit
The user-defined lower limit for turbulent quantities e.g. k, eps/omega, etc..
void constrainSystem(SparseMatrix< Number > &mx, NumericVector< Number > &rhs, const Real desired_value, const dof_id_type dof_id)
Implicitly constrain the system by adding a factor*(u-u_desired) to it at a desired dof value...
std::vector< std::size_t > pm_radiation_indices
Indices of participating media radiation equations in ns_residuals.
void limitSolutionUpdate(NumericVector< Number > &solution, const Real min_limit=std::numeric_limits< Real >::epsilon(), const Real max_limit=1e10)
Limit a solution to its minimum and maximum bounds: $u = min(max(u, min_limit), max_limit)$.
bool isRecovering() const
void relaxSolutionUpdate(NumericVector< Number > &vec_new, const NumericVector< Number > &vec_old, const Real relaxation_factor)
Relax the update on a solution field using the following approach: $u = u_{old}+ (u - u_{old})$...
std::vector< std::pair< unsigned int, Real > > ns_residuals
(linear iterations, normalized residual) entries in the order used by NS::FV::converged() ...
const std::vector< Real > _turbulence_absolute_tolerance
The user-defined absolute tolerance for determining the convergence turbulence variables.
const bool _should_solve_momentum
Flags controlling which systems are actively solved (can be used with restart to freeze flow) ...
std::vector< LinearSystem * > _pm_radiation_systems
Pointer(s) to the system(s) corresponding to the participting media radiation equation(s) ...
auto index_range(const T &sizable)
void print(std::ostream &os=libMesh::out, const bool sparse=false) const
std::vector< unsigned int > _passive_scalar_system_numbers
NS::FV::CHTHandler _cht
********************** Conjugate heat transfer variables ************** //
void initCouplingField()
Initialize the coupling fields (HbyA and Ainv)
Moose::PetscSupport::PetscOptions _pressure_petsc_options
Options which hold the petsc settings for the pressure equation.
virtual System & system() override
Definition: NS.h:200
const bool _has_solid_energy_system
Boolean for easy check if a solid energy system shall be solved or not.
void initFaceMassFlux()
Initialize the container for face velocities.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
const unsigned int _pressure_sys_number
The number of the system corresponding to the pressure equation.