Skip to content

Fix PML instability in Gmsh CPML MPI example#1274

Merged
danielpeter merged 2 commits into
SPECFEM:develfrom
mnagaso:fix/gmsh-cpml-pml-instability
Mar 31, 2026
Merged

Fix PML instability in Gmsh CPML MPI example#1274
danielpeter merged 2 commits into
SPECFEM:develfrom
mnagaso:fix/gmsh-cpml-pml-instability

Conversation

@mnagaso

@mnagaso mnagaso commented Mar 31, 2026

Copy link
Copy Markdown

Summary

Fixes numerical blowup (simulation instability) when using PML boundary conditions with external Gmsh meshes in the Gmsh_example_CPML_MPI example.

Problem

The SPECFEM2D simulation blows up when using CPML with Gmsh-generated external meshes, particularly at the top boundary. The internal mesher works correctly for the same configuration.

Root Cause

Three bugs were identified in the Gmsh mesh converter (meshio2spec2d.py) and geometry builder (create_geom_with_pygmsh.py):

Bug 1: pml_transition_layer default removes PML elements

meshio2spec2d.py: The write() method defaulted pml_transition_layer=True, which called get_cpml_cells_except_damping() to remove the innermost PML row. For a 3-element PML (NELEM_PML_THICKNESS=3), this reduced the effective PML to 2 layers — insufficient for stable absorption, causing late-time blowup.

Fix: Changed default to pml_transition_layer=False.

Bug 2: Missing absorbing boundary flags for CPML

meshio2spec2d.py: When CPML is used, all outer PML boundaries need absorbing edges for Dirichlet boundary conditions (see pml_init.F90: determine_boundary_abs_points_PML()). The top_abs flag defaulted to False, meaning the top absorbing boundary was missing when CPML was detected.

Fix: Auto-set all *_abs flags to True when CPML physical groups are detected.

Bug 3: Spurious inner boundary when top_pml=False

create_geom_with_pygmsh.py: When top_pml=False, the top domain rectangle was tagged "Top", which created a spurious _Top inner boundary (the bottom edge of the top domain rectangle). For multi-rectangle models, this incorrectly excluded side PML elements near the domain-top interface.

Fix: Introduced "TopFree" tag that adds the outer edge to the Top physical group without creating an inner boundary.

Files Changed

  • meshio2spec2d.py: Default pml_transition_layer changed to False; auto-detect absorbing flags when CPML is used
  • create_geom_with_pygmsh.py: New "TopFree" boundary tag for non-PML top boundary
  • create_mesh_topo.ipynb: Updated write() call to use pml_transition_layer=False
  • MESH/*: Regenerated mesh files with fixed code
  • DATA/STATIONS: Updated station file

Testing

The simulation was run with 4 MPI ranks for 10,000 timesteps (DT=0.002, total time 20s) and completed stably. Final wavefield amplitudes remained bounded (elastic max norm: 4.22e-04, acoustic max: 188.0).

mnagaso added 2 commits March 31, 2026 09:33
Three bugs caused numerical blowup with PML boundary conditions when
using external Gmsh meshes:

1. meshio2spec2d.py: pml_transition_layer default was True, which removed
   the innermost PML row via get_cpml_cells_except_damping(). For a
   3-element PML this left only 2 layers - insufficient for absorption.
   Changed default to False.

2. meshio2spec2d.py: When CPML is detected (PML_X physical group exists),
   all outer PML boundaries now auto-set their absorbing flags to True.
   This ensures Dirichlet BCs are applied at outer PML edges as required
   by determine_boundary_abs_points_PML() in pml_init.F90.

3. create_geom_with_pygmsh.py: When top_pml=False, the top domain
   rectangle was tagged 'Top' which created a spurious '_Top' inner
   boundary. Introduced 'TopFree' tag that adds the outer edge to the
   Top physical group without creating an inner boundary.

Updated create_mesh_topo.ipynb and regenerated MESH files accordingly.
Previously, the offset was hardcoded to the minimum cell ID of M1,
which causes wrong material assignments when another material has a
smaller minimum cell ID. Now the offset is the global minimum cell ID
across all material keys (M1, M2, ...).
@danielpeter

Copy link
Copy Markdown
Member

thanks for this update :)

@danielpeter danielpeter merged commit 24593fa into SPECFEM:devel Mar 31, 2026
31 checks passed
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.

2 participants