Skip to content

Refactoring PML#249

Open
ruansava wants to merge 17 commits into
mainfrom
ruben/pml
Open

Refactoring PML#249
ruansava wants to merge 17 commits into
mainfrom
ruben/pml

Conversation

@ruansava

Copy link
Copy Markdown
Collaborator

Introduces a refactored PML formulation

Refactor PML solver and add cost save option
Introduce abc package and PML support
Refactor variable names
Refactor PML/ABC, add NRBC and damping helpers
HABC > PML
Add Neumann BC support and test updates
@ruansava
ruansava requested review from Ig-dolci and Olender March 24, 2026 19:36
ruansava added 11 commits March 24, 2026 19:30
Add PML tests and initialize isotropic params
Add PML support and robustness fixes across modules
Introducing profilers
Allow skipping model init in IsotropicWave
Set wave.c to initial_velocity_model in tests
Set model velocity, add PML wrapper and test fixes
Fix gradient scaling and IsotropicWave inits
Add automatic mesh and update tests/tools

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these files be here?

@ruansava ruansava Apr 1, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! This would be an "output" folder

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to run make clean before opening a PR

Comment thread spyro/abc/rec_lay.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure this should be a class. Can't it just be that one method that this calss contains?

'''

# Add specific attributes for run PML solver
self.c = self.initial_velocity_model

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be done here

- final_energy : Dissipated energy in the HABC scheme
f_Nyq : `float`
Nyquist frequency according to the time step. f_Nyq = 1 / (2 * dt)
f_Nyquist : `float`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES!!!!

Finite element order for the Eikonal analysis
abc_get_ref_model : `bool`
If True, the infinite model is created
abc_user_pad_length : `bool`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this new parameter and functionality

if value == "PML":
abc_dictionary.setdefault("exponent", 2)
self.abc_exponent = abc_dictionary["exponent"]
abc_dictionary.setdefault("R", 1e-6)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no default cmax anymore? So in my opinion, during FWI c changes. However, we know previously what the cmax is going to be and can use this value for both optimization boundaries and PML calculation (I don't think the PML should change during FWI toghether with the velocity model)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same with HABC, properties should change with the iterations. If there is no update, you can increase your reflections. You can set with the initial velocity model and maintain fixed. The idea is always to extract the maximum quantity of parameters from data automatically

Comment thread spyro/io/dictionaryio.py
options_dictionary = dictionary["options"]

# Check if dictionary is empty or doesn't have 'options'
options_dictionary = dictionary.get("options", {})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like a simple fail if the options key doesn't exist

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, this should be different
def init(self, dictionary=None) because kargs should not be set with mutable objects: dictionary, list, tuple, etc
I use options_dictionary = dictionary.get("options", {}) because some text didn't need additional data

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be called inside the automaticmeshing class. If there are non existing inputs in the meshing parameter class, please put them there

self.cellVertices,
self.cellNodeMaps,
) = self.__point_locator()
(self.cellIDs, self.cellVertices,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLease do not do this. It makes it harder to review and there's nothing worng with how it was

'''Isotropic elastic wave propagator'''

def __init__(self, dictionary, comm=None):
def __init__(self, dictionary, empty_set_property=False, comm=None):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this parameter should be here. We deal with this in the model_parameters class

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is the field synthetic data of dicitionary of IsotropicWave. In fact, it should be made in an empty ELasticWave object; however this class is abstract. Another problem is the check that currently has this class. Without this test of material properties does not run and this should be provisionally because this class will be completely refactored. Then, when synthetic data will be deleted this field will disappear.
Another options is set with Wave class directly

self.field_logger.add_functional("mechanical_energy",
lambda: assemble(self.mechanical_energy))

if not empty_set_property:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be in this class

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see previous comment

def construct_solver_or_matrix_no_pml(Wave_object):
"""Builds solver operators for wave object without a PML. Doesn't create mass matrices if
matrix_free option is on, which it is by default.
'''

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't do these formatting changes. Not only are they not numpy docs style, they make reviews harder

Wave_object.u_np1 = u_np1

Wave_object.current_time = 0.0
Wave_object.current_time = 0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't do these formatting changes. They make reviews harder. If you want X.0 float to be X, we can discuss this on a wednsday and then apply changes on a single code wide PR that only changes that

)
m1 = ((Constant(1.) / (Wave_object.c * Wave_object.c))
* ((u - 2. * u_n + u_nm1) / Constant(dt**2))
* v * dx(**quad_rule))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the previous format since it is easier to follow open and closed parantheses. Also, same as the other formatting comments

a = dot(grad(u_n), grad(v)) * dx(**quad_rule) # explicit

le = 0.0
le = 0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't do these formatting changes. They make reviews harder. If you want X.0 float to be X, we can discuss this on a wednsday and then apply changes on a single code wide PR that only changes that

weak_expr_abc = dot((u_n - u_nm1) / Constant(dt), v)

f_abc = (1 / Wave_object.c) * weak_expr_abc
f_abc = (Constant(1.) / Wave_object.c) * weak_expr_abc

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 1 doesn't change during the code so it doesn't really need to be a constant. At least thats how I understand it, but I don't see any benefit to this change

# Damping
le += Wave_object.eta_mask * weak_expr_abc * \
(1 / (Wave_object.c * Wave_object.c)) * \
(Constant(1.) / (Wave_object.c * Wave_object.c)) * \

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before

if Wave_object.absorb_left:
le += f_abc*ds(4, **qr_s)
# Only NRBC
bnds = [Wave_object.absorb_top, Wave_object.absorb_bottom,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the clarity of your approach here

lin_var = fire.LinearVariationalProblem(
Wave_object.lhs,
Wave_object.rhs + Wave_object.source_function,
Wave_object.lhs, Wave_object.rhs + Wave_object.source_function,

@Olender Olender Apr 1, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before

Wave_object.solver = fire.LinearVariationalSolver(
lin_var, solver_parameters=solver_parameters,
)
lin_var, solver_parameters=solver_parameters)

@Olender Olender Apr 1, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as before

@Olender Olender Apr 1, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let's follow the code formatting approach we talked about in the meeting

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to stop here for today

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think of all the innocent merge conflicts you’re unleashing into the world! Think of the branches! Think of the rebases. Think of the developers who will stare into the void after a 500-line “purely cosmetic” diff!

self.initial_velocity_model = self.guess_velocity_model
if c is not None:
self.initial_velocity_model.dat.data[:] = c
self.c = self.initial_velocity_model

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be necessary. Something wrong is going on somewhere else

spyro_plot_model(Wave_obj_real_velocity, filename=model_filename, abc_points=abc_points, high_resolution=high_resolution_model)
spyro_plot_model(Wave_obj_real_velocity, filename=model_filename, abc_points=abc_points)

Wave_obj_real_velocity.c = Wave_obj_real_velocity.initial_velocity_model

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be here. Having this happen in a lot of places in the code is a major point of failure that will be hard to debug

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