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 : // MOOSE includes 11 : #include "DOFMapOutput.h" 12 : #include "FEProblem.h" 13 : #include "KernelBase.h" 14 : #include "MooseApp.h" 15 : #include "Moose.h" 16 : #include "Conversion.h" 17 : #include "MooseMesh.h" 18 : #include "NonlinearSystem.h" 19 : 20 : #include "libmesh/fe.h" 21 : 22 : // compiler includes (for type demangling) 23 : #include <cxxabi.h> 24 : #include <fstream> 25 : 26 : using namespace libMesh; 27 : 28 : registerMooseObjectAliased("MooseApp", DOFMapOutput, "DOFMap"); 29 : 30 : InputParameters 31 15337 : DOFMapOutput::validParams() 32 : { 33 : // Get the parameters from the base class 34 15337 : InputParameters params = FileOutput::validParams(); 35 15337 : params.addClassDescription("Output degree-of-freedom (DOF) map."); 36 : 37 : // Screen and file output toggles 38 15337 : params.addParam<bool>("output_screen", false, "Output to the screen"); 39 15337 : params.addParam<bool>("output_file", true, "Output to the file"); 40 15337 : params.addParam<std::string>("system_name", "nl0", "System to output"); 41 : 42 : // By default this only executes on the initial timestep 43 15337 : params.set<ExecFlagEnum>("execute_on", true) = EXEC_INITIAL; 44 : 45 15337 : params.addParam<NonlinearSystemName>( 46 : "nl_sys", "nl0", "The nonlinear system that we should output information for."); 47 15337 : return params; 48 0 : } 49 : 50 536 : DOFMapOutput::DOFMapOutput(const InputParameters & parameters) 51 : : FileOutput(parameters), 52 536 : _write_file(getParam<bool>("output_file")), 53 536 : _write_screen(getParam<bool>("output_screen")), 54 536 : _system_name(getParam<std::string>("system_name")), 55 536 : _mesh(_problem_ptr->mesh()), 56 1608 : _nl_sys_num(_problem_ptr->nlSysNum(getParam<NonlinearSystemName>("nl_sys"))) 57 : { 58 536 : } 59 : 60 : std::string 61 1119 : DOFMapOutput::filename() 62 : { 63 1119 : if (_file_num > 0) 64 226 : return _file_base + "_" + Moose::stringify(_file_num) + ".json"; 65 : else 66 1006 : return _file_base + ".json"; 67 : } 68 : 69 : std::string 70 1778 : DOFMapOutput::demangle(const std::string & name) 71 : { 72 : #if defined(LIBMESH_HAVE_GCC_ABI_DEMANGLE) 73 1778 : return libMesh::demangle(name.c_str()); 74 : #else 75 : // at least remove leading digits 76 : std::string demangled(name); 77 : while (demangled.length() && demangled[0] >= '0' && demangled[0] <= '9') 78 : demangled.erase(0, 1); 79 : 80 : return demangled; 81 : #endif 82 : } 83 : 84 : void 85 583 : DOFMapOutput::writeStreamToFile(bool /*append*/) 86 : { 87 : // Create the stream 88 583 : std::ofstream output; 89 : 90 : // Open the file and write contents of file output stream and close the file 91 583 : output.open(filename().c_str(), std::ios::trunc); 92 583 : if (output.fail()) 93 0 : mooseError("Unable to open file ", filename()); 94 : 95 583 : output << _file_output_stream.str(); 96 583 : output.close(); 97 : 98 : // Clear the file output stream 99 583 : _file_output_stream.str(""); 100 583 : _file_num++; 101 583 : } 102 : 103 : template <typename T> 104 : std::string 105 2087 : DOFMapOutput::join(const T & begin, const T & end, const char * const delim) 106 : { 107 2087 : std::ostringstream os; 108 98672 : for (T it = begin; it != end; ++it) 109 96585 : os << (it != begin ? delim : "") << *it; 110 4174 : return os.str(); 111 2087 : } 112 : 113 : void 114 593 : DOFMapOutput::output() 115 : { 116 : // Don't build this information if nothing is to be written 117 593 : if (!_write_screen && !_write_file) 118 0 : return; 119 : 120 593 : std::stringstream oss; 121 : 122 : // Get the DOF Map through the equation system 123 593 : const System & sys = _problem_ptr->es().get_system(_system_name); // TransientNonlinearImplicit 124 593 : const DofMap & dof_map = sys.get_dof_map(); 125 : 126 : // fetch the KernelWarehouse through the NonlinearSystem 127 593 : NonlinearSystemBase & _nl = _problem_ptr->getNonlinearSystemBase(_nl_sys_num); 128 593 : auto & kernels = _nl.getKernelWarehouse(); 129 : 130 : // get a set of all subdomains 131 593 : const std::set<SubdomainID> & subdomains = _mesh.meshSubdomains(); 132 : 133 593 : bool first = true; 134 593 : oss << "{\"ndof\": " << sys.n_dofs() << ", \"demangled\": "; 135 : #if defined(LIBMESH_HAVE_GCC_ABI_DEMANGLE) 136 593 : oss << "true"; 137 : #else 138 : oss << "false"; 139 : #endif 140 593 : oss << ", \"vars\": ["; 141 1418 : for (unsigned int vg = 0; vg < dof_map.n_variable_groups(); ++vg) 142 : { 143 825 : const VariableGroup & vg_description(dof_map.variable_group(vg)); 144 1986 : for (unsigned int vn = 0; vn < vg_description.n_variables(); ++vn) 145 : { 146 1161 : unsigned int var = vg_description.number(vn); 147 : 148 1161 : if (!first) 149 568 : oss << ", "; 150 1161 : first = false; 151 : 152 1161 : oss << "{\"name\": \"" << vg_description.name(vn) << "\", \"subdomains\": ["; 153 3248 : for (std::set<SubdomainID>::const_iterator sd = subdomains.begin(); sd != subdomains.end(); 154 2087 : ++sd) 155 : { 156 2087 : oss << (sd != subdomains.begin() ? ", " : "") << "{\"id\": " << *sd << ", \"kernels\": ["; 157 : 158 : // if this variable has active kernels output them 159 2087 : if (kernels.hasActiveVariableBlockObjects(var, *sd)) 160 : { 161 1105 : const auto & active_kernels = kernels.getActiveVariableBlockObjects(var, *sd); 162 2883 : for (unsigned i = 0; i < active_kernels.size(); ++i) 163 : { 164 1778 : KernelBase & kb = *(active_kernels[i].get()); 165 3556 : oss << (i > 0 ? ", " : "") << "{\"name\": \"" << kb.name() << "\", \"type\": \"" 166 1778 : << demangle(typeid(kb).name()) << "\"}"; 167 : } 168 : } 169 2087 : oss << "], \"dofs\": ["; 170 : 171 : // get the list of unique DOFs for this variable 172 : // Start by looking at local DOFs 173 2087 : std::set<dof_id_type> dofs; 174 2087 : ConstElemRange * active_local_elems = _mesh.getActiveLocalElementRange(); 175 157451 : for (const auto & elem : *active_local_elems) 176 : { 177 155364 : if (elem->subdomain_id() == *sd) 178 : { 179 82818 : std::vector<dof_id_type> di; 180 82818 : dof_map.dof_indices(elem, di, var); 181 82818 : dofs.insert(di.begin(), di.end()); 182 82818 : } 183 : } 184 : 185 : // Then collect DOFs from other processors. On a distributed 186 : // mesh they may know about DOFs we can't even see. 187 2087 : _communicator.set_union(dofs); 188 : 189 2087 : oss << join(dofs.begin(), dofs.end(), ", ") << "]}"; 190 2087 : } 191 1161 : oss << "]}"; 192 : } 193 : } 194 593 : oss << "]}" << std::endl; 195 : 196 : // Write the message to file stream 197 593 : if (_write_file) 198 583 : _file_output_stream << oss.str() << std::endl; 199 : 200 : // Write message to the screen 201 593 : if (_write_screen) 202 10 : _console << oss.str() << std::flush; 203 : 204 : // Write the actual file 205 593 : if (_write_file) 206 583 : writeStreamToFile(); 207 593 : }