Skip to content

fix(helpers): resolve .msh format ambiguity between Ansys and GMSH writers#4

Open
fznoussi wants to merge 1 commit into
mainfrom
fix/helper_pick_best_MSH_format
Open

fix(helpers): resolve .msh format ambiguity between Ansys and GMSH writers#4
fznoussi wants to merge 1 commit into
mainfrom
fix/helper_pick_best_MSH_format

Conversation

@fznoussi
Copy link
Copy Markdown
Collaborator

@fznoussi fznoussi commented May 11, 2026

fix(helpers): resolve .msh format ambiguity between Ansys and GMSH writers

When converting a MED file to MSH format:

$ meshio convert mesh.med output.msh

the output was silently written by the Ansys writer instead of the GMSH
writer, producing a file with no metadata and no error:

expected: GMSH .msh with $PhysicalNames, $Entities, $Nodes

actual: Ansys .msh with no groups, no physical names

Root cause: the .msh extension is shared between Ansys and GMSH.
_filetypes_from_path() returns both formats and the code was blindly
picking the first one:

file_formats = _filetypes_from_path(Path("output.msh"))

-> ['ansys', 'gmsh']

file_format = file_formats[0]

-> 'ansys' <- Ansys writer called silently

Fix A : Add _pick_best_format() to resolve ambiguous extensions

When multiple formats share the same extension, the mesh metadata
is inspected to determine the most appropriate writer.

GMSH is preferred over Ansys when any of the following keys are
present in cell_data, point_data or field_data:

  • GMSH-specific keys : gmsh:physical, gmsh:geometrical, gmsh:dim_tags
  • MED-specific keys : cell_tags, point_tags, med:*

def _pick_best_format(file_formats, mesh):
if "gmsh" in file_formats:
gmsh_keys = {"gmsh:physical", "gmsh:geometrical", "gmsh:dim_tags"}
med_keys = {"cell_tags", "point_tags"}
has_gmsh = bool(gmsh_keys & set(mesh.cell_data.keys()))
or bool(gmsh_keys & set(mesh.point_data.keys()))
has_med = bool(med_keys & set(mesh.cell_data.keys()))
or bool(med_keys & set(mesh.point_data.keys()))
or any(k.startswith("med:") for k in mesh.field_data)
if has_gmsh or has_med:
return "gmsh"
return file_formats[0]

The fallback to file_formats[0] preserves the original behaviour for
all cases where no metadata hint is available.

Fix B : Call _pick_best_format() only when ambiguity exists

_pick_best_format() is only invoked when more than one format matches
the extension, avoiding any overhead on unambiguous extensions:

BEFORE

file_format = file_formats[0]

AFTER

if len(file_formats) > 1:
file_format = _pick_best_format(file_formats, mesh)
else:
file_format = file_formats[0]

Confirmed against mesh.med generated by GMSH 4.13:

$ meshio convert mesh.med output.msh
$ meshio info output.msh

Before: Ansys writer selected, 1 block, no $PhysicalNames
After : GMSH writer selected, 6 blocks, $PhysicalNames contains "subgroup"

Fixes nschloe#1541

  $ meshio convert mesh.med output.msh

the output was silently written by the Ansys writer instead of the GMSH
writer, producing a file with no metadata and no error:

  # expected: GMSH .msh with , ,
  # actual:   Ansys .msh with no groups, no physical names

Root cause: the .msh extension is shared between Ansys and GMSH.
_filetypes_from_path() returns both formats and the code was blindly
picking the first one:

  file_formats = _filetypes_from_path(Path(output.msh))
  # -> ['ansys', 'gmsh']

  file_format = file_formats[0]
  # -> 'ansys'  <- Ansys writer called silently

Fix A - Add _pick_best_format() to resolve ambiguous extensions

  When multiple formats share the same extension, the mesh metadata
  is inspected to determine the most appropriate writer.

  GMSH is preferred over Ansys when any of the following keys are
  present in cell_data, point_data or field_data:

  - GMSH-specific keys : gmsh:physical, gmsh:geometrical, gmsh:dim_tags
  - MED-specific keys  : cell_tags, point_tags, med:*

  def _pick_best_format(file_formats, mesh):
      if gmsh in file_formats:
          gmsh_keys = {gmsh:physical, gmsh:geometrical, gmsh:dim_tags}
          med_keys  = {cell_tags, point_tags}
          has_gmsh = bool(gmsh_keys & set(mesh.cell_data.keys()))                   or bool(gmsh_keys & set(mesh.point_data.keys()))
          has_med  = bool(med_keys & set(mesh.cell_data.keys()))                    or bool(med_keys & set(mesh.point_data.keys()))                    or any(k.startswith(med:) for k in mesh.field_data)
          if has_gmsh or has_med:
              return gmsh
      return file_formats[0]

  The fallback to file_formats[0] preserves the original behaviour for
  all cases where no metadata hint is available.

Fix B - Call _pick_best_format() only when ambiguity exists

  _pick_best_format() is only invoked when more than one format matches
  the extension, avoiding any overhead on unambiguous extensions:

  # BEFORE
  file_format = file_formats[0]

  # AFTER
  if len(file_formats) > 1:
      file_format = _pick_best_format(file_formats, mesh)
  else:
      file_format = file_formats[0]

Confirmed against mesh.med generated by GMSH 4.13:

  $ meshio convert mesh.med output.msh
  $ meshio info output.msh

  Before: Ansys writer selected, 1 block, no
  After : GMSH writer selected, 6 blocks,  contains subgroup
@fznoussi fznoussi changed the title When converting a MED file to MSH format: fix(helpers): resolve .msh format ambiguity between Ansys and GMSH writers May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Unable to convert between .msh and .med or read info from .med ("MED files cannot have two sections of the same cell type")

1 participant