https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SIMPLESolveNonlinearAssembly.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"
13#include "NonlinearSystemBase.h"
14
15#include "libmesh/nonlinear_implicit_system.h"
16
17using namespace libMesh;
18
21{
23
24 params.addParam<TagName>("pressure_gradient_tag",
25 "pressure_momentum_kernels",
26 "The name of the tags associated with the kernels in the momentum "
27 "equations which are not related to the pressure gradient.");
28
29 return params;
30}
31
33 : SIMPLESolveBase(ex),
34 _pressure_sys_number(_problem.nlSysNum(getParam<SolverSystemName>("pressure_system"))),
35 _pressure_system(_problem.getNonlinearSystemBase(_pressure_sys_number)),
36 _has_turbulence_systems(!getParam<std::vector<SolverSystemName>>("turbulence_systems").empty()),
37 _energy_sys_number(_has_energy_system
38 ? _problem.nlSysNum(getParam<SolverSystemName>("energy_system"))
40 _energy_system(_has_energy_system ? &_problem.getNonlinearSystemBase(_energy_sys_number)
41 : nullptr),
42 _solid_energy_sys_number(
43 _has_solid_energy_system
44 ? _problem.nlSysNum(getParam<SolverSystemName>("solid_energy_system"))
46 _solid_energy_system(_has_solid_energy_system
47 ? &_problem.getNonlinearSystemBase(_solid_energy_sys_number)
48 : nullptr),
49 _turbulence_system_names(getParam<std::vector<SolverSystemName>>("turbulence_systems")),
50 _turbulence_equation_relaxation(getParam<std::vector<Real>>("turbulence_equation_relaxation")),
51 _turbulence_field_min_limit(getParam<std::vector<Real>>("turbulence_field_min_limit")),
52 _turbulence_l_abs_tol(getParam<Real>("turbulence_l_abs_tol")),
53 _turbulence_absolute_tolerance(getParam<std::vector<Real>>("turbulence_absolute_tolerance")),
54 _pressure_tag_name(getParam<TagName>("pressure_gradient_tag")),
55 _pressure_tag_id(_problem.addVectorTag(_pressure_tag_name))
56{
57 // We disable this considering that this object passes petsc options a little differently
59
60 // We fetch the system numbers for the momentum components plus add vectors
61 // for removing the contribution from the pressure gradient terms.
62 for (auto system_i : index_range(_momentum_system_names))
63 {
65 _momentum_systems.push_back(
67 _momentum_systems[system_i]->addVector(_pressure_tag_id, false, ParallelType::PARALLEL);
68
69 // We disable this considering that this object passes petsc options a little differently
70 _momentum_systems[system_i]->system().prefix_with_name(false);
71 }
72
74 for (auto system_i : index_range(_passive_scalar_system_names))
75 {
80
81 // We disable this considering that this object passes petsc options a little differently
82 _passive_scalar_systems[system_i]->system().prefix_with_name(false);
83 }
84
86 {
87 for (auto system_i : index_range(_turbulence_system_names))
88 {
90 _turbulence_systems.push_back(
92
93 // We disable this considering that this object passes petsc options a little differently
94 _turbulence_systems[system_i]->system().prefix_with_name(false);
95 }
96
97 // We check for input errors with regards to the turbulence equations. At the same time, we
98 // set up the corresponding system numbers
100 paramError("turbulence_equation_relaxation",
101 "The number of equation relaxation parameters does not match the number of "
102 "turbulence scalar equations!");
104 paramError("turbulence_absolute_tolerance",
105 "The number of absolute tolerances does not match the number of "
106 "turbulence equations!");
107 if (_turbulence_field_min_limit.empty())
108 // If no minimum bounds are given, initialize to default value 1e-8
111 paramError("turbulence_field_min_limit",
112 "The number of lower bounds for turbulent quantities does not match the "
113 "number of turbulence equations!");
114 }
115
116 if (isParamValid("solid_energy_system") && !_has_energy_system)
118 "solid_energy_system",
119 "We cannot solve a solid energy system without solving for the fluid energy as well!");
120
122 {
123 const auto & turbulence_petsc_options = getParam<MultiMooseEnum>("turbulence_petsc_options");
124 const auto & turbulence_petsc_pair_options = getParam<MooseEnumItem, std::string>(
125 "turbulence_petsc_options_iname", "turbulence_petsc_options_value");
127 turbulence_petsc_options, "", *this, _turbulence_petsc_options);
128 Moose::PetscSupport::addPetscPairsToPetscOptions(turbulence_petsc_pair_options,
130 "",
131 *this,
133
134 _turbulence_linear_control.real_valued_data["rel_tol"] = getParam<Real>("turbulence_l_tol");
135 _turbulence_linear_control.real_valued_data["abs_tol"] = getParam<Real>("turbulence_l_abs_tol");
137 getParam<unsigned int>("turbulence_l_max_its");
138 }
139 else
140 checkDependentParameterError("turbulence_system",
141 {"turbulence_petsc_options",
142 "turbulence_petsc_options_iname",
143 "turbulence_petsc_options_value",
144 "turbulence_l_tol",
145 "turbulence_l_abs_tol",
146 "turbulence_l_max_its",
147 "turbulence_equation_relaxation",
148 "turbulence_absolute_tolerance"},
149 false);
150}
151
152void
154{
155 // Fetch the segregated rhie-chow object and transfer some information about the momentum
156 // system(s)
158 &getUserObject<INSFVRhieChowInterpolatorSegregated>("rhie_chow_user_object"));
160
161 // Initialize the face velocities in the RC object
163}
164
165std::vector<std::pair<unsigned int, Real>>
167{
168 // Temporary storage for the (flux-normalized) residuals form
169 // different momentum components
170 std::vector<std::pair<unsigned int, Real>> its_normalized_residuals;
171
172 // We can create this here with the assumption that every momentum component has the same number
173 // of dofs
174 auto zero_solution = _momentum_systems[0]->system().current_local_solution->zero_clone();
175
176 // Solve the momentum equations.
177 // TO DO: These equations are VERY similar. If we can store the differences (things coming from
178 // BCs for example) separately, it is enough to construct one matrix.
179 for (const auto system_i : index_range(_momentum_systems))
180 {
182
183 // We will need the right hand side and the solution of the next component
184 NonlinearImplicitSystem & momentum_system =
185 libMesh::cast_ref<NonlinearImplicitSystem &>(_momentum_systems[system_i]->system());
186
187 PetscLinearSolver<Real> & momentum_solver =
188 libMesh::cast_ref<PetscLinearSolver<Real> &>(*momentum_system.get_linear_solver());
189
190 NumericVector<Number> & solution = *(momentum_system.solution);
191 NumericVector<Number> & rhs = *(momentum_system.rhs);
192 SparseMatrix<Number> & mmat = *(momentum_system.matrix);
193
194 auto diff_diagonal = solution.zero_clone();
195
196 // We plug zero in this to get the system matrix and the right hand side of the linear problem
197 _problem.computeResidualAndJacobian(*zero_solution, rhs, mmat);
198 // Sadly, this returns -b so we multiply with -1
199 rhs.scale(-1.0);
200
201 // Still need to relax the right hand side with the same vector
203 NS::FV::relaxRightHandSide(rhs, solution, *diff_diagonal);
204
205 // The normalization factor depends on the right hand side so we need to recompute it for this
206 // component
207 Real norm_factor = NS::FV::computeNormalizationFactor(solution, mmat, rhs);
208
209 // Very important, for deciding the convergence, we need the unpreconditioned
210 // norms in the linear solve
211 LibmeshPetscCall(KSPSetNormType(momentum_solver.ksp(), KSP_NORM_UNPRECONDITIONED));
212 // Solve this component. We don't update the ghosted solution yet, that will come at the end
213 // of the corrector step. Also setting the linear tolerances and maximum iteration counts.
216
217 // We solve the equation
218 auto its_resid_pair = momentum_solver.solve(mmat, mmat, solution, rhs);
219 momentum_system.update();
220
221 // Save the normalized residual
222 its_normalized_residuals.push_back(
223 std::make_pair(its_resid_pair.first, momentum_solver.get_initial_residual() / norm_factor));
224
225 if (_print_fields)
226 {
227 _console << " matrix when we solve " << std::endl;
228 mmat.print();
229 _console << " rhs when we solve " << std::endl;
230 rhs.print();
231 _console << " velocity solution component " << system_i << std::endl;
232 solution.print();
233 _console << "Norm factor " << norm_factor << std::endl;
234 _console << Moose::stringify(momentum_solver.get_initial_residual()) << std::endl;
235 }
236
237 _momentum_systems[system_i]->setSolution(*(momentum_system.current_local_solution));
238 _momentum_systems[system_i]->copyPreviousSolutions(Moose::SolutionIterationType::Nonlinear);
239 }
240
241 return its_normalized_residuals;
242}
243
244std::pair<unsigned int, Real>
246{
248
249 // We will need some members from the implicit nonlinear system
250 NonlinearImplicitSystem & pressure_system =
251 libMesh::cast_ref<NonlinearImplicitSystem &>(_pressure_system.system());
252
253 // We will need the solution, the right hand side and the matrix
254 NumericVector<Number> & current_local_solution = *(pressure_system.current_local_solution);
255 NumericVector<Number> & solution = *(pressure_system.solution);
256 SparseMatrix<Number> & mmat = *(pressure_system.matrix);
257 NumericVector<Number> & rhs = *(pressure_system.rhs);
258
259 // Fetch the linear solver from the system
260 PetscLinearSolver<Real> & pressure_solver =
261 libMesh::cast_ref<PetscLinearSolver<Real> &>(*pressure_system.get_linear_solver());
262
263 // We need a zero vector to be able to emulate the Ax=b system by evaluating the
264 // residual and jacobian. Unfortunately, this will leave us with the -b on the right hand side
265 // so we correct it by multiplying it with (-1)
266 auto zero_solution = current_local_solution.zero_clone();
267 _problem.computeResidualAndJacobian(*zero_solution, rhs, mmat);
268 rhs.scale(-1.0);
269
270 if (_print_fields)
271 {
272 _console << "Pressure matrix" << std::endl;
273 mmat.print();
274 }
275
276 // We compute the normalization factors based on the fluxes
277 Real norm_factor = NS::FV::computeNormalizationFactor(solution, mmat, rhs);
278
279 // We need the non-preconditioned norm to be consistent with the norm factor
280 LibmeshPetscCall(KSPSetNormType(pressure_solver.ksp(), KSP_NORM_UNPRECONDITIONED));
281
282 // Setting the linear tolerances and maximum iteration counts
285
286 if (_pin_pressure)
288
289 auto its_res_pair = pressure_solver.solve(mmat, mmat, solution, rhs);
290 pressure_system.update();
291
292 if (_print_fields)
293 {
294 _console << " rhs when we solve pressure " << std::endl;
295 rhs.print();
296 _console << " Pressure " << std::endl;
297 solution.print();
298 _console << "Norm factor " << norm_factor << std::endl;
299 }
300
301 _pressure_system.setSolution(current_local_solution);
302
303 return std::make_pair(its_res_pair.first, pressure_solver.get_initial_residual() / norm_factor);
304}
305
306std::pair<unsigned int, Real>
308 NonlinearSystemBase & system,
309 const Real relaxation_factor,
310 libMesh::SolverConfiguration & solver_config,
311 const Real absolute_tol)
312{
314
315 // We will need some members from the implicit nonlinear system
316 NonlinearImplicitSystem & ni_system =
317 libMesh::cast_ref<NonlinearImplicitSystem &>(system.system());
318
319 // We will need the solution, the right hand side and the matrix
320 NumericVector<Number> & current_local_solution = *(ni_system.current_local_solution);
321 NumericVector<Number> & solution = *(ni_system.solution);
322 SparseMatrix<Number> & mmat = *(ni_system.matrix);
323 NumericVector<Number> & rhs = *(ni_system.rhs);
324
325 // We need a vector that stores the (diagonal_relaxed-original_diagonal) vector
326 auto diff_diagonal = solution.zero_clone();
327
328 // Fetch the linear solver from the system
329 PetscLinearSolver<Real> & linear_solver =
330 libMesh::cast_ref<PetscLinearSolver<Real> &>(*ni_system.get_linear_solver());
331
332 // We need a zero vector to be able to emulate the Ax=b system by evaluating the
333 // residual and jacobian. Unfortunately, this will leave us with the -b on the right hand side
334 // so we correct it by multiplying it with (-1)
335 auto zero_solution = current_local_solution.zero_clone();
336 _problem.computeResidualAndJacobian(*zero_solution, rhs, mmat);
337 rhs.scale(-1.0);
338
339 // Go and relax the system matrix and the right hand side
340 NS::FV::relaxMatrix(mmat, relaxation_factor, *diff_diagonal);
341 NS::FV::relaxRightHandSide(rhs, solution, *diff_diagonal);
342
343 if (_print_fields)
344 {
345 _console << system.name() << " system matrix" << std::endl;
346 mmat.print();
347 _console << system.name() << " RHS vector" << std::endl;
348 rhs.print();
349 }
350
351 // We compute the normalization factors based on the fluxes
352 Real norm_factor = NS::FV::computeNormalizationFactor(solution, mmat, rhs);
353
354 // We need the non-preconditioned norm to be consistent with the norm factor
355 LibmeshPetscCall(KSPSetNormType(linear_solver.ksp(), KSP_NORM_UNPRECONDITIONED));
356
357 // Setting the linear tolerances and maximum iteration counts
358 solver_config.real_valued_data["abs_tol"] = absolute_tol * norm_factor;
359 linear_solver.set_solver_configuration(solver_config);
360
361 // Solve the system and update current local solution
362 auto its_res_pair = linear_solver.solve(mmat, mmat, solution, rhs);
363 ni_system.update();
364
365 if (_print_fields)
366 {
367 _console << " rhs when we solve " << system.name() << std::endl;
368 rhs.print();
369 _console << system.name() << " solution " << std::endl;
370 solution.print();
371 _console << " Norm factor " << norm_factor << std::endl;
372 }
373
374 system.setSolution(current_local_solution);
375
376 return std::make_pair(its_res_pair.first, linear_solver.get_initial_residual() / norm_factor);
377}
378
379std::pair<unsigned int, Real>
381{
383
384 // We will need some members from the implicit nonlinear system
385 NonlinearImplicitSystem & se_system =
386 libMesh::cast_ref<NonlinearImplicitSystem &>(_solid_energy_system->system());
387
388 // We will need the solution, the right hand side and the matrix
389 NumericVector<Number> & current_local_solution = *(se_system.current_local_solution);
390 NumericVector<Number> & solution = *(se_system.solution);
391 SparseMatrix<Number> & mat = *(se_system.matrix);
392 NumericVector<Number> & rhs = *(se_system.rhs);
393
394 // Fetch the linear solver from the system
395 PetscLinearSolver<Real> & se_solver =
396 libMesh::cast_ref<PetscLinearSolver<Real> &>(*se_system.get_linear_solver());
397
398 // We need a zero vector to be able to emulate the Ax=b system by evaluating the
399 // residual and jacobian. Unfortunately, this will leave us with the -b on the righ hand side
400 // so we correct it by multiplying it with (-1)
401 auto zero_solution = current_local_solution.zero_clone();
402 _problem.computeResidualAndJacobian(*zero_solution, rhs, mat);
403 rhs.scale(-1.0);
404
405 if (_print_fields)
406 {
407 _console << "Solid energy matrix" << std::endl;
408 mat.print();
409 }
410
411 // We compute the normalization factors based on the fluxes
412 Real norm_factor = NS::FV::computeNormalizationFactor(solution, mat, rhs);
413
414 // We need the non-preconditioned norm to be consistent with the norm factor
415 LibmeshPetscCall(KSPSetNormType(se_solver.ksp(), KSP_NORM_UNPRECONDITIONED));
416
417 // Setting the linear tolerances and maximum iteration counts
420
421 auto its_res_pair = se_solver.solve(mat, mat, solution, rhs);
422 se_system.update();
423
424 if (_print_fields)
425 {
426 _console << " Solid energy rhs " << std::endl;
427 rhs.print();
428 _console << " Solid temperature " << std::endl;
429 solution.print();
430 _console << "Norm factor " << norm_factor << std::endl;
431 }
432
433 _solid_energy_system->setSolution(current_local_solution);
434
435 return std::make_pair(its_res_pair.first, se_solver.get_initial_residual() / norm_factor);
436}
437
438bool
440{
442
443 // Dummy solver parameter file which is needed for switching petsc options
444 SolverParams solver_params;
445 solver_params._type = Moose::SolveType::ST_LINEAR;
446 solver_params._line_search = Moose::LineSearchType::LS_NONE;
447
448 // Initialize the quantities which matter in terms of the iteration
449 unsigned int iteration_counter = 0;
450
451 // Assign residuals to general residual vector
452 unsigned int no_systems =
455 no_systems += _turbulence_systems.size();
456 std::vector<std::pair<unsigned int, Real>> ns_its_residuals(no_systems, std::make_pair(0, 1.0));
457 std::vector<Real> ns_abs_tols(_momentum_systems.size(), _momentum_absolute_tolerance);
458 ns_abs_tols.push_back(_pressure_absolute_tolerance);
460 {
461 ns_abs_tols.push_back(_energy_absolute_tolerance);
463 ns_abs_tols.push_back(_solid_energy_absolute_tolerance);
464 }
466 for (auto system_i : index_range(_turbulence_absolute_tolerance))
467 ns_abs_tols.push_back(_turbulence_absolute_tolerance[system_i]);
468
469 bool converged = false;
470 // Loop until converged or hit the maximum allowed iteration number
471 while (iteration_counter < _num_iterations && !converged)
472 {
473 iteration_counter++;
474 // Resdiual index
475 size_t residual_index = 0;
476
477 // Execute all objects tagged as nonlinear
478 // This will execute everything in the problem at nonlinear, including the aux kernels.
479 // This way we compute the aux kernels before the momentum equations are solved.
481
482 // We clear the caches in the momentum and pressure variables
483 for (auto system_i : index_range(_momentum_systems))
484 _momentum_systems[system_i]->residualSetup();
486
487 // If we solve for energy, we clear the caches there too
489 {
493 }
494
495 // If we solve for turbulence, we clear the caches there too
497 for (auto system_i : index_range(_turbulence_systems))
498 _turbulence_systems[system_i]->residualSetup();
499
500 // We set the preconditioner/controllable parameters through petsc options. Linear
501 // tolerances will be overridden within the solver. In case of a segregated momentum
502 // solver, we assume that every velocity component uses the same preconditioner
504
505 // Solve the momentum predictor step
506 auto momentum_residual = solveMomentumPredictor();
507 for (const auto system_i : index_range(momentum_residual))
508 ns_its_residuals[system_i] = momentum_residual[system_i];
509
510 // Compute the coupling fields between the momentum and pressure equations
512
513 // We set the preconditioner/controllable parameters for the pressure equations through
514 // petsc options. Linear tolerances will be overridden within the solver.
516
517 // Solve the pressure corrector
518 ns_its_residuals[momentum_residual.size()] = solvePressureCorrector();
519 // We need this to make sure we evaluate cell gradients for the nonorthogonal correction in
520 // the face velocity update
522
523 // Compute the face velocity which is used in the advection terms
525
526 auto & pressure_current_solution = *(_pressure_system.system().current_local_solution.get());
527 auto & pressure_old_solution = *(_pressure_system.solutionPreviousNewton());
528 // Relax the pressure update for the next momentum predictor
530 pressure_current_solution, pressure_old_solution, _pressure_variable_relaxation);
531
532 // Overwrite old solution
533 pressure_old_solution = pressure_current_solution;
534 _pressure_system.setSolution(pressure_current_solution);
535
536 // We clear out the caches so that the gradients can be computed with the relaxed solution
538
539 // Reconstruct the cell velocity as well to accelerate convergence
541
542 // Update residual index
543 residual_index = momentum_residual.size();
544
545 // If we have an energy equation, solve it here. We assume the material properties in the
546 // Navier-Stokes equations depend on temperature, therefore we can not solve for temperature
547 // outside of the velocity-pressure loop
549 {
550 // We set the preconditioner/controllable parameters through petsc options. Linear
551 // tolerances will be overridden within the solver.
553 residual_index += 1;
554 ns_its_residuals[residual_index] = solveAdvectedSystem(_energy_sys_number,
559
561 {
562 // We set the preconditioner/controllable parameters through petsc options. Linear
563 // tolerances will be overridden within the solver.
565 residual_index += 1;
566 ns_its_residuals[residual_index] = solveSolidEnergySystem();
567 }
568 }
569
570 // If we have an turbulence equations, we solve it here. We solve it inside the
571 // momentum-pressure loop because it affects the turbulent viscosity
573 {
575
576 for (auto system_i : index_range(_turbulence_systems))
577 {
578 residual_index += 1;
579 ns_its_residuals[residual_index] =
581 *_turbulence_systems[system_i],
585
586 auto & current_solution =
587 *(_turbulence_systems[system_i]->system().current_local_solution.get());
588 NS::FV::limitSolutionUpdate(current_solution, _turbulence_field_min_limit[system_i]);
589
590 // Relax the turbulence update for the next momentum predictor
591 auto & old_solution = *(_turbulence_systems[system_i]->solutionPreviousNewton());
592
593 // Relax the pressure update for the next momentum predictor
595 current_solution, old_solution, _turbulence_equation_relaxation[system_i]);
596
597 // Overwrite old solution
598 old_solution = current_solution;
599 _turbulence_systems[system_i]->setSolution(current_solution);
600
601 // We clear out the caches so that the gradients can be computed with the relaxed solution
602 _turbulence_systems[system_i]->residualSetup();
603 }
604 }
605
606 // Printing residuals
607 residual_index = 0;
608 _console << "Iteration " << iteration_counter << " Initial residual norms:" << std::endl;
609 for (auto system_i : index_range(_momentum_systems))
610 _console << " Momentum equation:"
611 << (_momentum_systems.size() > 1
612 ? std::string(" Component ") + std::to_string(system_i + 1) +
613 std::string(" ")
614 : std::string(" "))
615 << COLOR_GREEN << ns_its_residuals[system_i].second << COLOR_DEFAULT << std::endl;
616 _console << " Pressure equation: " << COLOR_GREEN
617 << ns_its_residuals[momentum_residual.size()].second << COLOR_DEFAULT << std::endl;
618 residual_index = momentum_residual.size();
619
621 {
622 residual_index += 1;
623 _console << " Energy equation: " << COLOR_GREEN << ns_its_residuals[residual_index].second
624 << COLOR_DEFAULT << std::endl;
626 {
627 residual_index += 1;
628 _console << " Solid energy equation: " << COLOR_GREEN
629 << ns_its_residuals[residual_index].second << COLOR_DEFAULT << std::endl;
630 }
631 }
632
634 {
635 _console << "Turbulence Iteration " << std::endl;
636 for (auto system_i : index_range(_turbulence_systems))
637 {
638 residual_index += 1;
639 _console << _turbulence_systems[system_i]->name() << " " << COLOR_GREEN
640 << ns_its_residuals[residual_index].second << COLOR_DEFAULT << std::endl;
641 }
642 }
643
644 converged = NS::FV::converged(ns_its_residuals, ns_abs_tols);
645 }
646
647 converged = _continue_on_max_its ? true : converged;
648
649 // Now we solve for the passive scalar equations, they should not influence the solution of the
650 // system above. The reason why we need more than one iteration is due to the matrix relaxation
651 // which can be used to stabilize the equations
653 {
654 _console << " Passive Scalar Iteration " << iteration_counter << std::endl;
655
656 // We set the options used by Petsc (preconditioners etc). We assume that every passive
657 // scalar equation uses the same options for now.
659
660 iteration_counter = 0;
661 std::vector<std::pair<unsigned int, Real>> passive_scalar_residuals(
662 _passive_scalar_systems.size(), std::make_pair(0, 1.0));
663
664 bool passive_scalar_converged =
665 NS::FV::converged(passive_scalar_residuals, _passive_scalar_absolute_tolerance);
666 while (iteration_counter < _num_iterations && !passive_scalar_converged)
667 {
668 // We clear the caches in the passive scalar variables
669 for (auto system_i : index_range(_passive_scalar_systems))
670 _passive_scalar_systems[system_i]->residualSetup();
671
672 iteration_counter++;
673
674 // Solve the passive scalar equations
675 for (auto system_i : index_range(_passive_scalar_systems))
676 passive_scalar_residuals[system_i] =
678 *_passive_scalar_systems[system_i],
682
683 _console << "Iteration " << iteration_counter << " Initial residual norms:" << std::endl;
684 for (auto system_i : index_range(_passive_scalar_systems))
685 _console << _passive_scalar_systems[system_i]->name() << " " << COLOR_GREEN
686 << passive_scalar_residuals[system_i].second << COLOR_DEFAULT << std::endl;
687
688 passive_scalar_converged =
689 NS::FV::converged(passive_scalar_residuals, _passive_scalar_absolute_tolerance);
690 }
691
692 converged = _continue_on_max_its ? true : passive_scalar_converged;
693 }
694
695 return converged;
696}
697
698void
700{
701 // check to make sure that we don't have any time kernels in this simulation (Steady State)
702 for (const auto system : _momentum_systems)
703 checkTimeKernels(*system);
704
706
708 {
712 }
713
715 for (const auto system : _passive_scalar_systems)
716 checkTimeKernels(*system);
717
719 for (const auto system : _turbulence_systems)
720 checkTimeKernels(*system);
721}
722
723void
725{
726 // check to make sure that we don't have any time kernels in this simulation (Steady State)
727 if (system.containsTimeKernel())
728 mooseError("You have specified time kernels in your steady state simulation in system",
729 system.name());
730}
const ExecFlagType EXEC_NONLINEAR
const ConsoleStream _console
void setCurrentNonlinearSystem(const unsigned int nl_sys_num)
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
void computeResidualAndJacobian(const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual, libMesh::SparseMatrix< libMesh::Number > &jacobian)
virtual MooseMesh & mesh() override
virtual void execute(const ExecFlagType &exec_type)
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
A user object which implements the Rhie Chow interpolation for segregated momentum-pressure systems.
void computeHbyA(bool verbose)
Computes the inverse of the digaonal (1/A) of the system matrix plus the H/A components for the press...
void computeFaceVelocity()
Update the values of the face velocities in the containers.
void initFaceVelocities()
Initialize the container for face velocities.
void linkMomentumSystem(std::vector< NonlinearSystemBase * > momentum_systems, const std::vector< unsigned int > &momentum_system_numbers, const TagID pressure_gradient_tag)
Update the momentum system-related information.
void computeCellVelocity()
Update the cell values of the velocity variables.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const std::string & name() const
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
virtual unsigned int dimension() const
virtual bool containsTimeKernel() override
virtual void residualSetup() override
virtual libMesh::System & system() override
Solve class serving as a base class for the two SIMPLE solvers that operate with different assembly a...
const Real _momentum_equation_relaxation
The user-defined relaxation parameter for the momentum equation.
const bool _has_energy_system
Boolean for easy check if a fluid energy system shall be solved or not.
dof_id_type _pressure_pin_dof
The dof ID where the pressure needs to be pinned.
const std::vector< SolverSystemName > & _passive_scalar_system_names
The names of the passive scalar systems.
std::vector< unsigned int > _passive_scalar_system_numbers
const Real _pressure_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in pressure.
const std::vector< Real > _passive_scalar_equation_relaxation
The user-defined relaxation parameter(s) for the passive scalar equation(s)
const Real _pressure_l_abs_tol
Absolute linear tolerance for the pressure equation.
const Real _passive_scalar_l_abs_tol
Absolute linear tolerance for the passive scalar equation(s).
const bool _has_solid_energy_system
Boolean for easy check if a solid energy system shall be solved or not.
Moose::PetscSupport::PetscOptions _passive_scalar_petsc_options
Options which hold the petsc settings for the passive scalar equation(s)
SIMPLESolverConfiguration _pressure_linear_control
Options for the linear solver of the pressure equation.
static InputParameters validParams()
SIMPLESolverConfiguration _solid_energy_linear_control
Options for the linear solver of the energy equation.
const bool _has_passive_scalar_systems
Boolean for easy check if a passive scalar systems shall be solved or not.
const Real _momentum_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in momentum.
const Real _pressure_variable_relaxation
The user-defined relaxation parameter for the pressure variable.
const Real _momentum_l_abs_tol
Absolute linear tolerance for the momentum equation(s).
Moose::PetscSupport::PetscOptions _momentum_petsc_options
Options which hold the petsc settings for the momentum equation.
SIMPLESolverConfiguration _energy_linear_control
Options for the linear solver of the energy equation.
const Real _energy_l_abs_tol
Absolute linear tolerance for the energy equations.
const Real _pressure_pin_value
The value we want to enforce for pressure.
Moose::PetscSupport::PetscOptions _pressure_petsc_options
Options which hold the petsc settings for the pressure equation.
const bool _continue_on_max_its
If solve should continue if maximum number of iterations is hit.
void checkDependentParameterError(const std::string &main_parameter, const std::vector< std::string > &dependent_parameters, const bool should_be_defined)
const Real _energy_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in energy.
const unsigned int _num_iterations
The maximum number of momentum-pressure iterations.
const std::vector< Real > _passive_scalar_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in passive scalars.
const std::vector< SolverSystemName > & _momentum_system_names
The names of the momentum systems.
const Real _energy_equation_relaxation
The user-defined relaxation parameter for the energy equation.
SIMPLESolverConfiguration _momentum_linear_control
Options for the linear solver of the momentum equation.
SIMPLESolverConfiguration _passive_scalar_linear_control
Options for the linear solver of the passive scalar equation(s)
const Real _solid_energy_l_abs_tol
Absolute linear tolerance for the energy equations.
const bool _pin_pressure
If the pressure needs to be pinned.
Moose::PetscSupport::PetscOptions _energy_petsc_options
Options which hold the petsc settings for the fluid energy equation.
const bool _print_fields
Debug parameter which allows printing the coupling and solution vectors/matrices.
const Real _solid_energy_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in solid energy.
const std::vector< Real > _turbulence_absolute_tolerance
The user-defined absolute tolerance for determining the convergence in turbulence equations.
virtual void checkTimeKernels(NonlinearSystemBase &system)
Check if the system contains time kernels.
const bool _has_turbulence_systems
Boolean for easy check if turbulence systems shall be solved or not.
virtual std::vector< std::pair< unsigned int, Real > > solveMomentumPredictor() override
Solve a momentum predictor step with a fixed pressure field.
SIMPLESolverConfiguration _turbulence_linear_control
Options for the linear solver of the turbulence equation(s)
NonlinearSystemBase * _solid_energy_system
Pointer to the nonlinear system corresponding to the solid energy equation.
std::vector< unsigned int > _momentum_system_numbers
The number(s) of the system(s) corresponding to the momentum equation(s)
virtual std::pair< unsigned int, Real > solvePressureCorrector() override
Solve a pressure corrector step.
std::vector< Real > _turbulence_field_min_limit
The user-defined lower limit for turbulent quantities e.g. k, eps/omega, etc..
const TagID _pressure_tag_id
The ID of the tag which corresponds to the pressure gradient terms in the momentum equation.
virtual void linkRhieChowUserObject() override
Fetch the Rhie Chow user object that is reponsible for determining face velocities and mass flux.
virtual void checkIntegrity() override
Check if the user defined time kernels.
std::pair< unsigned int, Real > solveAdvectedSystem(const unsigned int system_num, NonlinearSystemBase &system, const Real relaxation_factor, libMesh::SolverConfiguration &solver_config, const Real abs_tol)
Solve an equation which contains an advection term that depends on the solution of the segregated Nav...
std::vector< unsigned int > _turbulence_system_numbers
const unsigned int _energy_sys_number
The number of the system corresponding to the energy equation.
const unsigned int _pressure_sys_number
The number of the system corresponding to the pressure equation.
std::vector< NonlinearSystemBase * > _momentum_systems
Pointer(s) to the system(s) corresponding to the momentum equation(s)
const std::vector< Real > _turbulence_equation_relaxation
The user-defined relaxation parameter(s) for the turbulence equation(s)
std::vector< NonlinearSystemBase * > _turbulence_systems
Pointer(s) to the system(s) corresponding to the turbulence equation(s)
Moose::PetscSupport::PetscOptions _turbulence_petsc_options
Options which hold the petsc settings for the turbulence equation(s)
std::pair< unsigned int, Real > solveSolidEnergySystem()
Solve the solid energy conservation equation.
INSFVRhieChowInterpolatorSegregated * _rc_uo
Pointer to the segregated RhieChow interpolation object.
const unsigned int _solid_energy_sys_number
The number of the system corresponding to the solid energy equation.
NonlinearSystemBase * _energy_system
Pointer to the nonlinear system corresponding to the fluid energy equation.
const std::vector< SolverSystemName > & _turbulence_system_names
The names of the turbulence scalar systems.
virtual bool solve() override
Performs the momentum pressure coupling.
const Real _turbulence_l_abs_tol
Absolute linear tolerance for the turbulence equation(s).
std::vector< NonlinearSystemBase * > _passive_scalar_systems
Pointer(s) to the system(s) corresponding to the passive scalar equation(s)
NonlinearSystemBase & _pressure_system
Reference to the nonlinear system corresponding to the pressure equation.
FEProblemBase & _problem
Moose::LineSearchType _line_search
Moose::SolveType _type
void setSolution(const NumericVector< Number > &soln)
virtual const NumericVector< Number > * solutionPreviousNewton() const
virtual const std::string & name() const
NumericVector< Number > * rhs
virtual LinearSolver< Number > * get_linear_solver() const
SparseMatrix< Number > * matrix
void set_solver_configuration(SolverConfiguration &solver_configuration)
virtual void print(std::ostream &os=libMesh::out) const
virtual void scale(const T factor)=0
virtual std::unique_ptr< NumericVector< T > > zero_clone() const=0
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
std::map< std::string, int > int_valued_data
std::map< std::string, Real > real_valued_data
void print(std::ostream &os=libMesh::out, const bool sparse=false) const
virtual std::unique_ptr< SparseMatrix< T > > zero_clone() const=0
std::unique_ptr< NumericVector< Number > > current_local_solution
void prefix_with_name(bool value)
std::unique_ptr< NumericVector< Number > > solution
void petscSetOptions(const PetscOptions &po, const SolverParams &solver_params, FEProblemBase *const problem=nullptr)
void addPetscFlagsToPetscOptions(const MultiMooseEnum &petsc_flags, std::string prefix, const ParallelParamObject &param_object, PetscOptions &petsc_options)
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)
std::string stringify(const T &t)
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.
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.
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...
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.
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}+\lambda (u - u_{old})...
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)$.
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...
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
auto index_range(const T &sizable)
const unsigned int invalid_uint
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real