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 : #include "SingleMatrixPreconditioner.h" 11 : 12 : // MOOSE includes 13 : #include "FEProblem.h" 14 : #include "MooseUtils.h" 15 : #include "MooseVariableFE.h" 16 : #include "NonlinearSystem.h" 17 : 18 : #include "libmesh/coupling_matrix.h" 19 : 20 : registerMooseObjectAliased("MooseApp", SingleMatrixPreconditioner, "SMP"); 21 : 22 : InputParameters 23 56624 : SingleMatrixPreconditioner::validParams() 24 : { 25 56624 : InputParameters params = MoosePreconditioner::validParams(); 26 : 27 56624 : params.addClassDescription("Single matrix preconditioner (SMP) builds a preconditioner using " 28 : "user defined off-diagonal parts of the Jacobian."); 29 : 30 56624 : params.addParam<std::vector<NonlinearVariableName>>( 31 : "coupled_groups", 32 : {}, 33 : "List multiple space separated groups of comma separated variables. " 34 : "Off-diagonal jacobians will be generated for all pairs within a group."); 35 169872 : params.addParam<bool>( 36 : "trust_my_coupling", 37 113248 : false, 38 : "Whether to trust my coupling even if the framework wants to be paranoid and create a full " 39 : "coupling matrix, which can happen when using global AD indexing for example."); 40 : 41 56624 : return params; 42 0 : } 43 : 44 14029 : SingleMatrixPreconditioner::SingleMatrixPreconditioner(const InputParameters & params) 45 14029 : : MoosePreconditioner(params) 46 : { 47 14029 : NonlinearSystemBase & nl = _fe_problem.getNonlinearSystemBase(_nl_sys_num); 48 14029 : unsigned int n_vars = nl.nVariables(); 49 14029 : const auto & libmesh_system = nl.system(); 50 14029 : auto cm = std::make_unique<CouplingMatrix>(n_vars); 51 : 52 14029 : if (!getParam<bool>("full")) 53 : { 54 : // put 1s on diagonal 55 1073 : for (unsigned int i = 0; i < n_vars; ++i) 56 608 : (*cm)(i, i) = 1; 57 : 58 : // off-diagonal entries from the off_diag_row and off_diag_column parameters 59 465 : for (const auto & off_diag : 60 974 : getParam<NonlinearVariableName, NonlinearVariableName>("off_diag_row", "off_diag_column")) 61 : { 62 44 : const auto row = libmesh_system.variable_number(off_diag.first); 63 44 : const auto column = libmesh_system.variable_number(off_diag.second); 64 44 : (*cm)(row, column) = 1; 65 465 : } 66 : 67 : // off-diagonal entries from the coupled_groups parameters 68 465 : const auto & all_vars = nl.getVariableNames(); 69 491 : for (const auto & group : getParam<std::vector<NonlinearVariableName>>("coupled_groups")) 70 : { 71 26 : std::vector<VariableName> vars; 72 26 : MooseUtils::tokenize(group, vars, 1, ","); 73 : try 74 : { 75 26 : MooseUtils::expandAllMatches(all_vars, vars); 76 : } 77 0 : catch (std::invalid_argument const & e) 78 : { 79 0 : mooseError("No variable name match found for '", e.what(), "'."); 80 0 : } 81 : 82 78 : for (const auto j : index_range(vars)) 83 78 : for (unsigned int k = j + 1; k < vars.size(); ++k) 84 : { 85 26 : const auto row = libmesh_system.variable_number(vars[j]); 86 26 : const auto column = libmesh_system.variable_number(vars[k]); 87 26 : (*cm)(row, column) = 1; 88 26 : (*cm)(column, row) = 1; 89 : } 90 26 : } 91 : } 92 : else 93 : { 94 34284 : for (unsigned int i = 0; i < n_vars; ++i) 95 61588 : for (unsigned int j = 0; j < n_vars; ++j) 96 40868 : (*cm)(i, j) = 1; 97 : } 98 : 99 14029 : setCouplingMatrix(std::move(cm)); 100 14029 : if (getParam<bool>("trust_my_coupling")) 101 4 : _fe_problem.trustUserCouplingMatrix(); 102 14029 : }