LCOV - code coverage report
Current view: top level - src/outputs - SampledOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 230 241 95.4 %
Date: 2026-05-29 20:35:17 Functions: 11 12 91.7 %
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 "SampledOutput.h"
      12             : #include "FEProblem.h"
      13             : #include "DisplacedProblem.h"
      14             : #include "MooseApp.h"
      15             : #include "MoosePartitioner.h"
      16             : 
      17             : #include "libmesh/distributed_mesh.h"
      18             : #include "libmesh/equation_systems.h"
      19             : #include "libmesh/mesh_function.h"
      20             : #include "libmesh/explicit_system.h"
      21             : 
      22             : using namespace libMesh;
      23             : 
      24             : InputParameters
      25       94812 : SampledOutput::validParams()
      26             : {
      27             : 
      28             :   // Get the parameters from the parent object
      29       94812 :   InputParameters params = AdvancedOutput::validParams();
      30      284436 :   params.addParam<unsigned int>("refinements",
      31      189624 :                                 0,
      32             :                                 "Number of uniform refinements for oversampling "
      33             :                                 "(refinement levels beyond any level of "
      34             :                                 "refinements already applied on the regular mesh)");
      35      379248 :   params.addParam<Point>("position",
      36             :                          "Set a positional offset, this vector will get added to the "
      37             :                          "nodal coordinates to move the domain.");
      38      379248 :   params.addParam<MeshFileName>("file", "The name of the mesh file to read, for oversampling");
      39      379248 :   params.addParam<std::vector<SubdomainName>>(
      40             :       "sampling_blocks", "The list of blocks to restrict the mesh sampling to");
      41      284436 :   params.addParam<bool>(
      42             :       "serialize_sampling",
      43      189624 :       true,
      44             :       "If set to true, all sampled output (see sampling parameters) will be done "
      45             :       "on rank 0. This option is useful to debug suspected parallel output issues");
      46             : 
      47             :   // **** DEPRECATED PARAMETERS ****
      48      474060 :   params.addDeprecatedParam<bool>("append_oversample",
      49      189624 :                                   false,
      50             :                                   "Append '_oversample' to the output file base",
      51             :                                   "This parameter is deprecated. To append '_oversample' utilize "
      52             :                                   "the output block name or the 'file_base'");
      53             : 
      54             :   // 'Oversampling' Group
      55      284436 :   params.addParamNamesToGroup("refinements position file sampling_blocks serialize_sampling",
      56             :                               "Modified Mesh Sampling");
      57             : 
      58       94812 :   return params;
      59           0 : }
      60             : 
      61       37150 : SampledOutput::SampledOutput(const InputParameters & parameters)
      62             :   : AdvancedOutput(parameters),
      63       37141 :     _refinements(getParam<unsigned int>("refinements")),
      64       74282 :     _using_external_sampling_file(isParamValid("file")),
      65       74282 :     _change_position(isParamValid("position")),
      66       37021 :     _use_sampled_output(_refinements > 0 || _using_external_sampling_file ||
      67      111173 :                         isParamValid("sampling_blocks") || _change_position),
      68       37161 :     _position(_change_position ? getParam<Point>("position") : Point()),
      69       37141 :     _sampling_mesh_changed(true),
      70       37141 :     _mesh_subdomains_match(true),
      71      185714 :     _serialize(getParam<bool>("serialize_sampling"))
      72             : {
      73       37141 : }
      74             : 
      75             : void
      76       36793 : SampledOutput::initialSetup()
      77             : {
      78       36793 :   AdvancedOutput::initialSetup();
      79             : 
      80             :   // Creates and initializes the sampling mesh
      81       36790 :   initSample();
      82       36790 : }
      83             : 
      84             : void
      85     2483712 : SampledOutput::outputStep(const ExecFlagType & type)
      86             : {
      87             :   // Output is not allowed
      88     2483712 :   if (!_allow_output && type != EXEC_FORCED)
      89       46557 :     return;
      90             : 
      91             :   // If recovering disable output of initial condition, it was already output
      92     2437155 :   if (type == EXEC_INITIAL && _app.isRecovering())
      93           0 :     return;
      94             : 
      95             :   // Return if the current output is not on the desired interval
      96     2437155 :   if (type != EXEC_FINAL && !onInterval())
      97       41535 :     return;
      98             : 
      99             :   // store current simulation time
     100     2395620 :   _last_output_simulation_time = _time;
     101             : 
     102             :   // store current wall time of output
     103     2395620 :   _last_output_wall_time = std::chrono::steady_clock::now();
     104             : 
     105             :   // set current type
     106     2395620 :   _current_execute_flag = type;
     107             : 
     108             :   // Call the output method
     109     2395620 :   if (shouldOutput())
     110             :   {
     111      823275 :     TIME_SECTION("outputStep", 2, "Outputting Step");
     112      164655 :     updateSample();
     113      164655 :     output();
     114      164655 :   }
     115             : 
     116     2395620 :   _current_execute_flag = EXEC_NONE;
     117             : }
     118             : 
     119       36027 : SampledOutput::~SampledOutput()
     120             : {
     121             :   // TODO: Remove once libmesh Issue #1184 is fixed
     122       36027 :   _sampling_es.reset();
     123       36027 :   _sampling_mesh_ptr.reset();
     124       36027 : }
     125             : 
     126             : void
     127        5306 : SampledOutput::meshChanged()
     128             : {
     129        5306 :   _sampling_mesh_changed = true;
     130        5306 : }
     131             : 
     132             : void
     133       36790 : SampledOutput::initSample()
     134             : {
     135             :   // Perform the mesh cloning, if needed
     136       36790 :   if (!_use_sampled_output)
     137       36614 :     return;
     138             : 
     139         176 :   cloneMesh();
     140             : 
     141             :   // Re-position the sampling mesh
     142         176 :   if (_change_position)
     143        2264 :     for (auto & node : _mesh_ptr->getMesh().node_ptr_range())
     144        2264 :       *node += _position;
     145             : 
     146             :   // Perform the mesh refinement
     147         176 :   if (_refinements > 0)
     148             :   {
     149         120 :     MeshRefinement mesh_refinement(_mesh_ptr->getMesh());
     150             : 
     151             :     // We want original and refined partitioning to match so we can
     152             :     // query from one to the other safely on distributed meshes.
     153         120 :     _mesh_ptr->getMesh().skip_partitioning(true);
     154         120 :     mesh_refinement.uniformly_refine(_refinements);
     155             : 
     156             :     // Note that nodesets are not propagated with mesh refinement, unless you built the nodesets
     157             :     // from the sidesets again, which is what happens for the regular mesh with initial refinement
     158         120 :   }
     159             : 
     160             :   // We can't allow renumbering if we want to output multiple time
     161             :   // steps to the same Exodus file
     162         176 :   _mesh_ptr->getMesh().allow_renumbering(false);
     163             : 
     164             :   // This should be called after changing the mesh (block restriction for example)
     165         268 :   if (_change_position || (_refinements > 0) || isParamValid("sampling_blocks"))
     166         166 :     _sampling_mesh_ptr->meshChanged();
     167             : 
     168             :   // Create the new EquationSystems
     169         176 :   _sampling_es = std::make_unique<EquationSystems>(_mesh_ptr->getMesh());
     170         176 :   _es_ptr = _sampling_es.get();
     171             : 
     172             :   // Reference the system from which we are copying
     173         176 :   EquationSystems & source_es = _problem_ptr->es();
     174             : 
     175             :   // If we're going to be copying from that system later, we need to keep its
     176             :   // original elements as ghost elements even if it gets grossly
     177             :   // repartitioned, since we can't repartition the sample mesh to
     178             :   // match.
     179             :   // FIXME: this is not enough. It assumes our initial partition of the sampling mesh
     180             :   // and the source mesh match. But that's usually only true in the 'refinement' case,
     181             :   // not with an arbitrary sampling mesh file
     182         176 :   DistributedMesh * dist_mesh = dynamic_cast<DistributedMesh *>(&source_es.get_mesh());
     183         176 :   if (dist_mesh)
     184             :   {
     185         650 :     for (auto & elem : dist_mesh->active_local_element_ptr_range())
     186         650 :       dist_mesh->add_extra_ghost_elem(elem);
     187             :   }
     188             : 
     189             :   // Initialize the _mesh_functions vector
     190         176 :   const auto num_systems = source_es.n_systems();
     191         176 :   _mesh_functions.resize(num_systems);
     192             : 
     193             :   // Keep track of the variable numbering in both regular and sampled system
     194         176 :   _variable_numbers_in_system.resize(num_systems);
     195             : 
     196             :   // Get the list of nodal and elemental output data
     197         176 :   const auto & nodal_data = getNodalVariableOutput();
     198         176 :   const auto & elemental_data = getElementalVariableOutput();
     199             : 
     200             :   // Loop over the number of systems
     201         528 :   for (const auto sys_num : make_range(num_systems))
     202             :   {
     203             :     // Reference to the current system
     204         352 :     const auto & source_sys = source_es.get_system(sys_num);
     205             : 
     206             :     // Add the system to the new EquationsSystems
     207         352 :     ExplicitSystem & dest_sys = _sampling_es->add_system<ExplicitSystem>(source_sys.name());
     208             : 
     209             :     // Loop through the variables in the System
     210         352 :     const auto num_vars = source_sys.n_vars();
     211         352 :     unsigned int num_actual_vars = 0;
     212         352 :     if (num_vars > 0)
     213             :     {
     214         242 :       if (_serialize)
     215         218 :         _serialized_solution = NumericVector<Number>::build(_communicator);
     216             : 
     217             :       // Add the variables to the system... simultaneously creating MeshFunctions for them.
     218         612 :       for (const auto var_num : make_range(num_vars))
     219             :       {
     220             :         // Is the variable supposed to be output?
     221         370 :         const auto & var_name = source_sys.variable_name(var_num);
     222         370 :         if (!nodal_data.count(var_name) && !elemental_data.count(var_name))
     223         146 :           continue;
     224             : 
     225             :         // We do what we can to preserve the block restriction
     226             :         const std::set<SubdomainID> * subdomains;
     227         248 :         std::set<SubdomainID> restricted_subdomains;
     228         248 :         if (_using_external_sampling_file && !_mesh_subdomains_match)
     229           0 :           subdomains = nullptr;
     230             :         else
     231             :         {
     232         248 :           subdomains = &source_sys.variable(var_num).active_subdomains();
     233             :           // Reduce the block restriction if the output is block restricted
     234         744 :           if (isParamValid("sampling_blocks") && !subdomains->empty())
     235             :           {
     236             :             const auto & sampling_blocks = _sampling_mesh_ptr->getSubdomainIDs(
     237          96 :                 getParam<std::vector<SubdomainName>>("sampling_blocks"));
     238          48 :             set_intersection(subdomains->begin(),
     239             :                              subdomains->end(),
     240             :                              sampling_blocks.begin(),
     241             :                              sampling_blocks.end(),
     242             :                              std::inserter(restricted_subdomains, restricted_subdomains.begin()));
     243          48 :             subdomains = &restricted_subdomains;
     244             : 
     245             :             // None of the subdomains are included in the sampling, might as well skip
     246          48 :             if (subdomains->empty())
     247             :             {
     248          48 :               hideAdditionalVariable(nodal_data.count(var_name) ? "nodal" : "elemental", var_name);
     249          24 :               continue;
     250             :             }
     251          48 :           }
     252             :         }
     253             : 
     254             :         // We are going to add the variable, let's count it
     255         224 :         _variable_numbers_in_system[sys_num].push_back(var_num);
     256         224 :         num_actual_vars++;
     257             : 
     258             :         // Add the variable. We essentially support nodal variables and constant monomials
     259         224 :         const FEType & fe_type = source_sys.variable_type(var_num);
     260         224 :         if (isSampledAtNodes(fe_type))
     261             :         {
     262         164 :           dest_sys.add_variable(source_sys.variable_name(var_num), fe_type, subdomains);
     263         164 :           if (dist_mesh && !_serialize)
     264           0 :             paramError("serialize_sampling",
     265             :                        "Variables sampled as nodal currently require serialization with a "
     266             :                        "distributed mesh.");
     267             :         }
     268             :         else
     269             :         {
     270          60 :           const auto & var_name = source_sys.variable_name(var_num);
     271          60 :           if (fe_type != FEType(CONSTANT, MONOMIAL))
     272             :           {
     273           0 :             mooseInfoRepeated("Sampled output projects variable '" + var_name +
     274             :                               "' onto a constant monomial");
     275           0 :             if (!_serialize)
     276           0 :               paramWarning("serialize_sampling",
     277             :                            "Projection without serialization may fail with insufficient ghosting. "
     278             :                            "Consider setting 'serialize_sampling' to true.");
     279             :           }
     280          60 :           dest_sys.add_variable(var_name, FEType(CONSTANT, MONOMIAL), subdomains);
     281             :         }
     282             :         // Note: we could do more, using the generic projector. But exodus output of higher order
     283             :         // or more exotic variables is limited anyway
     284         248 :       }
     285             : 
     286             :       // Size for the actual number of variables output
     287         242 :       _mesh_functions[sys_num].resize(num_actual_vars);
     288             :     }
     289             :   }
     290             : 
     291             :   // Initialize the newly created EquationSystem
     292         176 :   _sampling_es->init();
     293             : }
     294             : 
     295             : void
     296      164655 : SampledOutput::updateSample()
     297             : {
     298             :   // Do nothing if oversampling and changing position are not enabled
     299      164655 :   if (!_use_sampled_output)
     300      164139 :     return;
     301             : 
     302             :   // We need the mesh functions to extend the whole domain so we serialize both the mesh and the
     303             :   // solution. We need this because the partitioning of the sampling mesh may not match the
     304             :   // partitioning of the source mesh
     305         516 :   if (_serialize)
     306             :   {
     307         494 :     _problem_ptr->mesh().getMesh().gather_to_zero();
     308         494 :     _mesh_ptr->getMesh().gather_to_zero();
     309             :   }
     310             : 
     311             :   // Get a reference to actual equation system
     312         516 :   EquationSystems & source_es = _problem_ptr->es();
     313         516 :   const auto num_systems = source_es.n_systems();
     314             : 
     315             :   // Loop through each system
     316        1548 :   for (const auto sys_num : make_range(num_systems))
     317             :   {
     318        1032 :     if (!_mesh_functions[sys_num].empty())
     319             :     {
     320             :       // Get references to the source and destination systems
     321         560 :       System & source_sys = source_es.get_system(sys_num);
     322         560 :       System & dest_sys = _sampling_es->get_system(sys_num);
     323             : 
     324             :       // Update the solution for the sampling mesh
     325         560 :       if (_serialize)
     326             :       {
     327         538 :         _serialized_solution->clear();
     328         538 :         _serialized_solution->init(source_sys.n_dofs(), false, SERIAL);
     329             :         // Pull down a full copy of this vector on every processor so we can get values in
     330             :         // parallel
     331         538 :         source_sys.solution->localize(*_serialized_solution);
     332             :       }
     333             : 
     334             :       // Update the mesh functions
     335        1164 :       for (const auto var_num : index_range(_mesh_functions[sys_num]))
     336             :       {
     337         604 :         const auto original_var_num = _variable_numbers_in_system[sys_num][var_num];
     338             : 
     339             :         // If the mesh has changed, the MeshFunctions need to be re-built, otherwise simply clear
     340             :         // it for re-initialization
     341             :         // TODO: inherit from MeshChangedInterface and rebuild mesh functions on meshChanged()
     342         604 :         if (!_mesh_functions[sys_num][var_num] || _sampling_mesh_changed)
     343         831 :           _mesh_functions[sys_num][var_num] = std::make_unique<MeshFunction>(
     344             :               source_es,
     345         277 :               _serialize ? *_serialized_solution : *source_sys.solution,
     346             :               source_sys.get_dof_map(),
     347         277 :               original_var_num);
     348             :         else
     349         327 :           _mesh_functions[sys_num][var_num]->clear();
     350             : 
     351             :         // Initialize the MeshFunctions for application to the sampled solution
     352         604 :         _mesh_functions[sys_num][var_num]->init();
     353             : 
     354             :         // Mesh functions are still defined on the original mesh, which might not fully overlap
     355             :         // with the sampling mesh. We don't want to error with a libMesh assert on the out of mesh
     356             :         // mode
     357         604 :         _mesh_functions[sys_num][var_num]->enable_out_of_mesh_mode(-1e6);
     358             :       }
     359             : 
     360             :       // Fill solution vectors by evaluating mesh functions on sampling mesh
     361         993 :       for (const auto var_num : index_range(_mesh_functions[sys_num]))
     362             :       {
     363             :         // we serialized the mesh and the solution vector, we might as well just do this only on
     364             :         // processor 0.
     365         592 :         if (_serialize && processor_id() > 0)
     366         159 :           break;
     367             : 
     368         433 :         const auto original_var_num = _variable_numbers_in_system[sys_num][var_num];
     369         433 :         const FEType & fe_type = source_sys.variable_type(original_var_num);
     370             :         // we use the original variable block restriction for sampling
     371         433 :         const auto * var_blocks = &source_sys.variable(original_var_num).active_subdomains();
     372             :         // NOTE: if we have overlapping domains between the sampling mesh and the source mesh
     373             :         // we would get a value from the source mesh domain. We could further restrict this
     374             :         // block restriction with the sampling mesh block restriction to prevent this.
     375             : 
     376             :         // Loop over the mesh, nodes for nodal data, elements for element data
     377         433 :         if (isSampledAtNodes(fe_type))
     378             :         {
     379         694 :           for (const auto & node : (_serialize ? _mesh_ptr->getMesh().node_ptr_range()
     380      989940 :                                                : _mesh_ptr->getMesh().local_node_ptr_range()))
     381             :           {
     382             :             // Avoid working on ghosted dofs
     383      989246 :             if (node->n_dofs(sys_num, var_num) &&
     384      494623 :                 (_serialize || processor_id() == node->processor_id()))
     385             :             {
     386             :               // the node has to be within the domain of the mesh function
     387      494623 :               DenseVector<Real> value(1);
     388      494623 :               if (var_blocks->size())
     389         640 :                 (*_mesh_functions[sys_num][var_num])(
     390         640 :                     *node - _position, /*time*/ 0., value, var_blocks);
     391             :               else
     392      494303 :                 value[0] = (*_mesh_functions[sys_num][var_num])(*node - _position);
     393             : 
     394      494623 :               if (value[0] != -1e6)
     395      494623 :                 dest_sys.solution->set(node->dof_number(sys_num, var_num, /*comp=*/0), value[0]);
     396             :               else
     397           0 :                 mooseDoOnce(mooseWarning(
     398             :                     "Sampling at location ",
     399             :                     *node - _position,
     400             :                     " by process ",
     401             :                     std::to_string(processor_id()),
     402             :                     " was outside the problem mesh.\nThis message will not be repeated"));
     403      494623 :             }
     404         347 :           }
     405             :         }
     406             :         else
     407             :         {
     408          86 :           const auto elem_range = _serialize
     409          86 :                                       ? _mesh_ptr->getMesh().active_element_ptr_range()
     410          86 :                                       : _mesh_ptr->getMesh().active_local_element_ptr_range();
     411        1526 :           for (const auto & elem : elem_range)
     412             :           {
     413        1440 :             if (elem->n_dofs(sys_num, var_num) &&
     414         720 :                 (_serialize || processor_id() == elem->processor_id()))
     415             :             {
     416         720 :               DenseVector<Real> value(1);
     417         720 :               if (var_blocks->size())
     418         288 :                 (*_mesh_functions[sys_num][var_num])(
     419         288 :                     elem->true_centroid() - _position, /*time*/ 0., value, var_blocks);
     420             :               else
     421         576 :                 value[0] = (*_mesh_functions[sys_num][var_num])(elem->true_centroid() - _position);
     422             : 
     423         720 :               if (value[0] != -1e6)
     424         720 :                 dest_sys.solution->set(elem->dof_number(sys_num, var_num, /*comp=*/0), value[0]);
     425             :               else
     426           0 :                 mooseDoOnce(mooseWarning(
     427             :                     "Sampling at location ",
     428             :                     elem->true_centroid() - _position,
     429             :                     " was outside the problem mesh.\nThis message will not be repeated."));
     430         720 :             }
     431          86 :           }
     432          86 :         }
     433             :       }
     434             : 
     435             :       // We modified the solution vector directly, we have to close it
     436         560 :       dest_sys.solution->close();
     437             :     }
     438             :   }
     439             : 
     440             :   // Set this to false so that new output files are not created, since the sampling mesh
     441             :   // doesn't actually change
     442         516 :   _sampling_mesh_changed = false;
     443             : }
     444             : 
     445             : void
     446         176 : SampledOutput::cloneMesh()
     447             : {
     448             :   // Create the new mesh from a file
     449         528 :   if (isParamValid("file"))
     450             :   {
     451          20 :     InputParameters mesh_params = _app.getFactory().getValidParams("FileMesh");
     452          10 :     mesh_params.applyParameters(parameters(), {}, true);
     453          10 :     mesh_params.set<bool>("nemesis") = false;
     454             :     _sampling_mesh_ptr =
     455          40 :         _app.getFactory().createUnique<MooseMesh>("FileMesh", "output_problem_mesh", mesh_params);
     456          10 :     _sampling_mesh_ptr->allowRecovery(false); // We actually want to reread the initial mesh
     457          10 :     _sampling_mesh_ptr->init();
     458          10 :   }
     459             :   // Clone the existing mesh
     460             :   else
     461             :   {
     462         166 :     if (_app.isRecovering())
     463           3 :       mooseWarning("Recovering or Restarting with oversampling may not work (especially with "
     464             :                    "adapted meshes)!!  Refs #2295");
     465         166 :     _sampling_mesh_ptr = _mesh_ptr->safeClone();
     466             :   }
     467             : 
     468             :   // Remove unspecified blocks
     469         528 :   if (isParamValid("sampling_blocks"))
     470             :   {
     471             :     // Remove all elements not in the blocks
     472          72 :     const auto & blocks_to_keep_names = getParam<std::vector<SubdomainName>>("sampling_blocks");
     473          36 :     const auto & blocks_to_keep = _sampling_mesh_ptr->getSubdomainIDs(blocks_to_keep_names);
     474         588 :     for (const auto & elem_ptr : _sampling_mesh_ptr->getMesh().element_ptr_range())
     475         552 :       if (std::find(blocks_to_keep.begin(), blocks_to_keep.end(), elem_ptr->subdomain_id()) ==
     476        1104 :           blocks_to_keep.end())
     477         276 :         _sampling_mesh_ptr->getMesh().delete_elem(elem_ptr);
     478             : 
     479             :     // Deleting elements and isolated nodes would cause renumbering. Not renumbering might help
     480             :     // user examining the sampling mesh and the regular mesh. Also if we end up partitioning the
     481             :     // elements, the node partitioning is unlikely to match if the element numbering is different.
     482             :     // Still not enough of a guarantee, because of deleted elements the node partitioning could be
     483             :     // different. We will rely on ghosting to make it work
     484          36 :     _sampling_mesh_ptr->getMesh().allow_renumbering(false);
     485          36 :   }
     486             : 
     487             :   // Set a partitioner
     488         176 :   if (!_serialize)
     489             :   {
     490          12 :     _sampling_mesh_ptr->setIsCustomPartitionerRequested(true);
     491          24 :     InputParameters partition_params = _app.getFactory().getValidParams("CopyMeshPartitioner");
     492          24 :     partition_params.set<MooseMesh *>("mesh") = _sampling_mesh_ptr.get();
     493          24 :     partition_params.set<MooseMesh *>("source_mesh") = _mesh_ptr;
     494          12 :     std::shared_ptr<MoosePartitioner> mp = _factory.create<MoosePartitioner>(
     495          36 :         "CopyMeshPartitioner", "sampled_output_part", partition_params);
     496          12 :     _sampling_mesh_ptr->setCustomPartitioner(mp.get());
     497             : 
     498          12 :     _sampling_mesh_ptr->getMesh().prepare_for_use();
     499             :     // this should be called by prepare_for_use, but is not.
     500             :     // it also requires a prior call to prepare_for_use()
     501          12 :     mp->partition(_sampling_mesh_ptr->getMesh(), comm().size());
     502          12 :   }
     503             : 
     504             :   // Prepare mesh, needed for the mesh functions
     505         176 :   if (_using_external_sampling_file)
     506          10 :     _sampling_mesh_ptr->prepare(/*mesh to clone*/ nullptr);
     507         474 :   else if (_serialize && isParamValid("sampling_blocks"))
     508             :     // TODO: constraints have not been initialized?
     509          24 :     _sampling_mesh_ptr->getMesh().prepare_for_use();
     510             : 
     511         176 :   if (_serialize)
     512             :     // we want to avoid re-partitioning, as we will serialize anyway
     513         164 :     _sampling_mesh_ptr->getMesh().skip_partitioning(true);
     514             : 
     515             :   // Make sure that the mesh pointer points to the newly cloned mesh
     516         176 :   _mesh_ptr = _sampling_mesh_ptr.get();
     517             : 
     518             :   // Check the source and target mesh in case their subdomains match
     519         176 :   const std::vector<SubdomainID> mesh_subdomain_ids_vec(_mesh_ptr->meshSubdomains().begin(),
     520         528 :                                                         _mesh_ptr->meshSubdomains().end());
     521             :   const std::vector<SubdomainID> initial_mesh_subdomain_ids_vec(
     522         176 :       _problem_ptr->mesh().meshSubdomains().begin(), _problem_ptr->mesh().meshSubdomains().end());
     523         176 :   _mesh_subdomains_match =
     524         186 :       (_mesh_ptr->meshSubdomains() == _problem_ptr->mesh().meshSubdomains() &&
     525         186 :        _mesh_ptr->getSubdomainNames(mesh_subdomain_ids_vec) ==
     526         186 :            _problem_ptr->mesh().getSubdomainNames(initial_mesh_subdomain_ids_vec));
     527         176 :   if (_using_external_sampling_file && !_mesh_subdomains_match)
     528           0 :     mooseInfoRepeated("Variable block restriction disabled in sampled output due to non-matching "
     529             :                       "subdomain names and ids");
     530         176 : }
     531             : 
     532             : void
     533       27913 : SampledOutput::setFileBaseInternal(const std::string & file_base)
     534             : {
     535       27913 :   AdvancedOutput::setFileBaseInternal(file_base);
     536             :   // ** DEPRECATED SUPPORT **
     537       83739 :   if (getParam<bool>("append_oversample"))
     538           0 :     _file_base += "_oversample";
     539       27913 : }
     540             : 
     541             : bool
     542         657 : SampledOutput::isSampledAtNodes(const FEType & fe_type) const
     543             : {
     544             :   // This is the same criterion as in MooseVariableData
     545         657 :   const auto continuity = FEInterface::get_continuity(fe_type);
     546         657 :   return (continuity == C_ZERO || continuity == C_ONE);
     547             : }

Generated by: LCOV version 1.14