Description
Nemesis_IO_Helper::write_nodal_solution(const EquationSystems &, ...) silently drops vector-valued nodal variables (LAGRANGE_VEC, 1st-order MONOMIAL_VEC) instead of writing their values, leaving Exodus/NetCDF's default fill value (~9.97e+36) in their slots in the output file.
Root cause
// src/mesh/nemesis_io_helper.C, ~line 2450
void Nemesis_IO_Helper::write_nodal_solution(const EquationSystems & es,
const std::vector<std::pair<unsigned int, unsigned int>> & var_nums,
int timestep,
const std::vector<std::string> & output_names)
{
...
for (auto [sys_num, var] : var_nums)
{
const System & sys = es.get_system(sys_num);
const std::string & name = sys.variable_name(var);
auto pos = std::find(output_names.begin(), output_names.end(), name);
// Skip this name if it's not supposed to be output.
if (pos == output_names.end())
continue;
...
sys.variable_name(var) returns the unsuffixed variable name (e.g. "disp"), but output_names at this point only contains the suffixed per-component names ("disp_x", "disp_y", "disp_z") produced by EquationSystems::find_variable_numbers_by_predicate(). The lookup always fails for a vector variable, continue is hit, and the variable's values are never written to file — even though the disp_x/_y/_z slots were already created in the Exodus/Nemesis file.
This explains why 1st-order MONOMIAL_VEC and LAGRANGE_VEC are affected but constant MONOMIAL_VEC is not: constant MONOMIAL_VEC is classified as elemental data by EquationSystems::is_elemental_data_fe_type() and goes through write_element_values() instead, which is vector-aware (and was recently cleaned up in 9c8c56f, "Cleanup output system for writing truly constant monomial data"). LAGRANGE_VEC and 1st-order MONOMIAL_VEC are nodal, so they go through the buggy write_nodal_solution() path above, which has never been given equivalent TYPE_VECTOR handling. The unsuffixed-name lookup dates back to acea473 ("write_nodal_data(EquationSystems) overload", 2019) and has not been touched since.
Reproduction
Create a nodal vector auxiliary/solution variable (LAGRANGE_VEC, or 1st-order MONOMIAL_VEC) and write it out via Nemesis output. The variable's suffixed component slots (_x/_y/_z) are created in the file, but never populated, and read back as Exodus/NetCDF's default fill value.
Impact
Nodal vector-variable output through Nemesis is unusable; the only workaround is to output each component separately via a scalar aux kernel.
Test coverage gap
test/tests/outputs/nemesis/ (in the MOOSE test suite) only covers scalar variables (nemesis.i, nemesis_elemental.i, nemesis_scalar.i); none exercise LAGRANGE_VEC/MONOMIAL_VEC, so this regression would not be caught by existing CI.
Context
Originally reported downstream in idaholab/moose#24193 (discussion idaholab/moose#24135), with the elemental/nodal write-path split noticed there matching the symptom exactly (garbage-value nodal output vs. working constant elemental output).
Description
Nemesis_IO_Helper::write_nodal_solution(const EquationSystems &, ...)silently drops vector-valued nodal variables (LAGRANGE_VEC, 1st-orderMONOMIAL_VEC) instead of writing their values, leaving Exodus/NetCDF's default fill value (~9.97e+36) in their slots in the output file.Root cause
sys.variable_name(var)returns the unsuffixed variable name (e.g."disp"), butoutput_namesat this point only contains the suffixed per-component names ("disp_x","disp_y","disp_z") produced byEquationSystems::find_variable_numbers_by_predicate(). The lookup always fails for a vector variable,continueis hit, and the variable's values are never written to file — even though thedisp_x/_y/_zslots were already created in the Exodus/Nemesis file.This explains why 1st-order
MONOMIAL_VECandLAGRANGE_VECare affected but constantMONOMIAL_VECis not: constantMONOMIAL_VECis classified as elemental data byEquationSystems::is_elemental_data_fe_type()and goes throughwrite_element_values()instead, which is vector-aware (and was recently cleaned up in 9c8c56f, "Cleanup output system for writing truly constant monomial data").LAGRANGE_VECand 1st-orderMONOMIAL_VECare nodal, so they go through the buggywrite_nodal_solution()path above, which has never been given equivalentTYPE_VECTORhandling. The unsuffixed-name lookup dates back to acea473 ("write_nodal_data(EquationSystems) overload", 2019) and has not been touched since.Reproduction
Create a nodal vector auxiliary/solution variable (
LAGRANGE_VEC, or 1st-orderMONOMIAL_VEC) and write it out via Nemesis output. The variable's suffixed component slots (_x/_y/_z) are created in the file, but never populated, and read back as Exodus/NetCDF's default fill value.Impact
Nodal vector-variable output through Nemesis is unusable; the only workaround is to output each component separately via a scalar aux kernel.
Test coverage gap
test/tests/outputs/nemesis/(in the MOOSE test suite) only covers scalar variables (nemesis.i,nemesis_elemental.i,nemesis_scalar.i); none exerciseLAGRANGE_VEC/MONOMIAL_VEC, so this regression would not be caught by existing CI.Context
Originally reported downstream in idaholab/moose#24193 (discussion idaholab/moose#24135), with the elemental/nodal write-path split noticed there matching the symptom exactly (garbage-value nodal output vs. working constant elemental output).