Skip to content

Conversation

bch0w
Copy link
Member

@bch0w bch0w commented Aug 21, 2025

See Issues #245, #231 for motivation

Motivation

Total revamp to the Model class which is used to store and manipulate Model and Gradients for the purpose of updating models, scaling gradients, taking dot products etc. The previous approach brought the entire model vector in as a custom class which stored dictionaries of arrays, and did manipulations on 1D vectors stored as NumPy arrays. This was fine for regional scale problems inverting for a small number of parameters, but quickly became a bottleneck in terms of large I/O operations when parameter number increased (e.g., 21 parameter anisotropy).

This PR addresses that by doing away with the old system completely and rewriting a new specfem_model.Model class.

Changes

  • New Approach: Model class now no longer stores arrays in memory, but instead just references filenames of SPECFEM FORTRAN binary files
  • Model Manipulation: When operations are performed (e.g., multiplying gradient by -1 to get search direction), each individual file (e.g., proc000000_vs_kernel.bin) is read, manipulated, and written individually. This removes the need to store the entire model in RAM at once which can be a large operation.
  • Parallel: Operations are parallelized with Concurrent futures where possible. That way each process will read an individual file, manipulate, and write it (to the same place or a new location) without knowledge of any of the other processes
  • Efficient use of I/O: Previously whenever we did manipulations we had to do them one at a time, which meant reading all files into memory, doing something, writing them back, and then reading the written files etc. Inefficient. Now the Model.apply() function allows chaining multiple actions together so that files only have to be read in once.
  • Helper Functions: Model.get() has a few options for efficiently getting values from the Model vector, such as the min and max values, vector mean, etc. There are also other operations Model.dot() to get the dot product, or Model.mag() to get the magnitude of the Model vector and Model.angle() to find the angle between two vectors.
  • Tests: Some new tests to cover the main processing functions of the model class but this is still a work in progress

Riders

  • Cleaned up the SPECFEM2D model plotting
  • Slightly cleaner approach to defining and calling scratch directory names
  • Example 2: Changed default smoothing length from 5km to 20km for stronger regularization

Bugfixes

  • The previous function definition for calculating angles between two vectors may have been wrong (seisflows.tools.math.angle). Need to double check
  • Pyaflowa was allowing inversion to continue even if no windows were selected because it would just treat that as 0 misfit. Now the workflow exits if no windows are found for any source

Removed

These are currently removed, may make it back in before I merge, just want it recorded here

  • Model checks for Poissons ratio errors and negative velocities
  • Model print statements
  • NLCG optimization module, this was not working

Example

Here's some examples of how this is called in the code

# Points to a path containing SPECFEM FORTRAN Binary files
g = Model(path=self.path._g_new)  

# Multiply the gradient `g` by -1 and save the files to a new path
# the new variable `p_new` is lightweight, only containing filenames
p_new = g.apply(actions=["*"], values=[-1], 
                export_to=self.path._p_new)
g = Model(path=self.path._g_new)  # current gradient
p = Model(path=self.path._p_new)  # current search direction

# Take the dot product, easily readable
gtg = g.dot(g)
gtp = g.dot(p)

bch0w added 30 commits March 22, 2025 20:32
…fic class

basic functionality for model input and serial looping created
bombed out a few functionalities and merged a few functions together
…g on manipulating with another model

adding tests in test_tools to cover use cases
…ceptable actions to symbols not words to make it easier
…ose, honestly not sure why I didn't do this is the first palce
…st but they atleast match the current version
…t's wrong, will revert back but committing so I have a record
…inal seisflows? it was not producing the correct angle between a vector and itself in more than 2 dimensions. Need to doublecheck, rewrote it with an additional magnitude definition which is parallellized. Probably increased overhead from the concurrent futures but hopefully a speedup
…ian_to_gradient' to make it clear what this function is doing. condensed two function calls into one to keep things cleaner in compute direciton
…to warn users that this module is pretty rough and shoudl be used at own discretion
running into issues with not exposing the Model files to the optimization library
…o figure out all the places things are going wrong
…contained in the graphics tools now rather than split across multipler areas
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

optimize Model class for models with large number of parameters potential speed-up opportunities
1 participant