Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PML boundary condition #210

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

kerim371
Copy link
Contributor

Current implementation of damping boundary condition requires greately extending the computational area.

I hope PML do that better.

To incorporate PML abc we should probably have a list of damp func.
As a first step I'm trying to leave current implementation of damp_op function but make Model.damp member as list.
With that I currently get error:
ValueError('Default damp(x, y)is incompatible with other args asx_size=65, while x_size=200is expected. Perhaps you forgot to overridedamp(x, y)?')

The example of PML in Devito

Appreciate any help

To incorporate PML abc we should probably have a list of `damp` func.
For now I get error:
`ValueError('Default `damp(x, y)` is incompatible with other args as `x_size=65`, while `x_size=200` is expected. Perhaps you forgot to override `damp(x, y)`?')`
@kerim371
Copy link
Contributor Author

kerim371 commented Oct 18, 2023

I'm still struggling with this error.
What is the possible reason of such error? I simply wrapped Model.damp member to a list of a single function.
The full error output:

ERROR: PyError ($(Expr(:escape, :(ccall(#= /home/kerim/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'ValueError'>
ValueError('Default `damp(x, y)` is incompatible with other args as `x_size=65`, while `x_size=200` is expected. Perhaps you forgot to override `damp(x, y)`?')
  File "/home/kerim/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/pysource/interface.py", line 46, in forward_rec
    rec, _, I, _ = forward(model, src_coords, rec_coords, wavelet, save=False,
  File "/home/kerim/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/pysource/propagators.py", line 80, in forward
    summary = op(**kw)
  File "/home/kerim/Documents/Colada/r/python-install/lib/python3.9/site-packages/devito/operator/operator.py", line 738, in __call__
    return self.apply(**kwargs)
  File "/home/kerim/Documents/Colada/r/python-install/lib/python3.9/site-packages/devito/operator/operator.py", line 804, in apply
    args = self.arguments(**kwargs)
  File "/home/kerim/Documents/Colada/r/python-install/lib/python3.9/site-packages/devito/operator/operator.py", line 645, in arguments
    args = self._prepare_arguments(**kwargs)
  File "/home/kerim/Documents/Colada/r/python-install/lib/python3.9/site-packages/devito/operator/operator.py", line 549, in _prepare_arguments
    raise ValueError("Default `%s` is incompatible with other args as "

Stacktrace:
  [1] pyerr_check
    @ ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/exception.jl:75 [inlined]
  [2] pyerr_check
    @ ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/exception.jl:79 [inlined]
  [3] _handle_error(msg::String)
    @ PyCall ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/exception.jl:96
  [4] macro expansion
    @ ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/exception.jl:110 [inlined]
  [5] #107
    @ ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/pyfncall.jl:43 [inlined]
  [6] disable_sigint
    @ ./c.jl:458 [inlined]
  [7] __pycall!
    @ ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/pyfncall.jl:42 [inlined]
  [8] _pycall!(ret::PyCall.PyObject, o::PyCall.PyObject, args::Tuple{PyCall.PyObject, Matrix{Float32}, Matrix{Float32}, Matrix{Float32}}, nargs::Int64, kw::PyCall.PyObject)
    @ PyCall ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/pyfncall.jl:29
  [9] _pycall!(ret::PyCall.PyObject, o::PyCall.PyObject, args::Tuple{PyCall.PyObject, Matrix{Float32}, Matrix{Float32}, Matrix{Float32}}, kwargs::Base.Iterators.Pairs{Symbol, Real, NTuple{4, Symbol}, NamedTuple{(:fw, :space_order, :f0, :illum), Tuple{Bool, Int64, Float32, Bool}}})
    @ PyCall ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/pyfncall.jl:11
 [10] #pycall#112
    @ ~/Documents/Colada/r/julia-1.6/.julia/packages/PyCall/ilqDX/src/pyfncall.jl:80 [inlined]
 [11] #4
    @ ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/JUDI.jl:82 [inlined]
 [12] (::JUDI.var"#1#2"{JUDI.var"#4#5"{Tuple{PyCall.PyArray, PyCall.PyObject}, Base.Iterators.Pairs{Symbol, Real, NTuple{4, Symbol}, NamedTuple{(:fw, :space_order, :f0, :illum), Tuple{Bool, Int64, Float32, Bool}}}, PyCall.PyObject, Tuple{PyCall.PyObject, Matrix{Float32}, Matrix{Float32}, Matrix{Float32}}}})()
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/JUDI.jl:74
 [13] lock(f::JUDI.var"#1#2"{JUDI.var"#4#5"{Tuple{PyCall.PyArray, PyCall.PyObject}, Base.Iterators.Pairs{Symbol, Real, NTuple{4, Symbol}, NamedTuple{(:fw, :space_order, :f0, :illum), Tuple{Bool, Int64, Float32, Bool}}}, PyCall.PyObject, Tuple{PyCall.PyObject, Matrix{Float32}, Matrix{Float32}, Matrix{Float32}}}}, l::ReentrantLock)
    @ Base ./lock.jl:187
 [14] pylock(f::JUDI.var"#4#5"{Tuple{PyCall.PyArray, PyCall.PyObject}, Base.Iterators.Pairs{Symbol, Real, NTuple{4, Symbol}, NamedTuple{(:fw, :space_order, :f0, :illum), Tuple{Bool, Int64, Float32, Bool}}}, PyCall.PyObject, Tuple{PyCall.PyObject, Matrix{Float32}, Matrix{Float32}, Matrix{Float32}}})
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/JUDI.jl:71
 [15] rlock_pycall(::PyCall.PyObject, ::Type{Tuple{PyCall.PyArray, PyCall.PyObject}}, ::PyCall.PyObject, ::Vararg{Any, N} where N; kw::Base.Iterators.Pairs{Symbol, Real, NTuple{4, Symbol}, NamedTuple{(:fw, :space_order, :f0, :illum), Tuple{Bool, Int64, Float32, Bool}}})
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/JUDI.jl:81
 [16] wrapcall_data(::PyCall.PyObject, ::PyCall.PyObject, ::Vararg{Any, N} where N; kw::Base.Iterators.Pairs{Symbol, Real, NTuple{4, Symbol}, NamedTuple{(:fw, :space_order, :f0, :illum), Tuple{Bool, Int64, Float32, Bool}}})
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/python_interface.jl:19
 [17] devito_interface(modelPy::PyCall.PyObject, srcGeometry::GeometryIC{Float32}, srcData::Matrix{Float32}, recGeometry::GeometryIC{Float32}, recData::Nothing, dm::Nothing, options::JUDIOptions, illum::Bool, fw::Bool)
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/python_interface.jl:65
 [18] macro expansion
    @ ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/time_modeling_serial.jl:46 [inlined]
 [19] macro expansion
    @ ./timing.jl:287 [inlined]
 [20] macro expansion
    @ ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/JUDI.jl:141 [inlined]
 [21] time_modeling(model_full::JUDI.IsoModel{Float32, 2}, srcGeometry::GeometryIC{Float32}, srcData::Matrix{Float32}, recGeometry::GeometryIC{Float32}, recData::Nothing, dm::Nothing, op::Symbol, options::JUDIOptions, fw::Bool)
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/time_modeling_serial.jl:45
 [22] propagate(F::judiDataSourceModeling{Float32, :forward}, q::judiVector{Float32, Matrix{Float32}})
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/propagation.jl:9
 [23] macro expansion
    @ ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/propagation.jl:36 [inlined]
 [24] macro expansion
    @ ./timing.jl:287 [inlined]
 [25] macro expansion
    @ ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/JUDI.jl:141 [inlined]
 [26] run_and_reduce(func::Function, #unused#::Nothing, nsrc::Int64, arg_func::JUDI.var"#267#268"{judiDataSourceModeling{Float32, :forward}, judiVector{Float32, Matrix{Float32}}})
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/propagation.jl:35
 [27] multi_src_propagate(F::judiDataSourceModeling{Float32, :forward}, q::judiVector{Float32, Matrix{Float32}})
    @ JUDI ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/Modeling/propagation.jl:85
 [28] *
    @ ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/src/TimeModeling/LinearOperators/operators.jl:173 [inlined]
 [29] afoldl
    @ ./operators.jl:533 [inlined]
 [30] *(a::judiProjection{Float32}, b::judiModeling{Float32, :forward, JUDI.IsoModel{Float32, 2}}, c::JUDI.jAdjoint{judiProjection{Float32}}, xs::judiVector{Float32, Matrix{Float32}})
    @ Base ./operators.jl:560
 [31] top-level scope
    @ ~/Documents/Colada/r/julia-1.6/.julia/dev/JUDI/examples/scripts/modeling_basic_2D.jl:118

@mloubout
Copy link
Member

You need to make sure that

def physical_params(self, **kwargs):

Contains your pml field or it will use the ones from EmptyModel which is a tiny model only used to create the operator

`abc_type` may be either `damp` or `pml`.
This option defines the boundary condition.

`pml` kernel equations not yet implemented.
It only prepares now `pmlx0,pmlx1,pmly0...` `Model` member vars.

Thogh the function `pml_op` should be checked carefully if it is implemented correctly
@kerim371
Copy link
Contributor Author

@mloubout I ve added JUDIOptions.abc_type field with possible values damp and pml.
Then Model have attributes like pmlx0,pmlx1,pmly0 etc if the JUDIOptions.abc_type == pml.

I'm not sure whether I correctly implemented Model.pml_op() method.

I have some troubles with implementing kernel equations with pml.
If you could guide me I would like to work further on this PR.

Copy link
Member

@mloubout mloubout left a comment

Choose a reason for hiding this comment

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

I think the abc_type should go in Model, like NHL, rather than the options

Both `nb` and `abc_type` are defined in `DiscreteGrid` structure
@kerim371
Copy link
Contributor Author

I think the abc_type should go in Model, like NHL, rather than the options

Done, abc_type now is a member of DiscreteGrid struct as well as nb.

@mloubout
Copy link
Member

mloubout commented Nov 2, 2023

I have some troubles with implementing kernel equations with pml.

What's the main blocker?

@kerim371
Copy link
Contributor Author

kerim371 commented Nov 2, 2023

@mloubout basically I think it is better if I push my efforts with mistakes and then we discuss it. I will do that soon (I need few days).

But ultimately I can't understand the following: for acoustic media PML abc are defined using these three equations:
image
Does that mean that in kernels.py I have to define three stencils (like stencil = solve(wmr * u.dt2 + damp * udt - ulaplace - q, u_n)) and pack them in list of size 3 pde = [Eq(u_n, stencil, subdomain=model.grid.subdomains['nofsdomain'])]?

And further I don't know yet what are PML equations for scalar/Q-factor/VTI/TTI models.

@mloubout
Copy link
Member

mloubout commented Nov 2, 2023

yes it would return a list of three equations instead of one

For `pml` abc it needs to add few more equations with `phi` var
@kerim371
Copy link
Contributor Author

@mloubout hi,

From the Devito PML example I have to implement phi1/phi2 functions:
image

In Devito example they are defined as follows:

phi1 = TimeFunction(name="phi1",grid=grid,time_order=2,space_order=2,staggered=(x,z),dtype=np.float64)
phi2 = TimeFunction(name="phi2",grid=grid,time_order=2,space_order=2,staggered=(x,z),dtype=np.float64)

but as I see we don't set any values to them even if in the Devito examples it is written about these vars: "auxiliary variables, which will be non zero only in the absorption region"

Am I missing something or I can simply define them as TimeFunction(...) and then takes their derivatives etc?

@mloubout
Copy link
Member

but as I see we don't set any values

Yes this is expected, these are just extra state variables for the PML region, similar to the wavefield 'uso there is no value set it's an extra PDE which at each time step updates the values of Phi based onu` and the pml equation.

@kerim371
Copy link
Contributor Author

@mloubout some new obstacles appeared...

I define phi as Model attributes:

self.phi1 = TimeFunction(name="phi1",grid=self.grid,time_order=2,space_order=2,staggered=self.grid.dimensions)
self.phi2 = TimeFunction(name="phi2",grid=self.grid,time_order=2,space_order=2,staggered=self.grid.dimensions)

I have a feeling that I have to add them to Operator so they were compiled. If so what should be the right hand side?

After that I will have to compute something like phi1[t,x,z-1]: while I can get x,z from Grid.Dimensions, how can I retrieve time dimension t?

@mloubout
Copy link
Member

have a feeling that I have to add them to [Operator]so they were compiled.

Not sure what you mean, these are just objects, the operator just generates the code for the equations you define with it
You should have a look at:

https://nbviewer.org/github/devitocodes/devito/tree/master/examples/seismic/abc_methods/

For some example of oimplementation

@zhangxiaoshuotttt
Copy link

I tried this today. It works well for implementing damping boundary conditions. Thank you all.

@kerim371
Copy link
Contributor Author

kerim371 commented Mar 8, 2024

@zhangxiaoshuotttt hi,

What I did here is:

  1. added abc_type argument to Model structure (possible values: damp and pml)
  2. tried to add pml grid to src/pysource/models.py (I'm sure whether I did that correctly)

And yet to implement in src/pysource/kernels.py stencil for each type of modeling (acoustic, elastic etc) based on equations from Devito example.

That was pretty difficult for me so I stopped this PR for the now.

@mloubout mloubout force-pushed the master branch 10 times, most recently from 3d45d45 to 0148d00 Compare November 1, 2024 18:47
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.

3 participants