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 "MaterialDerivativeTestAction.h" 11 : 12 : #include "Conversion.h" 13 : #include "MooseEnum.h" 14 : #include "FEProblemBase.h" 15 : #include "MoosePreconditioner.h" 16 : #include "NonlinearSystemBase.h" 17 : #include "MooseVariableBase.h" 18 : 19 : #include "libmesh/fe.h" 20 : #include "libmesh/string_to_enum.h" 21 : 22 : registerMooseAction("MooseApp", MaterialDerivativeTestAction, "add_variable"); 23 : 24 : registerMooseAction("MooseApp", MaterialDerivativeTestAction, "add_kernel"); 25 : 26 : registerMooseAction("MooseApp", MaterialDerivativeTestAction, "add_preconditioning"); 27 : 28 : InputParameters 29 203 : MaterialDerivativeTestAction::validParams() 30 : { 31 203 : InputParameters params = Action::validParams(); 32 203 : params.addClassDescription( 33 : "Action for setting up the necessary objects for debugging material property derivatives."); 34 203 : params.addParam<std::vector<VariableName>>("args", 35 : "Variables the tested material property depends on."); 36 203 : params.addRequiredParam<MaterialPropertyName>( 37 : "prop_name", "Name of the material property to test the derivatives of."); 38 203 : MooseEnum prop_type_enum("Real RankTwoTensor RankFourTensor"); 39 203 : params.addParam<MooseEnum>( 40 : "prop_type", prop_type_enum, "Type of the material property to test the derivatives of."); 41 609 : params.addParam<unsigned int>( 42 406 : "derivative_order", 0, "Highest order derivative to test derivatives of."); 43 406 : return params; 44 203 : } 45 : 46 0 : MaterialDerivativeTestAction::MaterialDerivativeTestAction(const InputParameters & parameters) 47 : : Action(parameters), 48 0 : _args(getParam<std::vector<VariableName>>("args")), 49 0 : _prop_name(getParam<MaterialPropertyName>("prop_name")), 50 0 : _prop_type(getParam<MooseEnum>("prop_type").getEnum<PropTypeEnum>()), 51 0 : _derivative_order(getParam<unsigned int>("derivative_order")), 52 0 : _second(false), 53 0 : _derivatives({{_prop_name, {}}}) 54 : { 55 0 : std::vector<std::vector<std::vector<SymbolName>>> derivative_table(_derivative_order + 1); 56 : 57 : // 0th derivative is a (single) derivative w.r.t. to _no_ variables 58 0 : derivative_table[0] = {{}}; 59 : 60 : // build higher order derivatives 61 0 : for (unsigned int n = 1; n <= _derivative_order; ++n) 62 0 : for (const auto & function : derivative_table[n - 1]) 63 0 : for (const auto & var : _args) 64 : { 65 : // take previous order derivative and derive w.r.t. one of the args 66 0 : auto derivative = std::vector<SymbolName>(function); 67 0 : derivative.push_back(var); 68 : 69 : // add derivative to list 70 0 : derivative_table[n].push_back(derivative); 71 0 : _derivatives.insert( 72 0 : std::make_pair(derivativePropertyName(_prop_name, derivative), derivative)); 73 0 : } 74 0 : } 75 : 76 : void 77 0 : MaterialDerivativeTestAction::act() 78 : { 79 : // finite element type 80 0 : const std::string order = _second ? "SECOND" : "FIRST"; 81 0 : const std::string family("LAGRANGE"); 82 0 : const auto type = "MooseVariable"; 83 0 : auto params = _factory.getValidParams(type); 84 0 : params.set<MooseEnum>("order") = order; 85 0 : params.set<MooseEnum>("family") = family; 86 : 87 : // build higher order derivatives 88 0 : for (const auto & derivative : _derivatives) 89 : { 90 : // Create variables 91 0 : if (_current_task == "add_variable") 92 : { 93 0 : switch (_prop_type) 94 : { 95 0 : case PropTypeEnum::REAL: 96 0 : _problem->addVariable(type, "var_" + derivative.first, params); 97 0 : break; 98 : 99 0 : case PropTypeEnum::RANKTWOTENSOR: 100 0 : for (unsigned int i = 0; i < 3; ++i) 101 0 : for (unsigned int j = 0; j < 3; ++j) 102 0 : _problem->addVariable(type, 103 0 : "var_" + derivative.first + '_' + Moose::stringify(i) + '_' + 104 0 : Moose::stringify(j), 105 : params); 106 0 : break; 107 : 108 0 : case PropTypeEnum::RANKFOURTENSOR: 109 0 : for (unsigned int i = 0; i < 3; ++i) 110 0 : for (unsigned int j = 0; j < 3; ++j) 111 0 : for (unsigned int k = 0; k < 3; ++k) 112 0 : for (unsigned int l = 0; l < 3; ++l) 113 0 : _problem->addVariable(type, 114 0 : "var_" + derivative.first + '_' + Moose::stringify(i) + 115 0 : '_' + Moose::stringify(j) + '_' + Moose::stringify(k) + 116 0 : '_' + Moose::stringify(l), 117 : params); 118 0 : break; 119 : 120 0 : default: 121 0 : mooseError("Unknown property type."); 122 : } 123 : } 124 : 125 0 : if (_current_task == "add_kernel") 126 : { 127 0 : switch (_prop_type) 128 : { 129 0 : case PropTypeEnum::REAL: 130 : { 131 0 : auto params = _factory.getValidParams("MaterialDerivativeTestKernel"); 132 0 : params.set<std::vector<VariableName>>("args") = _args; 133 0 : params.set<std::vector<SymbolName>>("derivative") = derivative.second; 134 0 : params.set<MaterialPropertyName>("material_property") = _prop_name; 135 0 : params.set<NonlinearVariableName>("variable") = "var_" + derivative.first; 136 0 : _problem->addKernel("MaterialDerivativeTestKernel", "kernel_" + derivative.first, params); 137 0 : break; 138 0 : } 139 : 140 0 : case PropTypeEnum::RANKTWOTENSOR: 141 : { 142 0 : auto params = _factory.getValidParams("MaterialDerivativeRankTwoTestKernel"); 143 0 : params.set<std::vector<VariableName>>("args") = _args; 144 0 : params.set<std::vector<SymbolName>>("derivative") = derivative.second; 145 0 : params.set<MaterialPropertyName>("material_property") = _prop_name; 146 0 : for (unsigned int i = 0; i < 3; ++i) 147 0 : for (unsigned int j = 0; j < 3; ++j) 148 : { 149 : auto suffix = 150 0 : derivative.first + '_' + Moose::stringify(i) + '_' + Moose::stringify(j); 151 0 : params.set<NonlinearVariableName>("variable") = "var_" + suffix; 152 0 : params.set<unsigned int>("i") = i; 153 0 : params.set<unsigned int>("j") = j; 154 0 : _problem->addKernel( 155 0 : "MaterialDerivativeRankTwoTestKernel", "kernel_" + suffix, params); 156 0 : } 157 0 : break; 158 0 : } 159 : 160 0 : case PropTypeEnum::RANKFOURTENSOR: 161 : { 162 0 : auto params = _factory.getValidParams("MaterialDerivativeRankFourTestKernel"); 163 0 : params.set<std::vector<VariableName>>("args") = _args; 164 0 : params.set<std::vector<SymbolName>>("derivative") = derivative.second; 165 0 : params.set<MaterialPropertyName>("material_property") = _prop_name; 166 0 : for (unsigned int i = 0; i < 3; ++i) 167 0 : for (unsigned int j = 0; j < 3; ++j) 168 0 : for (unsigned int k = 0; k < 3; ++k) 169 0 : for (unsigned int l = 0; l < 3; ++l) 170 : { 171 0 : auto suffix = derivative.first + '_' + Moose::stringify(i) + '_' + 172 0 : Moose::stringify(j) + '_' + Moose::stringify(k) + '_' + 173 0 : Moose::stringify(l); 174 0 : params.set<NonlinearVariableName>("variable") = "var_" + suffix; 175 0 : params.set<unsigned int>("i") = i; 176 0 : params.set<unsigned int>("j") = j; 177 0 : params.set<unsigned int>("k") = k; 178 0 : params.set<unsigned int>("l") = l; 179 0 : _problem->addKernel( 180 0 : "MaterialDerivativeRankFourTestKernel", "kernel_" + suffix, params); 181 0 : } 182 0 : break; 183 0 : } 184 : 185 0 : default: 186 0 : mooseError("Unknown property type."); 187 : } 188 : } 189 : } 190 : 191 0 : if (_current_task == "add_preconditioning") 192 : { 193 0 : auto params = _factory.getValidParams("SMP"); 194 0 : auto & row = params.set<std::vector<NonlinearVariableName>>("off_diag_row"); 195 0 : auto & col = params.set<std::vector<NonlinearVariableName>>("off_diag_column"); 196 : 197 0 : for (const auto & derivative : _derivatives) 198 : { 199 0 : switch (_prop_type) 200 : { 201 0 : case PropTypeEnum::REAL: 202 0 : for (auto & arg : _args) 203 : { 204 0 : row.push_back("var_" + derivative.first); 205 0 : col.push_back(arg); 206 : } 207 0 : break; 208 : 209 0 : case PropTypeEnum::RANKTWOTENSOR: 210 0 : for (unsigned int i = 0; i < 3; ++i) 211 0 : for (unsigned int j = 0; j < 3; ++j) 212 0 : for (auto & arg : _args) 213 : { 214 0 : row.push_back("var_" + derivative.first + '_' + Moose::stringify(i) + '_' + 215 0 : Moose::stringify(j)); 216 0 : col.push_back(arg); 217 : } 218 0 : break; 219 : 220 0 : case PropTypeEnum::RANKFOURTENSOR: 221 0 : for (unsigned int i = 0; i < 3; ++i) 222 0 : for (unsigned int j = 0; j < 3; ++j) 223 0 : for (unsigned int k = 0; k < 3; ++k) 224 0 : for (unsigned int l = 0; l < 3; ++l) 225 0 : for (auto & arg : _args) 226 : { 227 0 : row.push_back("var_" + derivative.first + '_' + Moose::stringify(i) + '_' + 228 0 : Moose::stringify(j) + '_' + Moose::stringify(k) + '_' + 229 0 : Moose::stringify(l)); 230 0 : col.push_back(arg); 231 : } 232 0 : break; 233 : 234 0 : default: 235 0 : mooseError("Unknown property type."); 236 : } 237 : } 238 : 239 0 : if (_problem.get() != nullptr) 240 : { 241 : std::shared_ptr<MoosePreconditioner> pc = 242 0 : _factory.create<MoosePreconditioner>("SMP", "material_derivative_SMP", params); 243 : 244 0 : _problem->getNonlinearSystemBase(/*nl_sys=*/0).setPreconditioner(pc); 245 0 : } 246 : else 247 0 : mooseError("_problem.get() returned nullptr"); 248 0 : } 249 0 : }