LCOV - code coverage report
Current view: top level - src/splits - Split.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 72 81 88.9 %
Date: 2025-07-17 01:28:37 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      10             : // MOOSE includes
      11             : #include "Split.h"
      12             : #include "InputParameters.h"
      13             : #include "PetscSupport.h"
      14             : #include "FEProblem.h"
      15             : #include "Conversion.h"
      16             : #include "NonlinearSystem.h"
      17             : 
      18             : registerMooseObject("MooseApp", Split);
      19             : 
      20             : InputParameters
      21       15017 : Split::validParams()
      22             : {
      23       15017 :   InputParameters params = MooseObject::validParams();
      24       15017 :   params.addClassDescription("Field split based preconditioner for nonlinear solver.");
      25       15017 :   params.addParam<std::vector<NonlinearVariableName>>(
      26             :       "vars", {}, "Variables Split operates on (omitting this implies \"all variables\"");
      27       15017 :   params.addParam<std::vector<SubdomainName>>(
      28             :       "blocks", {}, "Mesh blocks Split operates on (omitting this implies \"all blocks\"");
      29       15017 :   params.addParam<std::vector<BoundaryName>>(
      30             :       "sides", {}, "Sidesets Split operates on (omitting this implies \"all sidesets\")");
      31       15017 :   params.addParam<std::vector<BoundaryName>>(
      32             :       "unsides",
      33             :       {},
      34             :       "Sidesets Split excludes (omitting this implies \"do not exclude any sidesets\")");
      35       15017 :   params.addParam<std::vector<std::string>>(
      36             :       "splitting", {}, "The names of the splits (subsystems) in the decomposition of this split");
      37       15017 :   params.addParam<std::vector<BoundaryName>>(
      38             :       "unside_by_var_boundary_name",
      39             :       "A map from boundary name to unside by variable, e.g. only unside for a given variable.");
      40       15017 :   params.addParam<std::vector<NonlinearVariableName>>(
      41             :       "unside_by_var_var_name",
      42             :       "A map from boundary name to unside by variable, e.g. only unside for a given variable.");
      43       15017 :   params.addParamNamesToGroup("sides unsides unside_by_var_boundary_name unside_by_var_var_name",
      44             :                               "Sideset restriction");
      45             : 
      46       15017 :   MooseEnum SplittingTypeEnum("additive multiplicative symmetric_multiplicative schur", "additive");
      47       15017 :   params.addParam<MooseEnum>("splitting_type", SplittingTypeEnum, "Split decomposition type");
      48             : 
      49       15017 :   MooseEnum SchurTypeEnum("diag upper lower full", "full");
      50       15017 :   params.addParam<MooseEnum>("schur_type", SchurTypeEnum, "Type of Schur complement");
      51             : 
      52             :   /**
      53             :    * Which preconditioning matrix to use with S = D - CA^{-1}B
      54             :    * 'Self' means use S to build the preconditioner.
      55             :    * limited choices here: PCNONE and PCLSC in PETSc
      56             :    * 'D' means the lower-right block in splitting J = [A B; C D]
      57             :    */
      58       15017 :   MooseEnum SchurPreEnum("S Sp A11", "S");
      59       15017 :   params.addParam<MooseEnum>(
      60             :       "schur_pre", SchurPreEnum, "Type of Schur complement preconditioner matrix");
      61             : 
      62       45051 :   params.addParam<MultiMooseEnum>("petsc_options",
      63       30034 :                                   Moose::PetscSupport::getCommonPetscFlags(),
      64             :                                   "PETSc flags for the FieldSplit solver");
      65       45051 :   params.addParam<MultiMooseEnum>("petsc_options_iname",
      66       30034 :                                   Moose::PetscSupport::getCommonPetscKeys(),
      67             :                                   "PETSc option names for the FieldSplit solver");
      68       15017 :   params.addParam<std::vector<std::string>>("petsc_options_value",
      69             :                                             "PETSc option values for the FieldSplit solver");
      70             : 
      71       15017 :   params.registerBase("Split");
      72       15017 :   params.registerSystemAttributeName("Split");
      73       30034 :   return params;
      74       15017 : }
      75             : 
      76         376 : Split::Split(const InputParameters & parameters)
      77             :   : MooseObject(parameters),
      78             :     Restartable(this, "Splits"),
      79         376 :     _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
      80         376 :     _vars(getParam<std::vector<NonlinearVariableName>>("vars")),
      81         376 :     _blocks(getParam<std::vector<SubdomainName>>("blocks")),
      82         376 :     _sides(getParam<std::vector<BoundaryName>>("sides")),
      83         376 :     _unsides(getParam<std::vector<BoundaryName>>("unsides")),
      84         376 :     _splitting(getParam<std::vector<std::string>>("splitting")),
      85         376 :     _splitting_type(getParam<MooseEnum>("splitting_type")),
      86         376 :     _schur_type(getParam<MooseEnum>("schur_type")),
      87         752 :     _schur_pre(getParam<MooseEnum>("schur_pre"))
      88             : {
      89         376 : }
      90             : 
      91             : void
      92         376 : Split::setup(NonlinearSystemBase & nl, const std::string & prefix)
      93             : {
      94             :   // The Split::setup() implementation does not actually depend on any
      95             :   // specific version of PETSc, so there's no need to wrap the entire
      96             :   // function.
      97             : 
      98             :   // A reference to the PetscOptions
      99         376 :   Moose::PetscSupport::PetscOptions & po = _fe_problem.getPetscOptions();
     100             :   // prefix
     101         376 :   std::string dmprefix = prefix + "dm_moose_";
     102             : 
     103         376 :   if (isParamValid("unside_by_var_boundary_name"))
     104             :   {
     105             :     const auto & unside_by_var_boundary_name =
     106          12 :         getParam<std::vector<BoundaryName>>("unside_by_var_boundary_name");
     107             :     const auto & unside_by_var_var_name =
     108          12 :         getParam<std::vector<NonlinearVariableName>>("unside_by_var_var_name");
     109             : 
     110          12 :     std::vector<std::string> vector_of_pairs;
     111          36 :     for (const auto i : index_range(unside_by_var_boundary_name))
     112          24 :       vector_of_pairs.push_back(unside_by_var_boundary_name[i] + ":" + unside_by_var_var_name[i]);
     113          12 :     po.pairs.emplace_back(dmprefix + "unside_by_var", Moose::stringify(vector_of_pairs, ","));
     114          12 :   }
     115             : 
     116             :   // var options
     117         376 :   if (!_vars.empty())
     118             :   {
     119         260 :     po.pairs.emplace_back(dmprefix + "vars", Moose::stringify(_vars, ","));
     120             : 
     121             :     // check that variables are either field or scalars
     122         520 :     for (const auto & var : _vars)
     123         260 :       if (!_fe_problem.hasVariable(var) && !_fe_problem.hasScalarVariable(var))
     124           0 :         mooseError("Variable '", var, "' specified in split '", name(), "' does not exist");
     125             :   }
     126             : 
     127             :   // block options
     128         376 :   if (!_blocks.empty())
     129           0 :     po.pairs.emplace_back(dmprefix + "blocks", Moose::stringify(_blocks, ","));
     130             : 
     131             :   // side options
     132         376 :   if (!_sides.empty())
     133          44 :     po.pairs.emplace_back(dmprefix + "sides", Moose::stringify(_sides, ","));
     134             : 
     135             :   // unside options
     136         376 :   if (!_unsides.empty())
     137          32 :     po.pairs.emplace_back(dmprefix + "unsides", Moose::stringify(_unsides, ","));
     138             : 
     139         376 :   if (!_splitting.empty())
     140             :   {
     141             :     // If this split has subsplits, it is presumed that the pc_type used to solve this split's
     142             :     // subsystem is fieldsplit
     143             :     // with the following parameters (unless overridden by the user-specified petsc_options below).
     144         136 :     po.pairs.emplace_back(prefix + "pc_type", "fieldsplit");
     145             : 
     146             :     // set Splitting Type
     147             :     const std::string petsc_splitting_type[] = {
     148         816 :         "additive", "multiplicative", "symmetric_multiplicative", "schur"};
     149         136 :     po.pairs.emplace_back(prefix + "pc_fieldsplit_type", petsc_splitting_type[_splitting_type]);
     150             : 
     151         136 :     if (_splitting_type == SplittingTypeSchur)
     152             :     {
     153             :       // set Schur Type
     154           0 :       const std::string petsc_schur_type[] = {"diag", "upper", "lower", "full"};
     155           0 :       po.pairs.emplace_back(prefix + "pc_fieldsplit_schur_fact_type",
     156           0 :                             petsc_schur_type[_schur_type]);
     157             : 
     158             :       // set Schur Preconditioner
     159           0 :       const std::string petsc_schur_pre[] = {"self", "selfp", "a11"};
     160           0 :       po.pairs.emplace_back(prefix + "pc_fieldsplit_schur_precondition",
     161           0 :                             petsc_schur_pre[_schur_pre]);
     162           0 :     }
     163             : 
     164             :     // The DM associated with this split defines the subsplits' geometry.
     165         136 :     po.pairs.emplace_back(dmprefix + "nfieldsplits", Moose::stringify(_splitting.size()));
     166         136 :     po.pairs.emplace_back(dmprefix + "fieldsplit_names", Moose::stringify(_splitting, ","));
     167             : 
     168             :     // Finally, recursively configure the splits contained within this split.
     169         408 :     for (const auto & split_name : _splitting)
     170             :     {
     171         272 :       std::shared_ptr<Split> split = nl.getSplit(split_name);
     172         272 :       std::string sprefix = prefix + "fieldsplit_" + split_name + "_";
     173         272 :       split->setup(nl, sprefix);
     174         272 :     }
     175         680 :   }
     176             : 
     177             :   // Now we set the user-specified petsc options for this split, possibly overriding the above
     178             :   // settings.
     179         376 :   Moose::PetscSupport::storePetscOptions(_fe_problem, prefix, *this);
     180         376 : }

Generated by: LCOV version 1.14