Migrating from SPECFEM2D Fortran to SPECFEM++¶
This tutorial demonstrates how to migrate a SPECFEM2D Fortran example to the
SPECFEM++ format using the anisotropic zinc crystal example. The original
SPECFEM2D uses a single Par_file for both meshing and simulation, while
SPECFEM++ separates these concerns into multiple configuration files.
Note
Not all physics are yet supported in SPECFEM++. This example focuses on currently working changes (the list may not be complete).
- NOT SUPPORTED:
- General physics
Attenuation
Axisymmetric simulations
Noise tomography
- Timeschemes
Classical 4-th order Runge-Kutta
LDDRK
- Sources
Moving sources
Bielak conditions
Acoustic forcing
- Seismogram Output formats
Seismic Unix
Binary
- Boundary Conditions
PML
- Architecture
MPI
Simultaneous runs
Original SPECFEM2D Structure¶
The original example located at
/specfem2d/EXAMPLES/applications/anisotropy/anisotropic_zinc_crystal/
in the SPECFEM2D repository contains:
anisotropic_zinc_crystal/
├── DATA/
│ ├── Par_file # Single configuration file
│ ├── SOURCE # Fortran-style source definition
│ └── topoaniso.dat # Topography file
└── run_this_example.sh # Execution script
You download Anisotropic Crystal ZIP to
access the original example.
The specfem fortran execution patter uses a single Par_file for both meshing
and simulation:
./bin/xmeshfem2D # Uses Par_file for meshing
./bin/xspecfem2D # Uses Par_file for simulation
SPECFEM++ Structure¶
The SPECFEM++ version separates the configuration into multiple files for clarity and modularity.
anisotropic-crystal/
├── Par_file # Updated: Mesh parameters [and receiver parameters]
├── specfem_config.yaml # New: Solver configuration
├── source.yaml # New: Source parameters
└── topoaniso.dat # Unchanged: Topography file
Execution uses a two-step workflow:
xmeshfem2D -p Par_file # Meshing only [and receiver generation]
specfem2d -p specfem_config.yaml # Simulation with YAML config
The reason we want to separate the configuration files is to improve clarity and modularity, as well as distinguishing between fortran code and new C++ implementation.
Migration Steps¶
These steps will follow how we approach updates to the original
Par_file and translation to the new SPECFEM++ structure.
Step 1: Split the Par_file¶
The original Par_file contains both meshing and simulation parameters. In
SPECFEM++, we separate these:
Parameters to keep from the Par_file (meshing parameters):
# Title and output directory (required in SPECFEM++)
title = Anisotropic Crystal
# Mesh parameters
NPROC = 1
PARTITIONING_TYPE = 3
NGNOD = 4
# Receiver parameters
use_existing_STATIONS = .false.
nreceiversets = 1
anglerec = 0.d0 # angle to rotate components at receivers
rec_normal_to_surface = .false. # base anglerec normal to surface (external mesh and curve file needed)
nrec = 50 # number of receivers
xdeb = 0.05 # first receiver x in meters
zdeb = 0.2640 # first receiver z in meters
xfin = 0.28 # last receiver x in meters (ignored if only one receiver)
zfin = 0.2640 # last receiver z in meters (ignored if only one receiver)
record_at_surface_same_vertical = .false. # receivers inside the medium or at the surface
stations_filename = ./OUTPUT_FILES/STATIONS
# Boundary conditions
STACEY_ABSORBING_CONDITIONS = .false.
absorbbottom = .false.
absorbright = .false.
absorbtop = .false.
absorbleft = .false.
# Material and mesh geometry
nbmodels = 1
# anisotropic: model_number 2 rho c11 c13 c15 c33 c35 c55 c12 c23 c25 0 0 0
1 2 7100. 16.5d10 5.d10 0 6.2d10 0 3.96d10 0 0 0 0 0 0
# External files
TOMOGRAPHY_FILE = ./DATA/tomo_file.xyz
read_external_mesh = .false.
interfacesfile = topoaniso.dat
# Domain geometry
xmin = 0.d0
xmax = 0.33
nx = 60
# Regions
nbregions = 1
# format: nxmin nxmax nzmin nzmax material_number
1 60 1 60 1
# Display parameters (for meshing output)
output_grid_Gnuplot = .false.
output_grid_ASCII = .false.
Additional Par_file parameters:
Add these to the Par_file:
OUTPUT_FILES = OUTPUT_FILES
database_filename = ./OUTPUT_FILES/database.bin
stations_filename = ./OUTPUT_FILES/STATIONS
Add new specfem_config.yaml (simulation parameters):
The solver parameters are converted from Fortran format to YAML:
parameters:
header:
title: Anisotropic Crystal
description: |
Wave propagation through anisotropic zinc crystal
simulation-setup:
elastic-wave: "P_SV" # P_SV = .true.
quadrature:
quadrature-type: GLL4
solver:
time-marching:
type-of-simulation: forward
time-scheme:
type: Newmark. # time_stepping_scheme = 1 in Par_file
dt: 55.e-9 # From DT in Par_file
nstep: 1500 # From NSTEP in Par_file
simulation-mode:
forward:
writer:
seismogram: # save_ASCII_seismograms = .true.
format: ascii
directory: ./OUTPUT_FILES/seismograms
display: # Visualization parameters too different to list here
format: PNG
directory: ./OUTPUT_FILES/display
field: displacement
simulation-field: forward
time-interval: 100 # From NTSTEP_BETWEEN_OUTPUT_IMAGES
receivers:
stations: "./OUTPUT_FILES/STATIONS"
angle: 0.0
seismogram-type:
- displacement
nstep_between_samples: 1
run-setup:
number-of-processors: 1
number-of-runs: 1
databases:
mesh-database: "./OUTPUT_FILES/database.bin"
sources: "./source.yaml"
Here, it is easiest to copy the box, where we already added the necessary parameters.
The writer.display is too different to list all the different changes, but we believe the parameters are fairly self-explanatory. See the SPECFEM++ Parameter Documentation for additional details.
Step 2: Convert SOURCE to source.yaml¶
The original SOURCE file uses Fortran-style parameters:
source_surf = .false.
xs = 0.165
zs = 0.165
source_type = 1
time_function_type = 1
f0 = 170000.
tshift = 0.0
anglesource = 0.0
factor = 1.d10
vx = 0.0
vz = 0.0
This converts to YAML format in source.yaml:
number-of-sources: 1
sources:
- force:
x : 0.165
z : 0.165
source_surf: false
angle : 0.0
vx : 0.0
vz : 0.0
Ricker:
factor: 1e10
tshift: 0.0
f0: 170000.0
Note
Instead of numbers we use names for the different source time functions. The Ricker wavelet is used here, but you can define other types as needed. Some of the supported time functions include: - Ricker - Gaussian - dGaussian (first derivative of Gaussian) - external Please refer to the parameters documentation for more details. See Source Description for more information on the source parameters.
Running the example using SPECFEM++¶
# Create output directories as specified in Par_file and specfem_config.yaml
mkdir -p OUTPUT_FILES/seismograms OUTPUT_FILES/display
# Separate configuration files
xmeshfem2D -p Par_file
specfem2d -p specfem_config.yaml
Summary¶
This migration pattern applies to any SPECFEM2D example - identify meshing vs. solver parameters, convert source definitions to YAML, and structure the configuration files according to their specific roles in the simulation workflow.
Benefits of the New Structure¶
Separation of Concerns:
- Meshing parameters stay in Par_file
- Solver parameters moved to specfem_config.yaml
Improved Readability: - YAML format is more human-readable - Hierarchical structure reflects parameter relationships - Clear separation between different simulation aspects
Parameter Mapping Reference¶
Here, we list a non-exhaustive mapping of parameters from the original
anisotropic zinc crystal example to the new SPECFEM++ format. This is useful for
understanding how to translate the parameters from the Fortran
Par_file and SOURCE file to the new SPECFEM++ configuration files.
Par_file Parameters¶
Some parameters are newly added or modified in SPECFEM++:
SPECFEM2D Par_file |
SPECFEM++ Par_file |
|---|---|
|
|
(implicit output directory) |
|
(implicit stations file) |
|
Solver Parameters¶
SPECFEM2D Par_file |
SPECFEM++ specfem_config.yaml |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source Parameters¶
Only listing the parameters that are different from the original Fortran
SOURCE file:
SPECFEM2D SOURCE |
SPECFEM++ source.yaml |
|---|---|
|
|
|
|
|
|
|
|
|
|