Skip to content

Nemesis_IO_Helper::write_nodal_solution() silently drops vector-valued nodal variables #4565

Description

@kyriv-lab

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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions