# Devito Self Adjoint modeling operators ## These operators are contributed by Chevron Energy Technology Company (2020) These operators are based on simplfications of the systems presented in:
**Self-adjoint, energy-conserving second-order pseudoacoustic systems for VTI and TTI media for reverse migration and full-waveform inversion** (2016)
Kenneth Bube, John Washbourne, Raymond Ergas, and Tamas Nemeth
SEG Technical Program Expanded Abstracts
https://library.seg.org/doi/10.1190/segam2016-13878451.1 ## Tutorial goal The goal of this series of tutorials is to generate -- and then test for correctness -- the modeling and inversion capability in Devito for variable density visco- acoustics. We use an energy conserving form of the wave equation that is *self adjoint*, which allows the same modeling system to be used for all for all phases of finite difference evolution required for quasi-Newton optimization: - **nonlinear forward**, nonlinear with respect to the model parameters - **Jacobian forward**, linearized with respect to the model parameters - **Jacobian adjoint**, linearized with respect to the model parameters These notebooks first implement and then test for correctness for three types of modeling physics. | Physics | Implementation | Notebook | |:----------------|:--------------------------|:----------------------------------| | Isotropic | Nonlinear ops | [sa_01_iso_implementation1.ipynb] | | Isotropic | Linearized ops | [sa_02_iso_implementation2.ipynb] | | Isotropic | Correctness tests | [sa_03_iso_correctness.ipynb] | |-----------------|---------------------------|-----------------------------------| | VTI Anisotropic | Nonlinear/linearized ops | [sa_11_vti_implementation.ipynb] | | VTI Anisotropic | Correctness tests | [sa_12_vti_correctness.ipynb] | |-----------------|---------------------------|-----------------------------------| | TTI Anisotropic | Nonlinear/linearized ops | [sa_21_tti_implementation.ipynb] | | TTI Anisotropic | Correctness tests | [sa_22_tti_correctness.ipynb] | |:----------------|:--------------------------|:----------------------------------| [sa_01_iso_implementation1.ipynb]: sa_01_iso_implementation1.ipynb [sa_02_iso_implementation2.ipynb]: sa_02_iso_implementation2.ipynb [sa_03_iso_correctness.ipynb]: sa_03_iso_correctness.ipynb [sa_11_vti_implementation.ipynb]: sa_11_vti_implementation.ipynb [sa_12_vti_correctness.ipynb]: sa_12_vti_correctness.ipynb [sa_21_tti_implementation.ipynb]: sa_21_tti_implementation.ipynb [sa_22_tti_correctness.ipynb]: sa_22_tti_correctness.ipynb ## Running unit tests - if you would like to see stdout when running the tests, use ```py.test -c testUtils.py``` ## TODO - [X] Devito-esque equation version of setup_w_over_q - [ ] figure out weird test failure depending on the order of equations in operator **Equation order 1** ``` return Operator([dm_update] + eqn + rec_term, subs=spacing_map, name='IsoJacobianAdjOperator', **kwargs) ``` **Equation order 2** ``` return Operator(eqn + rec_term + [dm_update], subs=spacing_map, name='IsoJacobianAdjOperator', **kwargs) ``` - With Equation order 1, all tests pass - With Equation order 2, there are different outcomes for tests - Possibly there is a different path chosen through the AST, and different c code is generated? - [ ] replace the conditional logic in the stencil with comprehension ``` space_fd = sum([getattr(b * getattr(field, 'd%s'%d.name)(x0=d+d.spacing/2)), 'd%s'%d.name)(x0=d-d.spacing/2)) for d in field.dimensions[1:]]) ``` - [ ] Add memoized methods back to wavesolver.py - [ ] Add ensureSanityOfFields methods for iso, vti, tti - [ ] Add timing info via logging for the w_over_q setup, as in initialize_damp - [ ] Add smoother back to setup_w_over_q method ``` eqn1 = Eq(wOverQ, val) Operator([eqn1], name='WOverQ_Operator_init')() # If we apply the smoother, we must renormalize output to [qmin,qmax] if sigma > 0: smooth = gaussian_smooth(wOverQ.data, sigma=sigma) smin, smax = np.min(smooth), np.max(smooth) smooth[:] = qmin + (qmax - qmin) * (smooth - smin) / (smax - smin) wOverQ.data[:] = smooth eqn2 = Eq(wOverQ, w / wOverQ) Operator([eqn2], name='WOverQ_Operator_recip')() ``` - [X] Correctness tests - [X] Analytic response in the far field - [X] Modeling operator linearity test, with respect to source - [X] Modeling operator adjoint test, with respect to source - [X] Nonlinear operator linearization test, with respect to model/data - [X] Jacobian operator linearity test, with respect to model/data - [X] Jacobian operator adjoint test, with respect to model/data - [X] Skew symmetry test for shifted derivatives ## To save generated code ``` f = open("operator.c", "w") print(op, file=f) f.close() ```