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 "DumpObjectsProblem.h" 11 : #include "DumpObjectsAction.h" 12 : #include "DumpObjectsNonlinearSystem.h" 13 : #include "DumpObjectsLinearSystem.h" 14 : #include "AuxiliarySystem.h" 15 : #include "InputParameters.h" 16 : #include "NonlinearSystem.h" 17 : #include "LinearSystem.h" 18 : #include "SolverSystem.h" 19 : #include "Function.h" 20 : #include <sstream> 21 : 22 : #include "libmesh/string_to_enum.h" 23 : 24 : using namespace libMesh; 25 : 26 : registerMooseObject("MooseApp", DumpObjectsProblem); 27 : 28 : InputParameters 29 14305 : DumpObjectsProblem::validParams() 30 : { 31 14305 : InputParameters params = FEProblemBase::validParams(); 32 14305 : params.addClassDescription("Single purpose problem object that does not run the given input but " 33 : "allows deconstructing actions into their series of underlying Moose " 34 : "objects and variables."); 35 14305 : params.addParam<std::string>( 36 : "dump_path", "all", "Syntax path of the action of which to dump the generated syntax"); 37 42915 : params.addParam<bool>( 38 : "include_all_user_specified_params", 39 28610 : true, 40 : "Whether to include all parameters that have been specified by a user in the dump, even if " 41 : "they match the default value of the parameter in the Factory"); 42 : 43 : // Change the default because any complex solve or executioners needs the problem to perform its 44 : // setup duties (all the calls in initialSetup()) which are skipped by the DumpObjectsProblem 45 42915 : params.addParam<bool>( 46 : "solve", 47 28610 : false, 48 : "Whether to attempt to solve the Problem. This will only cause additional outputs of the " 49 : "objects and their parameters. This is unlikely to succeed with more complex executioners."); 50 14305 : return params; 51 0 : } 52 : 53 20 : DumpObjectsProblem::DumpObjectsProblem(const InputParameters & parameters) 54 : : FEProblemBase(parameters), 55 20 : _include_all_user_specified_params(getParam<bool>("include_all_user_specified_params")) 56 : { 57 : // Make dummy systems based on parameters passed 58 20 : _solver_systems.resize(0); 59 40 : for (const auto i : index_range(_nl_sys_names)) 60 : { 61 20 : const auto & sys_name = _nl_sys_names[i]; 62 20 : const auto & new_sys = std::make_shared<DumpObjectsNonlinearSystem>(*this, sys_name); 63 20 : _solver_systems.push_back(new_sys); 64 20 : _nl[i] = new_sys; 65 20 : } 66 20 : for (const auto i : index_range(_linear_sys_names)) 67 : { 68 0 : const auto & sys_name = _linear_sys_names[i]; 69 0 : const auto & new_sys = std::make_shared<DumpObjectsLinearSystem>(*this, sys_name); 70 0 : _solver_systems.push_back(new_sys); 71 0 : _linear_systems[i] = new_sys; 72 0 : } 73 20 : _aux = std::make_shared<AuxiliarySystem>(*this, "aux0"); 74 : 75 : // Create a dummy assembly for the systems at hand 76 20 : newAssemblyArray(_solver_systems); 77 : 78 : // Create extra vectors and matrices if any 79 20 : createTagVectors(); 80 : 81 : // Create extra solution vectors if any 82 20 : createTagSolutions(); 83 : 84 : // Add an action to call printObjects at the end of the action/tasks phase 85 : // NOTE: We previously relied on problem.solve() but some executioners (SIMPLE in NavierStokes) do 86 : // not support this 87 20 : auto action_params = _app.getActionFactory().getValidParams("DumpObjectsAction"); 88 20 : action_params.applyParameters(parameters); 89 : auto dump_objects_action = 90 20 : _app.getActionFactory().create("DumpObjectsAction", "dump_objects", action_params); 91 20 : _app.actionWarehouse().addActionBlock(dump_objects_action); 92 20 : } 93 : 94 : std::string 95 100 : DumpObjectsProblem::deduceNecessaryParameters(const std::string & type, 96 : const InputParameters & parameters) 97 : { 98 100 : auto factory_params = stringifyParameters(_factory.getValidParams(type)); 99 100 : auto specified_params = stringifyParameters(parameters); 100 : 101 100 : std::string param_text; 102 1340 : for (auto & value_pair : specified_params) 103 : { 104 : // parameter name 105 1240 : const auto & param_name = value_pair.first; 106 1240 : const auto & param_value = value_pair.second; 107 : 108 : // determine whether to include the parameter 109 1240 : auto factory_it = factory_params.find(param_name); 110 1240 : bool include_param = (factory_it->second != param_value); 111 1240 : if (_include_all_user_specified_params) 112 1240 : include_param = include_param || parameters.isParamSetByUser(param_name); 113 1240 : if (factory_it == factory_params.end() || include_param) 114 160 : param_text += " " + param_name + " = " + param_value + '\n'; 115 : } 116 : 117 200 : return param_text; 118 100 : } 119 : 120 : void 121 100 : DumpObjectsProblem::dumpObjectHelper(const std::string & system, 122 : const std::string & type, 123 : const std::string & name, 124 : const InputParameters & parameters) 125 : { 126 100 : auto path = _app.actionWarehouse().getCurrentActionName(); 127 100 : auto param_text = deduceNecessaryParameters(type, parameters); 128 : 129 : // clang-format off 130 100 : _generated_syntax[path][system] += 131 200 : " [" + name + "]\n" 132 200 : + " type = " + type + '\n' 133 200 : + param_text 134 200 : + " []\n"; 135 : // clang-format on 136 100 : } 137 : 138 : void 139 0 : DumpObjectsProblem::dumpVariableHelper(const std::string & system, 140 : const std::string & var_name, 141 : FEFamily family, 142 : Order order, 143 : Real scale_factor, 144 : const std::set<SubdomainID> * const active_subdomains) 145 : { 146 0 : auto path = _app.actionWarehouse().getCurrentActionName(); 147 0 : std::string param_text; 148 : 149 0 : if (active_subdomains) 150 : { 151 0 : std::string blocks; 152 0 : for (auto & subdomain_id : *active_subdomains) 153 : { 154 0 : auto subdomain_name = _mesh.getMesh().subdomain_name(subdomain_id); 155 0 : if (subdomain_name == "") 156 0 : subdomain_name = std::to_string(subdomain_id); 157 : 158 0 : if (!blocks.empty()) 159 0 : blocks += ' '; 160 : 161 0 : blocks += subdomain_name; 162 0 : } 163 : 164 0 : if (active_subdomains->size() > 1) 165 0 : blocks = "'" + blocks + "'"; 166 : 167 0 : param_text += " blocks = " + blocks + '\n'; 168 0 : } 169 : 170 0 : if (family != LAGRANGE) 171 0 : param_text += " family = " + libMesh::Utility::enum_to_string<FEFamily>(family) + '\n'; 172 0 : if (order != FIRST) 173 0 : param_text += " order = " + libMesh::Utility::enum_to_string<Order>(order) + '\n'; 174 0 : if (scale_factor != 1.0) 175 0 : param_text += " scale = " + std::to_string(scale_factor); 176 : 177 : // clang-format off 178 0 : _generated_syntax[path][system] += 179 0 : " [" + var_name + "]\n" 180 0 : + param_text 181 0 : + " []\n"; 182 : // clang-format on 183 0 : } 184 : 185 : void 186 20 : DumpObjectsProblem::printObjects() 187 : { 188 20 : const auto path = getParam<std::string>("dump_path"); 189 20 : if (path != "all") 190 10 : dumpGeneratedSyntax(path); 191 : else 192 10 : dumpAllGeneratedSyntax(); 193 20 : } 194 : 195 : void 196 10 : DumpObjectsProblem::dumpGeneratedSyntax(const std::string path) 197 : { 198 10 : auto pathit = _generated_syntax.find(path); 199 10 : if (pathit == _generated_syntax.end()) 200 0 : return; 201 : 202 10 : Moose::out << "**START DUMP DATA**\n"; 203 40 : for (const auto & system_pair : pathit->second) 204 30 : Moose::out << '[' << system_pair.first << "]\n" << system_pair.second << "[]\n\n"; 205 10 : Moose::out << "**END DUMP DATA**\n"; 206 10 : Moose::out << std::flush; 207 : } 208 : 209 : void 210 10 : DumpObjectsProblem::dumpAllGeneratedSyntax() const 211 : { 212 10 : Moose::out << "**START DUMP DATA**\n"; 213 30 : for (const auto & path : _generated_syntax) 214 60 : for (const auto & system_pair : path.second) 215 40 : Moose::out << '[' << system_pair.first << "]\n" << system_pair.second << "[]\n\n"; 216 10 : Moose::out << "**END DUMP DATA**\n"; 217 10 : Moose::out << std::flush; 218 10 : } 219 : 220 : std::map<std::string, std::string> 221 200 : DumpObjectsProblem::stringifyParameters(const InputParameters & parameters) 222 : { 223 200 : std::map<std::string, std::string> parameter_map; 224 : 225 200 : std::string syntax; 226 200 : if (parameters.isParamValid("parser_syntax")) 227 0 : syntax = parameters.get<std::string>("parser_syntax"); 228 : 229 6960 : for (auto & value_pair : parameters) 230 : { 231 : // parameter name 232 6760 : const auto & param_name = value_pair.first; 233 : 234 6760 : if (!parameters.isPrivate(param_name) && parameters.isParamValid(param_name)) 235 : { 236 2440 : if (param_name == "control_tags") 237 : { 238 : // deal with the control tags. The current parser_syntax is automatically added to this. So 239 : // we can remove the parameter if that's all there is in it 240 : } 241 : else 242 : { 243 : // special treatment for some types 244 : 245 : // parameter value 246 2400 : std::string param_value; 247 2400 : if (parameters.have_parameter<bool>(param_name)) 248 : { 249 1000 : const bool & b = parameters.get<bool>(param_name); 250 1000 : param_value = b ? "true" : "false"; 251 : } 252 : else 253 : { 254 1400 : std::stringstream ss; 255 1400 : value_pair.second->print(ss); 256 1400 : param_value = ss.str(); 257 1400 : } 258 : 259 : // delete trailing space 260 2400 : if (!param_value.empty() && param_value.back() == ' ') 261 80 : param_value.pop_back(); 262 : 263 : // add quotes if the parameter contains spaces or is empty 264 2400 : if (param_value.find_first_of(" ") != std::string::npos || param_value.length() == 0) 265 240 : param_value = "'" + param_value + "'"; 266 : 267 2400 : parameter_map[param_name] = param_value; 268 2400 : } 269 : } 270 : } 271 : 272 400 : return parameter_map; 273 200 : } 274 : 275 : void 276 20 : DumpObjectsProblem::initialSetup() 277 : { 278 20 : TIME_SECTION("initializingFunctions", 5, "Initializing Functions"); 279 : mooseAssert(libMesh::n_threads() == 1, "We should only use one thread for dumping objects"); 280 : 281 : // Call the initialSetup methods for functions 282 : // We need to do that at least for the parsed functions that can be used as parameters 283 : // in the input file 284 : // Note that we are not planning to use the functions, which is why we are not re-initing scalar 285 : // variables 286 20 : _functions.initialSetup(0); 287 20 : }