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