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 "PorousFlowAddMaterialAction.h" 11 : #include "AddBCAction.h" 12 : #include "AddDiracKernelAction.h" 13 : #include "AddKernelAction.h" 14 : #include "AddMaterialAction.h" 15 : #include "AddPostprocessorAction.h" 16 : #include "AddUserObjectAction.h" 17 : #include "PorousFlowActionBase.h" 18 : #include "ActionWarehouse.h" 19 : #include "ActionFactory.h" 20 : #include "FEProblem.h" 21 : #include "MooseObjectAction.h" 22 : #include "Conversion.h" 23 : 24 : registerMooseAction("PorousFlowApp", PorousFlowAddMaterialAction, "meta_action"); 25 : 26 : InputParameters 27 9647 : PorousFlowAddMaterialAction::validParams() 28 : { 29 9647 : InputParameters params = Action::validParams(); 30 9647 : params.addClassDescription( 31 : "Makes sure that the correct nodal and/or qp materials are added for each property"); 32 9647 : return params; 33 0 : } 34 : 35 9647 : PorousFlowAddMaterialAction::PorousFlowAddMaterialAction(const InputParameters & params) 36 9647 : : Action(params), PorousFlowDependencies() 37 : { 38 9647 : } 39 : 40 : void 41 9647 : PorousFlowAddMaterialAction::act() 42 : { 43 : // Create the list of kernels, auxkernels, actions etc that each material may be 44 : // required by 45 9647 : createDependencyList(); 46 : 47 : // Get the list of materials that have been added 48 9647 : auto actions = _awh.getActions<AddMaterialAction>(); 49 : 50 64509 : for (auto & action : actions) 51 54862 : _ama_materials.push_back(const_cast<AddMaterialAction *>(action)); 52 : 53 64509 : for (auto & material : _ama_materials) 54 : { 55 54862 : InputParameters & pars = material->getObjectParams(); 56 : 57 : // Check if the material is a PorousFlow material 58 109724 : if (pars.isParamValid("pf_material_type")) 59 : { 60 50965 : const std::string pf_material_type = pars.get<std::string>("pf_material_type"); 61 : 62 : // PorousFlowJoiner materials are added automatically by the PorousFlowAddMaterialJoiner 63 : // action, so no need to check these here 64 50965 : if (pf_material_type != "joiner") 65 : { 66 : // There are two possibilities that must be considered: 67 : // 1) The parameter at_nodes has been set by the user. In this case, the material will 68 : // be added as normal by AddMaterialAction 69 : // 2) The parameter at_nodes has not been set by the user. In this case, this action 70 : // will check to see if the material is required at the qps, at the nodes, or possibly both 71 : 72 : // Only check the second possibility 73 101588 : if (!pars.isParamSetByUser("at_nodes")) 74 : { 75 : bool qp_material_required = false; 76 : 77 : // First, check the case at_nodes = false, as this is the default behaviour for the 78 : // at_nodes parameter. Note: the local variable at_nodes is set to true, so the material 79 : // is at the qps when !at_nodes 80 : const bool at_nodes = true; 81 : 82 84018 : if (isPFMaterialRequired(pf_material_type, !at_nodes)) 83 : { 84 : // This material is required at the qps, so add it as normal (setting the paramter 85 : // at_nodes = false for clarity) 86 29173 : pars.set<bool>("at_nodes") = !at_nodes; 87 : qp_material_required = true; 88 : } 89 : 90 : // Check if the material is required at the nodes as well and that it isn't already 91 : // added in the input file. If it is needed and not already supplied, then it is added 92 : // in one of two ways: 1) If the material wasn't also required at the qps (checked above), 93 : // then we can simply set the at_nodes parameter to true. 2) If it was also required at 94 : // the qps, then a new material action is required to be added to the action warehouse 95 112028 : if (isPFMaterialRequired(pf_material_type, at_nodes) && 96 28010 : !isPFMaterialPresent(material, at_nodes)) 97 : { 98 27858 : if (!qp_material_required) 99 8458 : pars.set<bool>("at_nodes") = at_nodes; 100 : else 101 19400 : addPFMaterial(material, at_nodes); 102 : } 103 : } 104 : } 105 : } 106 : } 107 9647 : } 108 : 109 : void 110 9647 : PorousFlowAddMaterialAction::createDependencyList() 111 : { 112 : // Unique list of kernels added in input file 113 9647 : auto kernels = _awh.getActions<AddKernelAction>(); 114 47538 : for (auto & kernel : kernels) 115 37891 : _dependency_list.insert(kernel->getMooseObjectType()); 116 : 117 : // Unique list of PorousFlowActions added in input file 118 9647 : auto actions = _awh.getActions<PorousFlowActionBase>(); 119 10924 : for (auto & action : actions) 120 1277 : _dependency_list.insert(action->name()); 121 : 122 : // Unique list of auxkernels added in input file 123 9647 : auto auxkernels = _awh.getActions<AddKernelAction>(); 124 47538 : for (auto & auxkernel : auxkernels) 125 37891 : _dependency_list.insert(auxkernel->getMooseObjectType()); 126 : 127 : // Unique list of postprocessors added in input file 128 9647 : auto postprocessors = _awh.getActions<AddPostprocessorAction>(); 129 41303 : for (auto & postprocessor : postprocessors) 130 31656 : _dependency_list.insert(postprocessor->getMooseObjectType()); 131 : 132 : // Unique list of userojects added in input file 133 9647 : auto userobjects = _awh.getActions<AddUserObjectAction>(); 134 34182 : for (auto & userobject : userobjects) 135 24535 : _dependency_list.insert(userobject->getMooseObjectType()); 136 : 137 : // Unique list of BCs added in input file 138 9647 : auto bcs = _awh.getActions<AddBCAction>(); 139 22568 : for (auto & bc : bcs) 140 12921 : _dependency_list.insert(bc->getMooseObjectType()); 141 : 142 : // Unique list of Dirac kernels added in input file 143 9647 : auto diracs = _awh.getActions<AddDiracKernelAction>(); 144 11660 : for (auto & dirac : diracs) 145 2013 : _dependency_list.insert(dirac->getMooseObjectType()); 146 9647 : } 147 : 148 : bool 149 84018 : PorousFlowAddMaterialAction::isPFMaterialRequired(std::string pf_material_type, bool at_nodes) 150 : { 151 126027 : const std::string nodal_ext = at_nodes ? "_nodal" : "_qp"; 152 : 153 : // Check if this material is required by looping through the list of dependencies 154 : bool required = false; 155 427220 : for (auto item : _dependency_list) 156 : { 157 400385 : required = _deps.dependsOn(item, pf_material_type + nodal_ext); 158 400385 : if (required) 159 : break; 160 : } 161 : 162 84018 : return required; 163 : } 164 : 165 : bool 166 28010 : PorousFlowAddMaterialAction::isPFMaterialPresent(AddMaterialAction * material, bool at_nodes) 167 : { 168 : bool is_present = false; 169 : 170 : // Need to check that it hasn't been added in the input file also to 171 : // avoid a duplicate material property error 172 242110 : for (auto & ama_material : _ama_materials) 173 : { 174 214100 : if (ama_material->name() != material->name() && 175 186090 : ama_material->getMooseObjectType() == material->getMooseObjectType()) 176 : { 177 : InputParameters & mat_params = ama_material->getObjectParams(); 178 4486 : const bool mat_at_nodes = mat_params.get<bool>("at_nodes"); 179 : 180 : InputParameters & pars = material->getObjectParams(); 181 : 182 : // If the material isn't related to a fluid phase, it is present if 183 : // its at_nodes parameter is equal to the given at_nodes 184 6198 : if (mat_at_nodes == at_nodes && !pars.isParamValid("phase")) 185 : is_present = true; 186 : 187 : // If the material is related to a fluid phase, it is present if 188 : // its at_nodes parameter is equal to the given at_nodes, and its 189 : // phase is equal to phase 190 8972 : if (pars.isParamValid("phase")) 191 : { 192 4220 : const unsigned int phase = pars.get<unsigned int>("phase"); 193 : 194 8098 : if (mat_params.isParamValid("phase") && mat_params.get<unsigned int>("phase") == phase) 195 : is_present = true; 196 : } 197 : 198 : // Finally, if the material is block restricted then it is not already 199 : // present if the block parameter is not identical 200 4486 : if (mat_params.get<std::vector<SubdomainName>>("block") != 201 : pars.get<std::vector<SubdomainName>>("block")) 202 : is_present = false; 203 : } 204 : } 205 : 206 28010 : return is_present; 207 : } 208 : 209 : void 210 19400 : PorousFlowAddMaterialAction::addPFMaterial(AddMaterialAction * material, bool at_nodes) 211 : { 212 19400 : const std::string nodal_ext = at_nodes ? "_nodal" : "_qp"; 213 : 214 : // Input parameters for the material that is being added 215 : InputParameters & pars = material->getObjectParams(); 216 : 217 : // PorousFlowMaterial type 218 19400 : const std::string pf_material_type = pars.get<std::string>("pf_material_type"); 219 19400 : const std::string moose_object_type = material->getMooseObjectType(); 220 : 221 : // If it is a material that also has a fluid phase, then extract that to add to name 222 : std::string phase_str; 223 38800 : if (pars.isParamValid("phase")) 224 : { 225 4814 : unsigned int phase = pars.get<unsigned int>("phase"); 226 9628 : phase_str = "_phase" + Moose::stringify(phase); 227 : } 228 : 229 : // Add material to the action warehouse 230 19400 : InputParameters action_params = _action_factory.getValidParams("AddMaterialAction"); 231 19400 : action_params.set<ActionWarehouse *>("awh") = &_awh; 232 : 233 : // Setup action for passed in material type 234 38800 : action_params.set<std::string>("type") = moose_object_type; 235 : 236 19400 : const std::string material_name = material->name() + phase_str + nodal_ext; 237 : 238 : auto action = MooseSharedNamespace::dynamic_pointer_cast<MooseObjectAction>( 239 38800 : _action_factory.create("AddMaterialAction", material_name, action_params)); 240 : 241 19400 : action->getObjectParams().applyParameters(pars); 242 19400 : action->getObjectParams().set<bool>("at_nodes") = at_nodes; 243 : 244 58200 : _awh.addActionBlock(action); 245 38800 : }