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 54800 : SingleMatrixPreconditioner::validParams() 24 : { 25 54800 : InputParameters params = MoosePreconditioner::validParams(); 26 : 27 54800 : params.addClassDescription("Single matrix preconditioner (SMP) builds a preconditioner using " 28 : "user defined off-diagonal parts of the Jacobian."); 29 : 30 54800 : 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 164400 : params.addParam<bool>( 36 : "trust_my_coupling", 37 109600 : 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 54800 : return params; 42 0 : } 43 : 44 13117 : SingleMatrixPreconditioner::SingleMatrixPreconditioner(const InputParameters & params) 45 13117 : : MoosePreconditioner(params) 46 : { 47 13117 : NonlinearSystemBase & nl = _fe_problem.getNonlinearSystemBase(_nl_sys_num); 48 13117 : unsigned int n_vars = nl.nVariables(); 49 13117 : const auto & libmesh_system = nl.system(); 50 13117 : auto cm = std::make_unique<CouplingMatrix>(n_vars); 51 : 52 13117 : if (!getParam<bool>("full")) 53 : { 54 : // put 1s on diagonal 55 1011 : for (unsigned int i = 0; i < n_vars; ++i) 56 572 : (*cm)(i, i) = 1; 57 : 58 : // off-diagonal entries from the off_diag_row and off_diag_column parameters 59 439 : for (const auto & off_diag : 60 919 : getParam<NonlinearVariableName, NonlinearVariableName>("off_diag_row", "off_diag_column")) 61 : { 62 41 : const auto row = libmesh_system.variable_number(off_diag.first); 63 41 : const auto column = libmesh_system.variable_number(off_diag.second); 64 41 : (*cm)(row, column) = 1; 65 439 : } 66 : 67 : // off-diagonal entries from the coupled_groups parameters 68 439 : const auto & all_vars = nl.getVariableNames(); 69 463 : for (const auto & group : getParam<std::vector<NonlinearVariableName>>("coupled_groups")) 70 : { 71 24 : std::vector<VariableName> vars; 72 24 : MooseUtils::tokenize(group, vars, 1, ","); 73 : try 74 : { 75 24 : 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 72 : for (const auto j : index_range(vars)) 83 72 : for (unsigned int k = j + 1; k < vars.size(); ++k) 84 : { 85 24 : const auto row = libmesh_system.variable_number(vars[j]); 86 24 : const auto column = libmesh_system.variable_number(vars[k]); 87 24 : (*cm)(row, column) = 1; 88 24 : (*cm)(column, row) = 1; 89 : } 90 24 : } 91 : } 92 : else 93 : { 94 32099 : for (unsigned int i = 0; i < n_vars; ++i) 95 57832 : for (unsigned int j = 0; j < n_vars; ++j) 96 38411 : (*cm)(i, j) = 1; 97 : } 98 : 99 13117 : setCouplingMatrix(std::move(cm)); 100 13117 : if (getParam<bool>("trust_my_coupling")) 101 4 : _fe_problem.trustUserCouplingMatrix(); 102 13117 : }