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 15889 : DOFMapOutput::validParams() 32 : { 33 : // Get the parameters from the base class 34 15889 : InputParameters params = FileOutput::validParams(); 35 31778 : params.addClassDescription("Output degree-of-freedom (DOF) map."); 36 : 37 : // Screen and file output toggles 38 63556 : params.addParam<bool>("output_screen", false, "Output to the screen"); 39 63556 : params.addParam<bool>("output_file", true, "Output to the file"); 40 63556 : params.addParam<std::string>("system_name", "nl0", "System to output"); 41 : 42 : // By default this only executes on the initial timestep 43 31778 : params.set<ExecFlagEnum>("execute_on", true) = EXEC_INITIAL; 44 : 45 47667 : params.addParam<NonlinearSystemName>( 46 : "nl_sys", "nl0", "The nonlinear system that we should output information for."); 47 15889 : return params; 48 0 : } 49 : 50 572 : DOFMapOutput::DOFMapOutput(const InputParameters & parameters) 51 : : FileOutput(parameters), 52 572 : _write_file(getParam<bool>("output_file")), 53 1144 : _write_screen(getParam<bool>("output_screen")), 54 1144 : _system_name(getParam<std::string>("system_name")), 55 572 : _mesh(_problem_ptr->mesh()), 56 2288 : _nl_sys_num(_problem_ptr->nlSysNum(getParam<NonlinearSystemName>("nl_sys"))) 57 : { 58 572 : } 59 : 60 : std::string 61 1185 : DOFMapOutput::filename() 62 : { 63 1185 : if (_file_num > 0) 64 119 : return _file_base + "_" + Moose::stringify(_file_num) + ".json"; 65 : else 66 1066 : 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 613 : DOFMapOutput::writeStreamToFile(bool /*append*/) 86 : { 87 : // Create the stream 88 613 : std::ofstream output; 89 : 90 : // Open the file and write contents of file output stream and close the file 91 613 : output.open(filename().c_str(), std::ios::trunc); 92 613 : if (output.fail()) 93 0 : mooseError("Unable to open file ", filename()); 94 : 95 613 : output << _file_output_stream.str(); 96 613 : output.close(); 97 : 98 : // Clear the file output stream 99 1226 : _file_output_stream.str(""); 100 613 : _file_num++; 101 613 : } 102 : 103 : template <typename T> 104 : std::string 105 2157 : DOFMapOutput::join(const T & begin, const T & end, const char * const delim) 106 : { 107 2157 : std::ostringstream os; 108 105812 : for (T it = begin; it != end; ++it) 109 103655 : os << (it != begin ? delim : "") << *it; 110 4314 : return os.str(); 111 2157 : } 112 : 113 : void 114 623 : DOFMapOutput::output() 115 : { 116 : // Don't build this information if nothing is to be written 117 623 : if (!_write_screen && !_write_file) 118 0 : return; 119 : 120 623 : std::stringstream oss; 121 : 122 : // Get the DOF Map through the equation system 123 623 : const System & sys = _problem_ptr->es().get_system(_system_name); // TransientNonlinearImplicit 124 623 : const DofMap & dof_map = sys.get_dof_map(); 125 : 126 : // fetch the KernelWarehouse through the NonlinearSystem 127 623 : NonlinearSystemBase & _nl = _problem_ptr->getNonlinearSystemBase(_nl_sys_num); 128 623 : auto & kernels = _nl.getKernelWarehouse(); 129 : 130 : // get a set of all subdomains 131 623 : const std::set<SubdomainID> & subdomains = _mesh.meshSubdomains(); 132 : 133 623 : bool first = true; 134 623 : oss << "{\"ndof\": " << sys.n_dofs() << ", \"demangled\": "; 135 : #if defined(LIBMESH_HAVE_GCC_ABI_DEMANGLE) 136 623 : oss << "true"; 137 : #else 138 : oss << "false"; 139 : #endif 140 623 : oss << ", \"vars\": ["; 141 1478 : for (unsigned int vg = 0; vg < dof_map.n_variable_groups(); ++vg) 142 : { 143 855 : const VariableGroup & vg_description(dof_map.variable_group(vg)); 144 2086 : for (unsigned int vn = 0; vn < vg_description.n_variables(); ++vn) 145 : { 146 1231 : unsigned int var = vg_description.number(vn); 147 : 148 1231 : if (!first) 149 608 : oss << ", "; 150 1231 : first = false; 151 : 152 1231 : oss << "{\"name\": \"" << vg_description.name(vn) << "\", \"subdomains\": ["; 153 3388 : for (std::set<SubdomainID>::const_iterator sd = subdomains.begin(); sd != subdomains.end(); 154 2157 : ++sd) 155 : { 156 2157 : oss << (sd != subdomains.begin() ? ", " : "") << "{\"id\": " << *sd << ", \"kernels\": ["; 157 : 158 : // if this variable has active kernels output them 159 2157 : 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 1778 : oss << (i > 0 ? ", " : "") << "{\"name\": \"" << kb.name() << "\", \"type\": \"" 166 5334 : << demangle(typeid(kb).name()) << "\"}"; 167 : } 168 : } 169 2157 : oss << "], \"dofs\": ["; 170 : 171 : // get the list of unique DOFs for this variable 172 : // Start by looking at local DOFs 173 2157 : std::set<dof_id_type> dofs; 174 2157 : ConstElemRange * active_local_elems = _mesh.getActiveLocalElementRange(); 175 163121 : for (const auto & elem : *active_local_elems) 176 : { 177 160964 : if (elem->subdomain_id() == *sd) 178 : { 179 88418 : std::vector<dof_id_type> di; 180 88418 : dof_map.dof_indices(elem, di, var); 181 88418 : dofs.insert(di.begin(), di.end()); 182 88418 : } 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 2157 : _communicator.set_union(dofs); 188 : 189 2157 : oss << join(dofs.begin(), dofs.end(), ", ") << "]}"; 190 2157 : } 191 1231 : oss << "]}"; 192 : } 193 : } 194 623 : oss << "]}" << std::endl; 195 : 196 : // Write the message to file stream 197 623 : if (_write_file) 198 613 : _file_output_stream << oss.str() << std::endl; 199 : 200 : // Write message to the screen 201 623 : if (_write_screen) 202 10 : _console << oss.str() << std::flush; 203 : 204 : // Write the actual file 205 623 : if (_write_file) 206 613 : writeStreamToFile(); 207 623 : }