LCOV - code coverage report
Current view: top level - src/outputs - DOFMapOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 87 90 96.7 %
Date: 2025-07-17 01:28:37 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14