From 1ec67374ecea6be9426ed1fd8e01cf3a8c687267 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Fri, 12 May 2023 10:36:07 +0200 Subject: [PATCH 001/111] starting the elastic business... --- ...perties.jl => acou_material_properties.jl} | 0 .../backends/Elastic2D_Iso_CPML_Serial.jl | 374 ++++++++++++++++++ src/models/elastic/ela_abstract_types.jl | 4 + src/models/elastic/ela_init_bc.jl | 31 ++ src/models/elastic/ela_material_properties.jl | 5 + 5 files changed, 414 insertions(+) rename src/models/acoustic/{material_properties.jl => acou_material_properties.jl} (100%) create mode 100644 src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl create mode 100644 src/models/elastic/ela_abstract_types.jl create mode 100644 src/models/elastic/ela_init_bc.jl create mode 100644 src/models/elastic/ela_material_properties.jl diff --git a/src/models/acoustic/material_properties.jl b/src/models/acoustic/acou_material_properties.jl similarity index 100% rename from src/models/acoustic/material_properties.jl rename to src/models/acoustic/acou_material_properties.jl diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl new file mode 100644 index 0000000..642120a --- /dev/null +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -0,0 +1,374 @@ + +module Elastic2D_Iso_CPML_Serial + +# Dummy data module +module Data +Array = Base.Array +end + +# the backend needs these +ones = Base.ones +zeros = Base.zeros + + + +# Staggered grid with equal spacing in x and z. +# Second order in time, fourth order in space. +# Convolutionary Perfectly Matched Layer (C-PML) boundary conditions +# +# References: +# Levander A. (1988), Fourth-order finite-difference P-SV seismograms, Geophysics. +# Komatitsch D. and Martin R. (2007), An unsplit convolutional +# perfectly matched layer improved at grazing incidence for the +# seismic wave equation, Geophysics. +# Robertsson, J.O. (1996) Numerical Free-Surface Condition for +# Elastic/Viscoelastic Finite-Difference Modeling in the Presence +# of Topography, Geophysics. +# +# +# STAGGERED GRID +# x +# +----------------------------------------------------> +# | +# | +# | (i) (i+1/2) (i+1) (i+3/2) +# | | | | | +# | | | | | +# z | (j) ---vx,rho-----Txx----vx,rho ----- +# | lam,mu Tzz lam,mu | +# | | | | | +# | | | | | +# | (j+1/2) -----Txz------vz-------Txz------- +# | | | | | +# | | | | | +# | | | | | +# | (j+1) ----vx,rho-----Txx-----vx,rho----- +# | lam,mu Tzz lam,mu +# v +# +# Where +# +# Txx Stress_xx (Normal stress x) +# Tzz: Stress_zz (Normal stress z) +# Txz: Stress_xz (Shear stress) +# vx: Velocity_x (x component of velocity) +# vz: Velocity_z (z component of velocity) +# +# +# Node indexing: +# ------------------------------------------------ +# | Code | Staggered grid | +# ------------------------------------------------ +# | rho(i,j) | rho(i,j) | +# | lam(i,j),mu(i,j) | lam(i,j),mu(i,j) | +# | Txx(i,j),Tzz(i,j) | Txx(i+1/2,j),Tzz(i+1/2,j)| +# | Txz(i,j) | Txz(i,j+1/2) | +# | vx(i,j) | vx(i,j) | +# | vz(i,j) | vz(i+1/2,j+1/2) | +# ------------------------------------------------ + + +############################## +# Derivative operators +############################## +# +# o => point where to take the derivative +# +# forward operator: 1/24 * (f[i-1]-27*f[i]+27*f[i+1]-f[i+2]) +# +# i-1 i i+1 i+2 +# | | o | | +# +# backward operator: 1/24 * (f[i-2]-27*f[i-1]+27*f[i]-f[i+1]) +# +# i-2 i-1 i i+1 +# | | o | | +# +# Weigths for taking derivarives for incresing indices +# Dweights = 1.0/inpar.dh * [1/24.0, -27.0/24.0, 27.0/24.0, -1/24.0] + + + +function precomp_prop(ρ,μ,λ,dh) + + fact::Float64 = 1.0/(24.0*dh) + + #------------------------------------------------------------- + # pre-interpolate properties at half distances between nodes + #------------------------------------------------------------- + # ρ_ihalf_jhalf (nx-1,ny-1) ?? + ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 + # μ_ihalf (nx-1,ny) ?? + # μ_ihalf (nx,ny-1) ?? + if harmonicaver_μ==true + # harmonic mean + μ_ihalf = 1.0./( 1.0./μ[2:end,:] + 1.0./μ[1:end-1,:] ) + μ_jhalf = 1.0./( 1.0./μ[:,2:end] + 1.0./μ[:,1:end-1] ) + else + μ_ihalf = (μ[2:end,:]+μ[1:end-1,:])/2.0 ###????? + μ_jhalf = (μ[:,2:end]+μ[:,1:end-1])/2.0 ###????? + end + # λ_ihalf (nx-1,ny) ?? + λ_ihalf = (λ[2:end,:]+λ[1:end-1,:])/2.0 ###????? + + return μ_ihalf,μ_jhalf,λ_ihalf,fact +end + + +function update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, + freetop) + + if freeop + for j = 1:2 + for i = 3:nx-1 + + # Vx + # σxx derivative only in x so no problem + ∂σxx∂x_bkw = fact * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) + # image, mirroring σxz[i,j-2] = -σxz[i,j+1], etc. + ∂σxz∂z_bkw = fact * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) + # update velocity + vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) + + end + end + end + + # vx + for j = 3:nz-1 + for i = 3:nx-1 + + # Vx + ∂σxx∂x_bkw = fact * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) + ∂σxz∂z_bkw = fact * ( σxz[i,j-2] -27.0*σxz[i,j-1] +27.0*σxz[i,j] -σxz[i,j+1] ) + + # C-PML stuff + ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw + ψ_∂σxz∂z[i,j] = b_z[j] * ψ_∂σxz∂z[i,j] + a_z[j] * ∂σxz∂z_bkw + + ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] + ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] + + # update velocity + vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) + + end + end + + return +end + + + +function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,b_x_half,b_z_half,a_x_half,a_z_half, + freetop) + + if freetop + for j = 1:2 + for i = 2:nx-2 + + # Vz + # σxz derivative only in x so no problem + ∂σxz∂x_fwd = fact * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) + # image, mirroring σzz[i,j-1] = -σxz[i,j+2], etc. + ∂σzz∂z_fwd = fact * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + # update velocity (ρ has been interpolated in advance) + vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) + + end + end + end + + # vz + for j = 2:nz-2 + for i = 2:nx-2 + + # Vz + ∂σxz∂x_fwd = fact * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) + ∂σzz∂z_fwd = fact * ( σzz[i,j-1] -27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + + # C-PML stuff + ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd + ψ_∂σzz∂z[i,j] = b_z_half[j] * ψ_∂σzz∂z[i,j] + a_z_half[j]*∂σzz∂z_fwd + + ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] + ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] + + # update velocity (ρ has been interpolated in advance) + vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) + + end + end + + return +end + + +function update_σxxσzz!(σxx,σzz,fact,vx,λ_ihalf,μ_ihalf,dt,b_x_half,b_z,a_x_half,a_z, + freetop) + + if freetop==true + # σxx, σzz + # j=1: we are on the free surface! + j = 1 + for i = 2:nx-2 + # σxx + # vx derivative only in x so no problem + ∂vx∂x_fwd = fact * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd + ∂vz∂z_bkd = -(1.0-2.0*μ_ihalf[i,j]/λ_ihalf[i,j])*∂vx∂x_fwd + # σxx + σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i,j] * dt * ∂vz∂z_bkd + + # σzz + σzz[i,j] = 0.0 # we are on the free surface! + end + + # j=2: we are just below the surface (1/2) + j = 2 + for i = 2:nx-2 + # σxx + # vx derivative only in x so no problem + ∂vx∂x_fwd = fact * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + # zero velocity above the free surface + ∂vz∂z_bkd = fact * ( 0.0 -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) + # σxx + σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i,j] * dt * ∂vz∂z_bkd + + # σzz + σzz[i,j] = σzz[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt* ∂vz∂z_bkd + + λ_ihalf[i,j] * dt * ∂vx∂x_fwd + + end + end + + # σxx, σzz + for j = 3:nz-1 + for i = 2:nx-2 + + # σxx,σzz + ∂vx∂x_fwd = fact * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + ∂vz∂z_bkd = fact * ( vz[i,j-2] -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) + + # C-PML stuff + ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd + ψ_∂vz∂z[i,j] = b_z[j] * ψ_∂vz∂z[i,j] + a_z[j]*∂vz∂z_bkd + + ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] + ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] + + # σxx + σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i,j] * dt * ∂vz∂z_bkd + + ## derivatives are the same than for σxx + # σzz + σzz[i,j] = σzz[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vz∂z_bkd + + λ_ihalf[i,j] * dt * ∂vx∂x_fwd + + end + end + return +end + + +function update_σxz!(σxz,fact,vx,vz,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, + freetop) + + if freetop + # σxz + j = 1 + for i=3:nx-1 + # zero velocity above the free surface + ∂vx∂z_fwd = fact * ( 0.0 -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) + # vz derivative only in x so no problem + ∂vz∂x_bkd = fact * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) + + # σxz + σxz[i,j] = σxz[i,j] + μ_jhalf[i,j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) + + end + end + + # σxz + for j = 2:nz-2 + for i = 3:nx-1 + + # σxz + ∂vx∂z_fwd = fact * ( vx[i,j-1] -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) + ∂vz∂x_bkd = fact * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) + + # C-PML stuff + ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd + ψ_∂vz∂x[i,j] = b_x[i] * ψ_∂vz∂x[i,j] + a_x[i]*∂vz∂x_bkd + + ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] + ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] + + # σxz + σxz[i,j] = σxz[i,j] + μ_jhalf[i,j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) + + end + end + + return +end + + + +function forward_onestep_CPML!(vx,vz,σxx,σzz,σxz, + ρ,ρ_ihalf_jhalf, + μ,μ_ihalf,μ_jhalf, + dt, + b_x,b_z,b_x_half,b_z_half, + a_x,a_z,a_x_half,a_z_half, + freetop,save_trace) + + + # precompute some stuff + μ_ihalf,μ_jhalf,λ_ihalf,fact = precomp_prop(ρ,μ,λ,dh) + + # update velocities vx and vz + update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, + freetop) + + update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,b_x_half,b_z_half, + a_x_half,a_z_half,freetop) + + # update stresses σxx, σzz and σxz + update_σxxσzz!(σxx,σzz,fact,vx,λ_ihalf,μ_ihalf,dt,b_x_half, + b_z,a_x_half,a_z,freetop) + + update_σxz!(σxz,fact,vx,vz,μ_jhalf,dt,b_x,b_z_half, + a_x,a_z_half,freetop) + + + # inject sources + inject_sources!( ??????, dt2srctf, possrcs, it) + # record receivers + if save_trace + record_receivers!( ??????, traces, posrecs, it) + end + + return +end + + +function correlate_gradient!( ) + + # _dt2 = 1 / dt^2 + # nx, ny = size(curgrad) + # for j in 1:ny + # for i in 1:nx + # curgrad[i, j] = curgrad[i, j] + (adjcur[i, j] * (pcur[i, j] - 2.0 * pold[i, j] + pveryold[i, j]) * _dt2) + # end + # end + return +end + + +######################################### +end # end module +######################################### diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl new file mode 100644 index 0000000..0e5d254 --- /dev/null +++ b/src/models/elastic/ela_abstract_types.jl @@ -0,0 +1,4 @@ + +abstract type ElasticWaveSimul{N} <: WaveSimul{N} end + +abstract type ElasticIsoWaveSimul{N} <: ElasticWaveSimul{N} end diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl new file mode 100644 index 0000000..7dfa5f5 --- /dev/null +++ b/src/models/elastic/ela_init_bc.jl @@ -0,0 +1,31 @@ + +init_bdc!(model::ElasticWaveSimul, srcs::Sources) = + init_bdc!(BoundaryConditionTrait(model), model, srcs) + +init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimul, srcs::Sources) = nothing + +@views function init_bdc!( + ::CPMLBoundaryCondition, + model::ElasticIsoWaveSimul, + srcs::Sources +) + N = length(model.cpmlcoeffs) + for n in 1:N + compute_CPML_coefficients!( + model.cpmlcoeffs[n], + get_maximum_func(model)( sqrt.((model.matprop.λ+2.0*model.matprop.μ)./model.matprop.ρ) ), + model.dt, + model.halo, + model.rcoef, + model.gridspacing[n] * model.halo, + srcs.domfreq + ) + end + + if model.freetop && N >= 1 + model.cpmlcoeffs[N].a_l .= 0.0 + model.cpmlcoeffs[N].a_hl .= 0.0 + model.cpmlcoeffs[N].b_l .= 1.0 + model.cpmlcoeffs[N].b_hl .= 1.0 + end +end diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl new file mode 100644 index 0000000..89c9423 --- /dev/null +++ b/src/models/elastic/ela_material_properties.jl @@ -0,0 +1,5 @@ +Base.@kwdef struct ElasticIsoMaterialProperty{N} <: MaterialProperties{N} + λ::Array{<:Float64, N} + μ::Array{<:Float64, N} + ρ::Array{<:Float64, N} +end From 6f9f5b4a0dc63ca6f7801f99af22f448aeb2bf28 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Thu, 25 May 2023 16:33:15 +0200 Subject: [PATCH 002/111] some progress... --- .../backends/Elastic2D_Iso_CPML_Serial.jl | 241 +++++++++--- src/models/elastic/ela_forward.jl | 76 ++++ src/models/elastic/ela_models.jl | 349 ++++++++++++++++++ src/models/elastic/ela_params.jl | 40 ++ src/sources.jl | 41 ++ 5 files changed, 701 insertions(+), 46 deletions(-) create mode 100644 src/models/elastic/ela_forward.jl create mode 100644 src/models/elastic/ela_models.jl create mode 100644 src/models/elastic/ela_params.jl diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 642120a..1418aa9 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -89,7 +89,7 @@ zeros = Base.zeros -function precomp_prop(ρ,μ,λ,dh) +function precomp_prop!(ρ,μ,λ,dh,μ_ihalf,μ_jhalf,λ_ihalf,fact) fact::Float64 = 1.0/(24.0*dh) @@ -97,21 +97,21 @@ function precomp_prop(ρ,μ,λ,dh) # pre-interpolate properties at half distances between nodes #------------------------------------------------------------- # ρ_ihalf_jhalf (nx-1,ny-1) ?? - ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 + @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 # μ_ihalf (nx-1,ny) ?? # μ_ihalf (nx,ny-1) ?? if harmonicaver_μ==true # harmonic mean - μ_ihalf = 1.0./( 1.0./μ[2:end,:] + 1.0./μ[1:end-1,:] ) - μ_jhalf = 1.0./( 1.0./μ[:,2:end] + 1.0./μ[:,1:end-1] ) + @. μ_ihalf = 1.0 / ( 1.0./μ[2:end,:] + 1.0 / μ[1:end-1,:] ) + @. μ_jhalf = 1.0 / ( 1.0./μ[:,2:end] + 1.0 / μ[:,1:end-1] ) else - μ_ihalf = (μ[2:end,:]+μ[1:end-1,:])/2.0 ###????? - μ_jhalf = (μ[:,2:end]+μ[:,1:end-1])/2.0 ###????? + @. μ_ihalf = (μ[2:end,:] + μ[1:end-1,:]) / 2.0 + @. μ_jhalf = (μ[:,2:end] + μ[:,1:end-1]) / 2.0 end # λ_ihalf (nx-1,ny) ?? - λ_ihalf = (λ[2:end,:]+λ[1:end-1,:])/2.0 ###????? + @. λ_ihalf = (λ[2:end,:] + λ[1:end-1,:]) / 2.0 - return μ_ihalf,μ_jhalf,λ_ihalf,fact + return fact end @@ -136,18 +136,46 @@ function update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_ # vx for j = 3:nz-1 - for i = 3:nx-1 + for i = 3:nx-1 # Vx ∂σxx∂x_bkw = fact * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) ∂σxz∂z_bkw = fact * ( σxz[i,j-2] -27.0*σxz[i,j-1] +27.0*σxz[i,j] -σxz[i,j+1] ) - # C-PML stuff - ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw - ψ_∂σxz∂z[i,j] = b_z[j] * ψ_∂σxz∂z[i,j] + a_z[j] * ∂σxz∂z_bkw - - ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] - ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] + ##======================= + # C-PML stuff + ##======================= + # x boundaries + if i <= halo + # left boundary + ψ_∂σxx∂x[i,j] = b_x_l[i] * ψ_∂σxx∂x[i,j] + a_x_l[i] * ∂σxx∂x_bkw + ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] + elseif i >= nx - halo + 1 + # right boundary + ii = i - (nx - halo) + 1 + ψ_∂σxx∂x[ii,j] = b_x_r[ii] * ψ_∂σxx∂x[ii,j] + a_x_r[ii] * ∂σxx∂x_bkw + ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii,j] + end + # y boundaries + if j <= halo && freetop==false + # top boundary + ψ_∂σxz∂z[i,j] = b_z_l[j] * ψ_∂σxz∂z[i,j] + a_z_l[j] * ∂σxz∂z_bkw + ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] + elseif j >= ny - halo + 1 + # bottom boundary + jj = j - (ny - halo) + 1 + ψ_∂σxz∂z[i,jj] = b_z_r[jj] * ψ_∂σxz∂z[i,jj] + a_z_r[jj] * ∂σxz∂z_bkw + ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,jj] + end + ##======================= + + # # C-PML stuff + # ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw + # ψ_∂σxz∂z[i,j] = b_z[j] * ψ_∂σxz∂z[i,j] + a_z[j] * ∂σxz∂z_bkw + + # # derivatives + # ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] + # ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] # update velocity vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) @@ -160,7 +188,7 @@ end -function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,b_x_half,b_z_half,a_x_half,a_z_half, +function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half, freetop) if freetop @@ -186,13 +214,41 @@ function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,b_x_half,b_z_half,a_x_ha # Vz ∂σxz∂x_fwd = fact * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) ∂σzz∂z_fwd = fact * ( σzz[i,j-1] -27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + + + ##======================= + # C-PML stuff + ##======================= + # x boundaries + if i <= halo + 1 + # left boundary + ψ_∂σxz∂x[i,j] = b_x_l_half[i] * ψ_∂σxx∂x[i,j] + ψ_∂σxz∂x[i,j] + a_x_l_half[i]*∂σxz∂x_fwd + ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] + elseif i >= nx - halo + # right boundary + ii = i - (nx - halo) + 1 + ψ_∂σxz∂x[ii,j] = b_x_l_half[ii] * ψ_∂σxx∂x[ii,j] + ψ_∂σxz∂x[ii,j] + a_x_l_half[ii]*∂σxz∂x_fwd + ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[ii,j] + end + # y boundaries + if j <= halo +1 && freetop==false # + 1 + # top boundary + ψ_∂σzz∂z[i,j] = b_z_r_half[j] * ψ_∂σzz∂z[i,j] + a_z_r_half[j]*∂σzz∂z_fwd + ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] + elseif j >= ny - halo + # bottom boundary + jj = j - (ny - halo) + 1 + ψ_∂σzz∂z[i,jj] = b_z_r_half[jj] * ψ_∂σzz∂z[i,jj] + a_z_r_half[jj]*∂σzz∂z_fwd + ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,jj] + end + ##======================= + + # # C-PML stuff + # ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd + # ψ_∂σzz∂z[i,j] = b_z_half[j] * ψ_∂σzz∂z[i,j] + a_z_half[j]*∂σzz∂z_fwd - # C-PML stuff - ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd - ψ_∂σzz∂z[i,j] = b_z_half[j] * ψ_∂σzz∂z[i,j] + a_z_half[j]*∂σzz∂z_fwd - - ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] - ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] + # ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] + # ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] # update velocity (ρ has been interpolated in advance) vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) @@ -204,8 +260,8 @@ function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,b_x_half,b_z_half,a_x_ha end -function update_σxxσzz!(σxx,σzz,fact,vx,λ_ihalf,μ_ihalf,dt,b_x_half,b_z,a_x_half,a_z, - freetop) +function update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, + b_x_half,b_z,a_x_half,a_z,freetop) if freetop==true # σxx, σzz @@ -251,13 +307,41 @@ function update_σxxσzz!(σxx,σzz,fact,vx,λ_ihalf,μ_ihalf,dt,b_x_half,b_z,a_ # σxx,σzz ∂vx∂x_fwd = fact * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) ∂vz∂z_bkd = fact * ( vz[i,j-2] -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) + + ##======================= + # C-PML stuff + ##======================= + # x boundaries + if i <= halo + 1 + # left boundary + ψ_∂vx∂x[i,j] = b_x_l_half[i] * ψ_∂vx∂x[i,j] + a_x_l_half[i]*∂vx∂x_fwd + ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] + elseif i >= nx - halo + # right boundary + ii = i - (nx - halo) + 1 + ψ_∂vx∂x[ii,j] = b_x_l_half[ii] * ψ_∂vx∂x[ii,j] + a_x_l_half[ii]*∂vx∂x_fwd + ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[ii,j] + end + # y boundaries + if j <= halo && freetop==false + # top boundary + ψ_∂vz∂z[i,j] = b_z_r[j] * ψ_∂vz∂z[i,j] + a_z_r[j]*∂vz∂z_bkd + ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] + + elseif j >= ny - halo + 1 + # bottom boundary + jj = j - (ny - halo) + 1 + ψ_∂vz∂z[i,jj] = b_z_r[jj] * ψ_∂vz∂z[i,jj] + a_z_r[jj]*∂vz∂z_bkd + ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,jj] + end + ##======================= - # C-PML stuff - ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd - ψ_∂vz∂z[i,j] = b_z[j] * ψ_∂vz∂z[i,j] + a_z[j]*∂vz∂z_bkd + # # C-PML stuff + # ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd + # ψ_∂vz∂z[i,j] = b_z[j] * ψ_∂vz∂z[i,j] + a_z[j]*∂vz∂z_bkd - ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] - ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] + # ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] + # ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] # σxx σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + @@ -274,7 +358,7 @@ function update_σxxσzz!(σxx,σzz,fact,vx,λ_ihalf,μ_ihalf,dt,b_x_half,b_z,a_ end -function update_σxz!(σxz,fact,vx,vz,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, +function update_σxz!(σxz,fact,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, freetop) if freetop @@ -299,13 +383,40 @@ function update_σxz!(σxz,fact,vx,vz,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, # σxz ∂vx∂z_fwd = fact * ( vx[i,j-1] -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) ∂vz∂x_bkd = fact * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) - - # C-PML stuff - ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd - ψ_∂vz∂x[i,j] = b_x[i] * ψ_∂vz∂x[i,j] + a_x[i]*∂vz∂x_bkd - - ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] - ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] + + ##======================= + # C-PML stuff + ##======================= + # x boundaries + if i <= halo + # left boundary + ψ_∂vz∂x[i,j] = b_x_l[i] * ψ_∂vz∂x[i,j] + a_x_l[i]*∂vz∂x_bkd + ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] + elseif i >= nx - halo + 1 + # right boundary + ii = i - (nx - halo) + 1 + ψ_∂vz∂x[ii,j] = b_x_r[ii] * ψ_∂vz∂x[ii,j] + a_x_r[ii]*∂vz∂x_bkd + ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[ii,j] + end + # y boundaries + if j <= halo +1 && freetop==false + # top boundary + ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd + ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] + elseif j >= ny - halo + # bottom boundary + jj = j - (ny - halo) + 1 + ψ_∂vx∂z[i,jj] = b_z_half[jj] * ψ_∂vx∂z[i,jj] + a_z_half[jj]*∂vx∂z_fwd + ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,jj] + end + ##======================= + + # # C-PML stuff + # ψ_∂vz∂x[i,j] = b_x[i] * ψ_∂vz∂x[i,j] + a_x[i]*∂vz∂x_bkd + # ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd + + # ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] + # ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] # σxz σxz[i,j] = σxz[i,j] + μ_jhalf[i,j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) @@ -322,26 +433,32 @@ function forward_onestep_CPML!(vx,vz,σxx,σzz,σxz, ρ,ρ_ihalf_jhalf, μ,μ_ihalf,μ_jhalf, dt, - b_x,b_z,b_x_half,b_z_half, - a_x,a_z,a_x_half,a_z_half, + ψ_∂σxx∂x,ψ_∂σxz∂z, + ψ_∂σxz∂x,ψ_∂σzz∂z, + ψ_∂vx∂x,ψ_∂vz∂z, + ψ_∂vx∂z,ψ_∂vz∂x, + a_x_l, a_x_r, b_x_l, b_x_r, + a_z_l, a_z_r, b_z_l, b_z_r, + a_x_l_half, a_x_r_half, b_x_l_half, b_x_r_half, + a_z_l_half, a_z_r_half, b_z_l_half, b_z_r_half, freetop,save_trace) # precompute some stuff - μ_ihalf,μ_jhalf,λ_ihalf,fact = precomp_prop(ρ,μ,λ,dh) + fact = precomp_prop!(ρ,μ,λ,dh,μ_ihalf,μ_jhalf,λ_ihalf) # update velocities vx and vz - update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, - freetop) + update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z, + b_x,b_z,a_x,a_z,freetop) - update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,b_x_half,b_z_half, - a_x_half,a_z_half,freetop) + update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, + b_x_half,b_z_half,a_x_half,a_z_half,freetop) # update stresses σxx, σzz and σxz - update_σxxσzz!(σxx,σzz,fact,vx,λ_ihalf,μ_ihalf,dt,b_x_half, + update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half,ψ_∂vx∂x,ψ_∂vz∂z, b_z,a_x_half,a_z,freetop) - update_σxz!(σxz,fact,vx,vz,μ_jhalf,dt,b_x,b_z_half, + update_σxz!(σxz,fact,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,ψ_∂vx∂z,ψ_∂vz∂x, a_x,a_z_half,freetop) @@ -356,6 +473,38 @@ function forward_onestep_CPML!(vx,vz,σxx,σzz,σxz, end +function inject_sources!( ) + + ## Inject the source as stress from moment tensor + ## See Igel 2017 Computational Seismology (book) page 31, 2.6.1 + if it<=lensrctf + + for ir in axes(possrcs, 1) + irec = floor(Int, possrcs[ir, 1]) + jrec = floor(Int, possrcs[ir, 2]) + + σxx[isrc,jsrc] = σxx[isrc,jsrc] + momtens.σxx * sourcetf[t]* dt + σzz[isrc,jsrc] = σzz[isrc,jsrc] + momtens.σzz * sourcetf[t]* dt + σxz[isrc,jsrc] = σxz[isrc,jsrc] + momtens.σxz * sourcetf[t]* dt + end + + end + + return +end + + +function record_receivers!(vx,vz,traces, posrecs, it) + for ir in axes(posrecs, 1) + irec = floor(Int, posrecs[ir, 1]) + jrec = floor(Int, posrecs[ir, 2]) + # interpolate velocities on the same grid? + # ????? traces_vx[it, ir ???] = vx[irec, jrec] + end + return +end + + function correlate_gradient!( ) # _dt2 = 1 / dt^2 diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl new file mode 100644 index 0000000..462d448 --- /dev/null +++ b/src/models/elastic/ela_forward.jl @@ -0,0 +1,76 @@ +swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) + +@views function swforward_1shot!( + ::CPMLBoundaryCondition, + model::ElasticIsoWaveSimul{N}, + possrcs, + posrecs, + srctf, + traces +) where {N} + # Velocity arrays + vx = model.vx + vz = model.vz + # Stress arrays + σxx = model.σxx + σzz = model.σzz + σxz = model.σxz + # C-PML memory arrays + + # Numerics + nt = model.nt + # Wrap sources and receivers arrays + possrcs_a = model.backend.Data.Array(possrcs) + posrecs_a = model.backend.Data.Array(posrecs) + srctf_a = model.backend.Data.Array(srctf) + traces_a = model.backend.Data.Array(traces) + # Reset wavesim + reset!(model) + + # Time loop + for it in 1:nt + # Compute one forward step + model.backend.forward_onestep_CPML!(model.vx, model.vz, + model.σxx, model.σzz, model.σxz, + model.ρ, model.ρ_ihalf_jhalf, + model.μ, model.μ_ihalf, model.μ_jhalf, + model.dt, + model.ψ_∂σxx∂x, model.ψ_∂σxz∂z, + model.ψ_∂σxz∂x, model.ψ_∂σzz∂z, + model.ψ_∂vx∂x, model.ψ_∂vz∂z, + model.ψ_∂vx∂z, model.ψ_∂vz∂x, + model.a_coeffs..., model.b_coeffs..., + possrcs_a, srctf_a, posrecs_a, traces_a, it, + freetop,save_trace) + + # pold, pcur, pnew = model.backend.forward_onestep_CPML!( + # pold, pcur, pnew, model.fact, + # model.gridspacing..., model.halo, + # model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., + # possrcs_a, srctf_a, posrecs_a, traces_a, it + # ) + + + + + + # Print timestep info + if it % model.infoevery == 0 + @debug @sprintf( + "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", + it, + model.dt * (it - 1), + maximum(abs.(Array(pcur))) + ) + end + + # Save snapshot + if snapenabled(model) && it % model.snapevery == 0 + @debug @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) + model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)] .= Array(pcur) + end + end + + # Save traces + traces .= Array(traces_a) +end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl new file mode 100644 index 0000000..b14eddf --- /dev/null +++ b/src/models/elastic/ela_models.jl @@ -0,0 +1,349 @@ +########################################################### + +# Functions for all ElasticIsoWaveSimul subtypes + +@views function check_matprop(model::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} + # Checks + vp = sqrt((matprop.λ .+ 2.*matprop.μ) ./ matprop.ρ) + @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" + @assert size(vp) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.ns)" + @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" + @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" + @assert all(matprop.ρ .> 0) "Density must be positive!" + + # Check courant condition + vp_max = get_maximum_func(model)(vp) + tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) + courant = vel_max * model.dt * tmp + @debug "Courant number: $(courant)" + if courant > 1.0 + @warn "Courant condition not satisfied! [$(courant)]" + end + + return +end + +function check_numerics( + model::ElasticIsoWaveSimul, + shot::Shot; + min_ppw::Integer=10 +) + # Check points per wavelengh + vel_min = get_minimum_func(model)(sqrt(model.matprop.μ ./ model.matprop.ρ)) # min Vs + h_max = maximum(model.gridspacing) + ppw = vel_min / shot.srcs.domfreq / h_max + @debug "Points per wavelength: $(ppw)" + @assert ppw >= min_ppw "Not enough points per wavelengh!" +end + +@views function update_matprop!(model::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} + # Update material properties + model.matprop.λ .= matprop.λ + model.matprop.μ .= matprop.μ + model.matprop.ρ .= matprop.ρ + return +end + + +# @views function scale_srctf(model::ElasticIsoWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} +# # scale with boxcar and timestep size +# scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt^2) +# # scale with velocity squared at each source position +# for s in axes(scaled_tf, 2) +# scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] .^ 2 +# end +# return scaled_tf +# end + +########################################################### + +struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} + # Physics + ls::NTuple{N, <:Real} + # Numerics + ns::NTuple{N, <:Integer} + gridspacing::NTuple{N, <:Real} + nt::Integer + dt::Real + # BDC and CPML parameters + halo::Integer + rcoef::Real + freetop::Bool + # Gradient computation setup + gradient::Bool + check_freq::Union{<:Integer, Nothing} + # Snapshots + snapevery::Union{<:Integer, Nothing} + snapshots::Union{<:Array{<:Real}, Nothing} + # Logging parameters + infoevery::Integer + # Material properties + matprop::VpElasticIsoMaterialProperty + # CPML coefficients + cpmlcoeffs::NTuple{N, CPMLCoefficients} + # Forward computation arrays + vx::Any + vz::Any + σxx::Any + σzz::Any + σxz::Any + λ::Any + μ::Any + ρ::Any + ρ_ihalf_jhalf::Any + μ_ihalf::Any + μ_jhalf::Any + λ_ihalf::Any + ψ_∂σxx∂x::Any + ψ_∂σxz∂z::Any + ψ_∂σxz∂x::Any + ψ_∂σzz∂z::Any + ψ_∂vx∂x::Any + ψ_∂vz∂z::Any + ψ_∂vz∂x::Any + ψ_∂vx∂z::Any + a_coeffs::Any + b_coeffs::Any + # Gradient computation arrays + grad::Any + adj::Any + ψ_∂σxx∂x_adj::Any + ψ_∂σxz∂z_adj::Any + ψ_∂σxz∂x_adj::Any + ψ_∂σzz∂z_adj::Any + ψ_∂vx∂x_adj::Any + ψ_∂vz∂z_adj::Any + ψ_∂vz∂x_adj::Any + ψ_∂vx∂z_adj::Any + # Checkpointing setup + last_checkpoint::Union{<:Integer, Nothing} + save_buffer::Any + checkpoints::Any + checkpoints_ψ_∂σxx∂x::Any + checkpoints_ψ_∂σxz∂z::Any + checkpoints_ψ_∂σxz∂x::Any + checkpoints_ψ_∂σzz∂z::Any + checkpoints_ψ_∂vx∂x::Any + checkpoints_ψ_∂vz∂z::Any + checkpoints_ψ_∂vz∂x::Any + checkpoints_ψ_∂vx∂z::Any + a_coeffs::Any + b_coeffs::Any + + + # Backend + backend::Module + + function ElasticIsoCPMLWaveSimul{N}( + ns::NTuple{N, <:Integer}, + gridspacing::NTuple{N, <:Real}, + nt::Integer, + dt::Real, + halo::Integer, + rcoef::Real; + parall::Symbol=:threads, + freetop::Bool=true, + gradient::Bool=false, + check_freq::Union{<:Integer, Nothing}=nothing, + snapevery::Union{<:Integer, Nothing}=nothing, + infoevery::Union{<:Integer, Nothing}=nothing + ) where {N} + # Check numerics + @assert all(ns .> 0) "All numbers of grid points must be positive!" + @assert all(gridspacing .> 0) "All cell sizes must be positive!" + @assert nt > 0 "Number of timesteps must be positive!" + @assert dt > 0 "Timestep size must be positive!" + + # Check BDC parameters + @assert halo >= 0 "CPML halo size must be non-negative!" + ns_cpml = freetop ? ns[1:(end-1)] : ns + @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" + + # Compute model sizes + ls = gridspacing .* (ns .- 1) + # Initialize material properties + matprop = VpElasticIsoMaterialProperty(zeros(ns...)) + + # Select backend + backend = select_backend(ElasticIsoCPMLWaveSimul{N}, parall) + + # Initialize computational arrays + fact = backend.zeros(ns...) + pold = backend.zeros(ns...) + pcur = backend.zeros(ns...) + pnew = backend.zeros(ns...) + # Initialize CPML arrays + ψ = [] + ξ = [] + for i in 1:N + ψ_ns = [ns...] + ξ_ns = [ns...] + ψ_ns[i] = halo + 1 + ξ_ns[i] = halo + append!(ψ, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) + append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + end + # Initialize CPML coefficients + cpmlcoeffs = tuple([CPMLCoefficients(halo, backend) for _ in 1:N]...) + # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) + a_coeffs = [] + b_coeffs = [] + for i in 1:N + append!(a_coeffs, [cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr]) + append!(b_coeffs, [cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr]) + end + # Initialize gradient arrays if needed + if gradient + # Current gradient array + curgrad = backend.zeros(ns...) + # Adjoint arrays + adjold = backend.zeros(ns...) + adjcur = backend.zeros(ns...) + adjnew = backend.zeros(ns...) + # Initialize CPML arrays + ψ_adj = [] + ξ_adj = [] + for i in 1:N + ψ_ns = [ns...] + ξ_ns = [ns...] + ψ_ns[i] = halo + 1 + ξ_ns[i] = halo + append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) + append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + end + # Checkpointing setup + if check_freq !== nothing + @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" + @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" + # Time step of last checkpoint + last_checkpoint = floor(Int, nt / check_freq) * check_freq + # Checkpointing arrays + save_buffer = backend.zeros(ns..., check_freq + 2) # pressure window buffer + checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints + checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints + checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints + # Save initial conditions as first checkpoint + checkpoints[-1] = copy(pold) + checkpoints[0] = copy(pcur) + checkpoints_ψ[0] = copy.(ψ) + checkpoints_ξ[0] = copy.(ξ) + # Preallocate future checkpoints + for it in 1:(nt+1) + if it % check_freq == 0 + checkpoints[it] = backend.zeros(ns...) + checkpoints[it-1] = backend.zeros(ns...) + checkpoints_ψ[it] = copy.(ψ) + checkpoints_ξ[it] = copy.(ξ) + end + end + else # no checkpointing + last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) + save_buffer = backend.zeros(ns..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) + checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) + checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) + checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) + end + # Save first 2 timesteps in save buffer + save_buffer[fill(Colon(), N)..., 1] .= pold + save_buffer[fill(Colon(), N)..., 2] .= pcur + end + + # Initialize snapshots array + snapshots = (snapevery !== nothing ? zeros(ns..., div(nt, snapevery)) : nothing) + # Check infoevery + if infoevery === nothing + infoevery = nt + 2 # never reach it + else + @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" + end + + return new( + ls, + ns, + gridspacing, + nt, + dt, + halo, + rcoef, + freetop, + gradient, + gradient ? check_freq : nothing, + snapevery, + snapshots, + infoevery, + matprop, + cpmlcoeffs, + fact, + pold, + pcur, + pnew, + ψ, + ξ, + a_coeffs, + b_coeffs, + gradient ? curgrad : nothing, + gradient ? adjold : nothing, + gradient ? adjcur : nothing, + gradient ? adjnew : nothing, + gradient ? ψ_adj : nothing, + gradient ? ξ_adj : nothing, + gradient ? last_checkpoint : nothing, + gradient ? save_buffer : nothing, + gradient ? checkpoints : nothing, + gradient ? checkpoints_ψ : nothing, + gradient ? checkpoints_ξ : nothing, + backend + ) + end +end + +########################################################### + +# Specific functions for ElasticIsoCPMLWaveSimul + +@views function reset!(model::ElasticIsoCPMLWaveSimul{N}) where {N} + # Reset computational arrays + model.pold .= 0.0 + model.pcur .= 0.0 + model.pnew .= 0.0 + for i in eachindex(model.ψ) + model.ψ[i] .= 0.0 + end + for i in eachindex(model.ξ) + model.ξ[i] .= 0.0 + end + # Reset gradient arrays + if model.gradient + model.curgrad .= 0.0 + model.adjold .= 0.0 + model.adjcur .= 0.0 + model.adjnew .= 0.0 + for i in eachindex(model.ψ_adj) + model.ψ_adj[i] .= 0.0 + end + for i in eachindex(model.ξ_adj) + model.ξ_adj[i] .= 0.0 + end + end +end +########################################################### + +# Traits for ElasticIsoCPMLWaveSimul + +IsSnappableTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = Snappable() +BoundaryConditionTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = CPMLBoundaryCondition() +GridTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = LocalGrid() + +########################################################### + +struct ElasticIsoReflWaveSimul{N} <: ElasticIsoWaveSimul{N} end # TODO implementation + +########################################################### + +# Traits for ElasticIsoReflWaveSimul + +IsSnappableTrait(::Type{<:ElasticIsoReflWaveSimul}) = Snappable() +BoundaryConditionTrait(::Type{<:ElasticIsoReflWaveSimul}) = ReflectiveBoundaryCondition() +GridTrait(::Type{<:ElasticIsoReflWaveSimul}) = LocalGrid() + +########################################################### diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl new file mode 100644 index 0000000..490ee9f --- /dev/null +++ b/src/models/elastic/ela_params.jl @@ -0,0 +1,40 @@ +""" +Parameters for acoustic wave simulations +""" +struct InputParametersElastic{N} <: InputParameters{N} + ntimesteps::Int + dt::Real + gridsize::NTuple{N, <:Int} + gridspacing::NTuple{N, <:Real} + boundcond::InputBoundaryConditionParameters +end + +function InputParametersElastic( + ntimesteps::Int, + dt::Real, + gridsize::AbstractVector{<:Int}, + gridspacing::AbstractVector{<:Real}, + boundcond::InputBoundaryConditionParameters +) + # Check dimensionality + N = length(gridsize) + @assert N == length(gridspacing) "Dimensionality mismatch between number of grid points and grid step sizes!" + @assert N > 0 "Dimensionality must positive!" + @assert N <= 3 "Dimensionality must be less than or equal to 3!" + + return InputParametersElastic{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) +end + +""" +Reflective boundary conditions parameters for acoustic wave simulations +""" +Base.@kwdef struct ReflectiveBoundaryConditionParameters <: InputBoundaryConditionParameters end + +""" +CPML boundary conditions parameters for acoustic wave simulations +""" +Base.@kwdef struct CPMLBoundaryConditionParameters <: InputBoundaryConditionParameters + halo::Int = 20 + rcoef::Real = 0.0001 + freeboundtop::Bool = true +end diff --git a/src/sources.jl b/src/sources.jl index fe23386..ff61495 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -25,4 +25,45 @@ end # Default type constructor {Float64} ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, domfreq) +####################################################33 +""" +Type representing a 2D moment tensor. +""" +struct MomentTensor2D{T <: Real} + Mxx::T + Mzz::T + Mxz::T +end + + +""" +Type representing a multi-source configuration for a wave propagation shot. +""" +struct MomentTensor2DSources{T <: Real} <: Sources + positions::Matrix{<:Real} + tf::Matrix{T} + momtens::Vector{MomentTensor2D} + domfreq::T + + @doc """ + MomentTensorSources{T<:Real}( + positions::Matrix{<:Real}, + tf::Matrix{<:T}, + momtens::Vector{MomentTensor2D}, + domfreq::T + ) + + Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. + """ + function MomentTensor2DSources{T}(positions::Matrix{<:Real}, tf::Matrix{T}, momtens::Vector{MomentTensor2D}, domfreq::T) where {T <: Real} + @assert size(positions, 1) > 0 "There must be at least one source!" + @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" + return new(positions, tf, momtens, domfreq) + end +end + +# Default type constructor {Float64} +MomentTensorSources(positions, tf, momtens, domfreq) = MomentTensorSources{Float64}(positions, tf, momtens, domfreq) + +#################################################### From 860caae7d988e3fd22d8d9e7ff0dbf9b9a7a87f1 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Thu, 25 May 2023 16:34:02 +0200 Subject: [PATCH 003/111] modified: ela_models.jl --- src/models/elastic/ela_models.jl | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index b14eddf..051b07f 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -90,18 +90,19 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} λ::Any μ::Any ρ::Any - ρ_ihalf_jhalf::Any - μ_ihalf::Any - μ_jhalf::Any - λ_ihalf::Any - ψ_∂σxx∂x::Any - ψ_∂σxz∂z::Any - ψ_∂σxz∂x::Any - ψ_∂σzz∂z::Any - ψ_∂vx∂x::Any - ψ_∂vz∂z::Any - ψ_∂vz∂x::Any - ψ_∂vx∂z::Any + # ρ_ihalf_jhalf::Any + # μ_ihalf::Any + # μ_jhalf::Any + # λ_ihalf::Any + ψ::Elaψ + # ψ_∂σxx∂x::Any + # ψ_∂σxz∂z::Any + # ψ_∂σxz∂x::Any + # ψ_∂σzz∂z::Any + # ψ_∂vx∂x::Any + # ψ_∂vz∂z::Any + # ψ_∂vz∂x::Any + # ψ_∂vx∂z::Any a_coeffs::Any b_coeffs::Any # Gradient computation arrays From f4077b8e2406b371b7921333e3dbf719c4ffd875 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Wed, 7 Jun 2023 13:19:55 +0200 Subject: [PATCH 004/111] some progress towards elastic... --- src/SeismicWaves.jl | 1 + src/checks.jl | 6 + src/models/acoustic/acou_models.jl | 2 +- src/models/cpmlcoeffs.jl | 19 +- .../backends/Elastic2D_Iso_CPML_Serial.jl | 113 +++---- src/models/elastic/ela_forward.jl | 45 +-- src/models/elastic/ela_material_properties.jl | 13 + src/models/elastic/ela_models.jl | 278 +++++++++--------- src/receivers.jl | 44 +++ src/shot.jl | 2 +- src/solve.jl | 2 +- src/sources.jl | 12 +- 12 files changed, 295 insertions(+), 242 deletions(-) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index e88a6fc..7512876 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -6,6 +6,7 @@ module SeismicWaves using LinearAlgebra using Printf using ParallelStencil +using ComputedFieldTypes export InputParametersAcoustic export CPMLBoundaryConditionParameters, ReflectiveBoundaryConditionParameters diff --git a/src/checks.jl b/src/checks.jl index 93dc6c4..b991899 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -20,6 +20,12 @@ function check_sim_consistency(wavsim::WaveSimul,matprop::MaterialProperties,sho tysource<:ScalarSources && tyreceiver<:ScalarReceivers return + + elseif tysim==ElasticIsoCPMLWaveSimul{N} && + tymatprop==MomentTensor2DSources && + tysource<:MomentTensor2DSources && + tyreceiver<:MomentTensor2DSources + return end return error("Types of WaveSimul, MaterialProperties and Sources/Receivers are incosistent \ diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 1f0d647..7c1f9ed 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -150,7 +150,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) end # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients(halo, backend) for _ in 1:N]...) + cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, sizehalfgrdplusone=true) for _ in 1:N]...) # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) a_coeffs = [] b_coeffs = [] diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 1d509d4..4c181d9 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -8,8 +8,10 @@ struct CPMLCoefficients b_hl::Any b_hr::Any - function CPMLCoefficients(halo::Integer, backend::Module) - return new( + function CPMLCoefficients(halo::Integer, backend::Module, + sizehalfgrdplusone::Bool=false) + if sizehalfgrdplusone + return new( backend.zeros(halo), backend.zeros(halo), backend.zeros(halo + 1), @@ -18,7 +20,18 @@ struct CPMLCoefficients backend.zeros(halo), backend.zeros(halo + 1), backend.zeros(halo + 1) - ) + ) + else + return new( + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo) + end end end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 1418aa9..5f07352 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -89,15 +89,14 @@ zeros = Base.zeros -function precomp_prop!(ρ,μ,λ,dh,μ_ihalf,μ_jhalf,λ_ihalf,fact) +function precomp_elaprop!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf) - fact::Float64 = 1.0/(24.0*dh) - #------------------------------------------------------------- # pre-interpolate properties at half distances between nodes #------------------------------------------------------------- # ρ_ihalf_jhalf (nx-1,ny-1) ?? - @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 + @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ + ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 # μ_ihalf (nx-1,ny) ?? # μ_ihalf (nx,ny-1) ?? if harmonicaver_μ==true @@ -111,22 +110,22 @@ function precomp_prop!(ρ,μ,λ,dh,μ_ihalf,μ_jhalf,λ_ihalf,fact) # λ_ihalf (nx-1,ny) ?? @. λ_ihalf = (λ[2:end,:] + λ[1:end-1,:]) / 2.0 - return fact + return end -function update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, - freetop) - if freeop +function update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, + freetop) + if freetop for j = 1:2 for i = 3:nx-1 # Vx # σxx derivative only in x so no problem - ∂σxx∂x_bkw = fact * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) + ∂σxx∂x_bkw = factx * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) # image, mirroring σxz[i,j-2] = -σxz[i,j+1], etc. - ∂σxz∂z_bkw = fact * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) + ∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) # update velocity vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) @@ -139,8 +138,8 @@ function update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_ for i = 3:nx-1 # Vx - ∂σxx∂x_bkw = fact * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) - ∂σxz∂z_bkw = fact * ( σxz[i,j-2] -27.0*σxz[i,j-1] +27.0*σxz[i,j] -σxz[i,j+1] ) + ∂σxx∂x_bkw = factx * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) + ∂σxz∂z_bkw = factz * ( σxz[i,j-2] -27.0*σxz[i,j-1] +27.0*σxz[i,j] -σxz[i,j+1] ) ##======================= # C-PML stuff @@ -188,8 +187,8 @@ end -function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half, - freetop) +function update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z,b_x_half,b_z_half, + a_x_half,a_z_half,freetop) if freetop for j = 1:2 @@ -197,9 +196,9 @@ function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σz # Vz # σxz derivative only in x so no problem - ∂σxz∂x_fwd = fact * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) + ∂σxz∂x_fwd = factx * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) # image, mirroring σzz[i,j-1] = -σxz[i,j+2], etc. - ∂σzz∂z_fwd = fact * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) # update velocity (ρ has been interpolated in advance) vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) @@ -212,8 +211,8 @@ function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σz for i = 2:nx-2 # Vz - ∂σxz∂x_fwd = fact * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) - ∂σzz∂z_fwd = fact * ( σzz[i,j-1] -27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + ∂σxz∂x_fwd = factx * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) + ∂σzz∂z_fwd = factz * ( σzz[i,j-1] -27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) ##======================= @@ -260,7 +259,7 @@ function update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σz end -function update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, +function update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, b_x_half,b_z,a_x_half,a_z,freetop) if freetop==true @@ -270,7 +269,7 @@ function update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x for i = 2:nx-2 # σxx # vx derivative only in x so no problem - ∂vx∂x_fwd = fact * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + ∂vx∂x_fwd = factx * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd ∂vz∂z_bkd = -(1.0-2.0*μ_ihalf[i,j]/λ_ihalf[i,j])*∂vx∂x_fwd # σxx @@ -286,9 +285,9 @@ function update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x for i = 2:nx-2 # σxx # vx derivative only in x so no problem - ∂vx∂x_fwd = fact * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + ∂vx∂x_fwd = factx * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) # zero velocity above the free surface - ∂vz∂z_bkd = fact * ( 0.0 -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) + ∂vz∂z_bkd = factz * ( 0.0 -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) # σxx σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd @@ -305,8 +304,8 @@ function update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x for i = 2:nx-2 # σxx,σzz - ∂vx∂x_fwd = fact * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) - ∂vz∂z_bkd = fact * ( vz[i,j-2] -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) + ∂vx∂x_fwd = factx * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + ∂vz∂z_bkd = factz * ( vz[i,j-2] -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) ##======================= # C-PML stuff @@ -358,7 +357,7 @@ function update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x end -function update_σxz!(σxz,fact,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, +function update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, freetop) if freetop @@ -366,9 +365,9 @@ function update_σxz!(σxz,fact,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, j = 1 for i=3:nx-1 # zero velocity above the free surface - ∂vx∂z_fwd = fact * ( 0.0 -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) + ∂vx∂z_fwd = factz * ( 0.0 -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) # vz derivative only in x so no problem - ∂vz∂x_bkd = fact * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) + ∂vz∂x_bkd = factx * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) # σxz σxz[i,j] = σxz[i,j] + μ_jhalf[i,j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) @@ -381,8 +380,8 @@ function update_σxz!(σxz,fact,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, for i = 3:nx-1 # σxz - ∂vx∂z_fwd = fact * ( vx[i,j-1] -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) - ∂vz∂x_bkd = fact * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) + ∂vx∂z_fwd = factz * ( vx[i,j-1] -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) + ∂vz∂x_bkd = factx * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) ##======================= # C-PML stuff @@ -430,62 +429,64 @@ end function forward_onestep_CPML!(vx,vz,σxx,σzz,σxz, + λ_ihalf, ρ,ρ_ihalf_jhalf, μ,μ_ihalf,μ_jhalf, - dt, + dt,dx,dz, ψ_∂σxx∂x,ψ_∂σxz∂z, ψ_∂σxz∂x,ψ_∂σzz∂z, ψ_∂vx∂x,ψ_∂vz∂z, ψ_∂vx∂z,ψ_∂vz∂x, - a_x_l, a_x_r, b_x_l, b_x_r, - a_z_l, a_z_r, b_z_l, b_z_r, - a_x_l_half, a_x_r_half, b_x_l_half, b_x_r_half, - a_z_l_half, a_z_r_half, b_z_l_half, b_z_r_half, - freetop,save_trace) + a_x_l, a_x_r, a_x_l_half, a_x_r_half, + a_z_l, a_z_r, a_z_l_half, a_z_r_half, + b_x_l, b_x_r, b_x_l_half, b_x_r_half, + b_z_l, b_z_r, b_z_l_half, b_z_r_half, + Mxx,Mzz,Mxz, + possrcs_a, srctf_a, posrecs_a, traces_a, it, + freetop, save_trace) - - # precompute some stuff - fact = precomp_prop!(ρ,μ,λ,dh,μ_ihalf,μ_jhalf,λ_ihalf) - + factx = 1.0/(24.0*dx) + factz = 1.0/(24.0*dz) + # update velocities vx and vz - update_vx!(vx,fact,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z, + update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z, b_x,b_z,a_x,a_z,freetop) - update_vz!(vz,fact,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, + update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, b_x_half,b_z_half,a_x_half,a_z_half,freetop) # update stresses σxx, σzz and σxz - update_σxxσzz!(σxx,σzz,fact,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half,ψ_∂vx∂x,ψ_∂vz∂z, + update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half,ψ_∂vx∂x,ψ_∂vz∂z, b_z,a_x_half,a_z,freetop) - update_σxz!(σxz,fact,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,ψ_∂vx∂z,ψ_∂vz∂x, + update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,ψ_∂vx∂z,ψ_∂vz∂x, a_x,a_z_half,freetop) # inject sources - inject_sources!( ??????, dt2srctf, possrcs, it) + inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_a, dt, possrcs, it) # record receivers if save_trace - record_receivers!( ??????, traces, posrecs, it) + record_receivers!(vx,vz,traces_a, posrecs, it) end return end -function inject_sources!( ) +function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_a, dt, possrcs, it) ## Inject the source as stress from moment tensor ## See Igel 2017 Computational Seismology (book) page 31, 2.6.1 if it<=lensrctf - for ir in axes(possrcs, 1) - irec = floor(Int, possrcs[ir, 1]) - jrec = floor(Int, possrcs[ir, 2]) + for s in axes(possrcs, 1) + irec = floor(Int, possrcs[s, 1]) + jrec = floor(Int, possrcs[s, 2]) - σxx[isrc,jsrc] = σxx[isrc,jsrc] + momtens.σxx * sourcetf[t]* dt - σzz[isrc,jsrc] = σzz[isrc,jsrc] + momtens.σzz * sourcetf[t]* dt - σxz[isrc,jsrc] = σxz[isrc,jsrc] + momtens.σxz * sourcetf[t]* dt + σxx[isrc,jsrc] = σxx[isrc,jsrc] + Mxx[s] * srctf_a[it] * dt + σzz[isrc,jsrc] = σzz[isrc,jsrc] + Mzz[s] * srctf_a[it] * dt + σxz[isrc,jsrc] = σxz[isrc,jsrc] + Mxz[s] * srctf_a[it] * dt end end @@ -494,12 +495,16 @@ function inject_sources!( ) end -function record_receivers!(vx,vz,traces, posrecs, it) +function record_receivers!(vx,vz,traces_a, posrecs, it) + for ir in axes(posrecs, 1) irec = floor(Int, posrecs[ir, 1]) jrec = floor(Int, posrecs[ir, 2]) # interpolate velocities on the same grid? - # ????? traces_vx[it, ir ???] = vx[irec, jrec] + N=2 # 2D + for i=1:N + traces_a[it,i,ir] = vx[irec, jrec] + end end return end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 462d448..1da4cf1 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -8,15 +8,7 @@ swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryCo srctf, traces ) where {N} - # Velocity arrays - vx = model.vx - vz = model.vz - # Stress arrays - σxx = model.σxx - σzz = model.σzz - σxz = model.σxz - # C-PML memory arrays - + # Numerics nt = model.nt # Wrap sources and receivers arrays @@ -24,35 +16,30 @@ swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryCo posrecs_a = model.backend.Data.Array(posrecs) srctf_a = model.backend.Data.Array(srctf) traces_a = model.backend.Data.Array(traces) + + ## ONLY 2D for now!!! + Mxx = model.backend.Data.Array(momtens.Mxx) + Mzz = model.backend.Data.Array(momtens.Mzz) + Mxz = model.backend.Data.Array(momtens.Mxz) + + # Reset wavesim reset!(model) # Time loop for it in 1:nt # Compute one forward step - model.backend.forward_onestep_CPML!(model.vx, model.vz, - model.σxx, model.σzz, model.σxz, + model.backend.forward_onestep_CPML!(model.velpartic..., model.stress..., + model.λ_ihalf model.ρ, model.ρ_ihalf_jhalf, model.μ, model.μ_ihalf, model.μ_jhalf, - model.dt, - model.ψ_∂σxx∂x, model.ψ_∂σxz∂z, - model.ψ_∂σxz∂x, model.ψ_∂σzz∂z, - model.ψ_∂vx∂x, model.ψ_∂vz∂z, - model.ψ_∂vx∂z, model.ψ_∂vz∂x, - model.a_coeffs..., model.b_coeffs..., + model.dt, model.gridspacing..., + model.ψ..., + model.a_coeffs..., + model.b_coeffs..., + Mxx,Mzz,Mxz, possrcs_a, srctf_a, posrecs_a, traces_a, it, - freetop,save_trace) - - # pold, pcur, pnew = model.backend.forward_onestep_CPML!( - # pold, pcur, pnew, model.fact, - # model.gridspacing..., model.halo, - # model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - # possrcs_a, srctf_a, posrecs_a, traces_a, it - # ) - - - - + freetop, save_trace) # Print timestep info if it % model.infoevery == 0 diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index 89c9423..4aa0e93 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -1,5 +1,18 @@ + Base.@kwdef struct ElasticIsoMaterialProperty{N} <: MaterialProperties{N} λ::Array{<:Float64, N} μ::Array{<:Float64, N} ρ::Array{<:Float64, N} end + + + +Base.@kwdef struct ElasticIsoMaterialProperty_Compute2D{N} <: MaterialProperties{N} + λ::Array{<:Float64, N} + μ::Array{<:Float64, N} + ρ::Array{<:Float64, N} + λ_ihalf::Array{<:Float64, N} + μ_ihalf::Array{<:Float64, N} + μ_jhalf::Array{<:Float64, N} + ρ_ihalf_jhalf::Array{<:Float64, N} +end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 051b07f..0f65dbd 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -23,6 +23,7 @@ return end + function check_numerics( model::ElasticIsoWaveSimul, shot::Shot; @@ -36,24 +37,27 @@ function check_numerics( @assert ppw >= min_ppw "Not enough points per wavelengh!" end + @views function update_matprop!(model::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} # Update material properties model.matprop.λ .= matprop.λ model.matprop.μ .= matprop.μ model.matprop.ρ .= matprop.ρ + + # the following on device? + precomp_elaprop!(model.matprop.ρ,model.matprop.μ,model.matprop.λ, + model.matprop.ρ_ihalf_jhalf, + model.matprop.μ_ihalf,model.matprop.μ_jhalf, + model.matprop.λ_ihalf) + return end -# @views function scale_srctf(model::ElasticIsoWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} -# # scale with boxcar and timestep size -# scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt^2) -# # scale with velocity squared at each source position -# for s in axes(scaled_tf, 2) -# scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] .^ 2 -# end -# return scaled_tf -# end +@views function scale_srctf(model::ElasticIsoWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} + scaled_tf = copy(srctf) + return scaled_tf +end ########################################################### @@ -74,64 +78,28 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} check_freq::Union{<:Integer, Nothing} # Snapshots snapevery::Union{<:Integer, Nothing} - snapshots::Union{<:Array{<:Real}, Nothing} + snapshots::Union{Vector{<:Array{<:Real}}, Nothing} # Logging parameters infoevery::Integer # Material properties - matprop::VpElasticIsoMaterialProperty - # CPML coefficients - cpmlcoeffs::NTuple{N, CPMLCoefficients} + matprop::ElasticIsoMaterialProperty + # # CPML coefficients + # cpmlcoeffs::NTuple{N, CPMLCoefficients} # Forward computation arrays - vx::Any - vz::Any - σxx::Any - σzz::Any - σxz::Any - λ::Any - μ::Any - ρ::Any - # ρ_ihalf_jhalf::Any - # μ_ihalf::Any - # μ_jhalf::Any - # λ_ihalf::Any - ψ::Elaψ - # ψ_∂σxx∂x::Any - # ψ_∂σxz∂z::Any - # ψ_∂σxz∂x::Any - # ψ_∂σzz∂z::Any - # ψ_∂vx∂x::Any - # ψ_∂vz∂z::Any - # ψ_∂vz∂x::Any - # ψ_∂vx∂z::Any + velpartic::Any # 2D: 2 comp, 3D: 3 comp + stress::Any # 2D: 3 arrays, 3D: 6 arrays + ψ::Any a_coeffs::Any b_coeffs::Any # Gradient computation arrays - grad::Any adj::Any - ψ_∂σxx∂x_adj::Any - ψ_∂σxz∂z_adj::Any - ψ_∂σxz∂x_adj::Any - ψ_∂σzz∂z_adj::Any - ψ_∂vx∂x_adj::Any - ψ_∂vz∂z_adj::Any - ψ_∂vz∂x_adj::Any - ψ_∂vx∂z_adj::Any + ψ_adj::Any + grad::Any # Checkpointing setup last_checkpoint::Union{<:Integer, Nothing} save_buffer::Any checkpoints::Any - checkpoints_ψ_∂σxx∂x::Any - checkpoints_ψ_∂σxz∂z::Any - checkpoints_ψ_∂σxz∂x::Any - checkpoints_ψ_∂σzz∂z::Any - checkpoints_ψ_∂vx∂x::Any - checkpoints_ψ_∂vz∂z::Any - checkpoints_ψ_∂vz∂x::Any - checkpoints_ψ_∂vx∂z::Any - a_coeffs::Any - b_coeffs::Any - - + checkpoints_ψ::Any # Backend backend::Module @@ -163,26 +131,49 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Compute model sizes ls = gridspacing .* (ns .- 1) # Initialize material properties - matprop = VpElasticIsoMaterialProperty(zeros(ns...)) + if N==2 + matprop = ElasticIsoMaterialProperty_Compute2D(λ=backend.zeros(ns...), + μ=backend.zeros(ns...), + ρ=backend.zerons(ns...), + λ_ihalf=backend.zeros((ns.-1)...), + μ_ihalf=backend.zeros((ns.-[1,0])...), + μ_jhalf=backend.zeros((ns.-[0,1])...), + ρ_ihalf_jhalf=backend.zeros((ns.-1)...), + ) + + else + error("Only elastic 2D is currently implemented.") + end # Select backend backend = select_backend(ElasticIsoCPMLWaveSimul{N}, parall) # Initialize computational arrays - fact = backend.zeros(ns...) - pold = backend.zeros(ns...) - pcur = backend.zeros(ns...) - pnew = backend.zeros(ns...) + velpartic = [backend.zeros(ns...) for _ in 1:N] # vx, vy[, vz] + stress = [backend.zeros(ns...) for _ in 1:(N-1)*3] # σxx, σxz, σzz[, σyz, σxy, σyy] + + ## 2D: + # ρ_ihalf_jhalf::Any + # μ_ihalf::Any + # μ_jhalf::Any + # λ_ihalf::Any + ## # Initialize CPML arrays - ψ = [] - ξ = [] + ## 2D: + # ψ_∂σxx∂x halo + # ψ_∂σxz∂z halo + # ψ_∂σxz∂x halo + # ψ_∂σzz∂z halo + # ψ_∂vx∂x halo + # ψ_∂vz∂z halo + # ψ_∂vz∂x halo + # ψ_∂vx∂z halo + ## + ψ = [] for i in 1:N ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + ψ_ns[i] = halo + append!(ψ, [backend.zeros(ψ_ns...) for _ in 1:(N*2^N)]) end # Initialize CPML coefficients cpmlcoeffs = tuple([CPMLCoefficients(halo, backend) for _ in 1:N]...) @@ -195,62 +186,62 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} end # Initialize gradient arrays if needed if gradient - # Current gradient array - curgrad = backend.zeros(ns...) - # Adjoint arrays - adjold = backend.zeros(ns...) - adjcur = backend.zeros(ns...) - adjnew = backend.zeros(ns...) - # Initialize CPML arrays - ψ_adj = [] - ξ_adj = [] - for i in 1:N - ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) - end - # Checkpointing setup - if check_freq !== nothing - @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" - @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" - # Time step of last checkpoint - last_checkpoint = floor(Int, nt / check_freq) * check_freq - # Checkpointing arrays - save_buffer = backend.zeros(ns..., check_freq + 2) # pressure window buffer - checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints - checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints - checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints - # Save initial conditions as first checkpoint - checkpoints[-1] = copy(pold) - checkpoints[0] = copy(pcur) - checkpoints_ψ[0] = copy.(ψ) - checkpoints_ξ[0] = copy.(ξ) - # Preallocate future checkpoints - for it in 1:(nt+1) - if it % check_freq == 0 - checkpoints[it] = backend.zeros(ns...) - checkpoints[it-1] = backend.zeros(ns...) - checkpoints_ψ[it] = copy.(ψ) - checkpoints_ξ[it] = copy.(ξ) - end - end - else # no checkpointing - last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) - save_buffer = backend.zeros(ns..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) - checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) - checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) - checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) - end - # Save first 2 timesteps in save buffer - save_buffer[fill(Colon(), N)..., 1] .= pold - save_buffer[fill(Colon(), N)..., 2] .= pcur + error("Gradient for elastic calculations not yet implemented!") + + # # Current gradient array + # curgrad = backend.zeros(ns...) + # # Adjoint arrays + # adj = backend.zeros(ns...) + # # Initialize CPML arrays + # ψ_adj = [] + # ξ_adj = [] + # for i in 1:N + # ψ_ns = [ns...] + # ξ_ns = [ns...] + # ψ_ns[i] = halo + 1 + # ξ_ns[i] = halo + # append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) + # append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + # end + # # Checkpointing setup + # if check_freq !== nothing + # @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" + # @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" + # # Time step of last checkpoint + # last_checkpoint = floor(Int, nt / check_freq) * check_freq + # # Checkpointing arrays + # save_buffer = backend.zeros(ns..., check_freq + 2) # pressure window buffer + # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints + # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints + # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints + # # Save initial conditions as first checkpoint + # checkpoints[-1] = copy(pold) + # checkpoints[0] = copy(pcur) + # checkpoints_ψ[0] = copy.(ψ) + # checkpoints_ξ[0] = copy.(ξ) + # # Preallocate future checkpoints + # for it in 1:(nt+1) + # if it % check_freq == 0 + # checkpoints[it] = backend.zeros(ns...) + # checkpoints[it-1] = backend.zeros(ns...) + # checkpoints_ψ[it] = copy.(ψ) + # checkpoints_ξ[it] = copy.(ξ) + # end + # end + # else # no checkpointing + # last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) + # save_buffer = backend.zeros(ns..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) + # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) + # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) + # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) + # end + # # Save first 2 timesteps in save buffer + # save_buffer[fill(Colon(), N)..., 1] .= pold + # save_buffer[fill(Colon(), N)..., 2] .= pcur end # Initialize snapshots array - snapshots = (snapevery !== nothing ? zeros(ns..., div(nt, snapevery)) : nothing) + snapshots = (snapevery !== nothing ? [zeros(ns..., div(nt, snapevery)) for _ in 1:N] : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -273,26 +264,18 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} snapshots, infoevery, matprop, - cpmlcoeffs, - fact, - pold, - pcur, - pnew, + velpartic, + stress, ψ, - ξ, a_coeffs, b_coeffs, - gradient ? curgrad : nothing, - gradient ? adjold : nothing, - gradient ? adjcur : nothing, - gradient ? adjnew : nothing, + gradient ? adj : nothing, gradient ? ψ_adj : nothing, - gradient ? ξ_adj : nothing, + gradient ? grad : nothing, gradient ? last_checkpoint : nothing, gradient ? save_buffer : nothing, gradient ? checkpoints : nothing, gradient ? checkpoints_ψ : nothing, - gradient ? checkpoints_ξ : nothing, backend ) end @@ -303,27 +286,28 @@ end # Specific functions for ElasticIsoCPMLWaveSimul @views function reset!(model::ElasticIsoCPMLWaveSimul{N}) where {N} + # Reset computational arrays - model.pold .= 0.0 - model.pcur .= 0.0 - model.pnew .= 0.0 - for i in eachindex(model.ψ) - model.ψ[i] .= 0.0 + for p in eachindex(model.velpartics) + model.velpartic[p] .= 0.0 + end + for p in eachindex(model.stress) + model.stress[p] .= 0.0 end - for i in eachindex(model.ξ) - model.ξ[i] .= 0.0 + for p in eachindex(model.ψ) + model.ψ[p] .= 0.0 end + # Reset gradient arrays if model.gradient - model.curgrad .= 0.0 - model.adjold .= 0.0 - model.adjcur .= 0.0 - model.adjnew .= 0.0 - for i in eachindex(model.ψ_adj) - model.ψ_adj[i] .= 0.0 + for p in eachindex(model.adj) + model.adj[p][:] .= 0.0 + end + for p in eachindex(model.grad) + model.grad[p] .= 0.0 end - for i in eachindex(model.ξ_adj) - model.ξ_adj[i] .= 0.0 + for p in eachindex(model.ψ_adj) + model.ψ_adj[p] .= 0.0 end end end diff --git a/src/receivers.jl b/src/receivers.jl index 3b9ef70..bb83f47 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -36,3 +36,47 @@ end # Default type constructor ScalarReceivers(positions, nt; observed=nothing, invcov=nothing) = ScalarReceivers{Float64}(positions, nt; observed=observed, invcov=invcov) + + +########################################################################### + +@doc raw""" +Type representing a multi-receiver configuration for a wave propagation shot. +""" +# The following using the package ComputedFieldTypes.jl +@computed struct VectorReceivers{N,T<:Real} <: Receivers + positions::Matrix{<:Real} + seismograms::Array{N+1} + observed::Matrix{T} + invcov::AbstractMatrix{T} + + @doc raw""" + Receivers[{T<:Real = Float64}](positions::Matrix{<:Real}, nt::Int, observed::Union{Matrix{T}, Nothing} = nothing) + + Create a single shot wave propagation receivers configuration from receivers positions. + """ + function VectorReceivers{N,T}( + positions::Matrix{<:Real}, + nt::Integer; + ndim::Integer=2, + observed::Union{Array{T}, Nothing}=nothing, + invcov::Union{AbstractMatrix{T}, Nothing}=nothing + ) where {T <: Real} + @assert size(positions, 1) > 0 "There must be at least one receiver!" + seismograms = zeros(T, nt, N, size(positions, 1)) + if observed !== nothing + @assert size(seismograms) == size(observed) "Size of observed data is not (# timesteps, # receivers)!" + else + observed = nothing + end + if invcov !== nothing + @assert size(invcov) == (nt, nt) "Size of invcov is not (# timesteps, # timesteps)!" + else + invcov = nothing + end + return new{N,T}(positions, seismograms, observed, invcov) + end +end + +# Default type constructor +VectorReceivers(positions, nt; observed=nothing, invcov=nothing) = VectorReceivers{Float64}(positions, nt; observed=observed, invcov=invcov) diff --git a/src/shot.jl b/src/shot.jl index 7be82ad..e8381d1 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -22,7 +22,7 @@ end # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(model, shot.srcs.positions) posrecs = find_nearest_grid_points(model, shot.recs.positions) - # prescale source time function + # source time function (prescale if needed) scaled_tf = scale_srctf(model, shot.srcs.tf, possrcs) # initialize traces array (same shape as receivers seismograms) traces = zero(shot.recs.seismograms) diff --git a/src/solve.jl b/src/solve.jl index a9a9eed..b7d1267 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -22,7 +22,7 @@ end # Remark: matprop in wavesim are mutated @info "Setting wavesim material properties" set_wavesim_matprop!(wavsim, matprop) - # Now onwards matprop from outside should not be used anymore!!! + # Now onwards matprop from "outside" should not be used anymore!!! # Snapshots setup takesnapshots = snapenabled(wavsim) diff --git a/src/sources.jl b/src/sources.jl index ff61495..01bb40f 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -31,9 +31,9 @@ ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, do Type representing a 2D moment tensor. """ struct MomentTensor2D{T <: Real} - Mxx::T - Mzz::T - Mxz::T + Mxx::Vector{T} + Mzz::Vector{T} + Mxz::Vector{T} end @@ -43,20 +43,20 @@ Type representing a multi-source configuration for a wave propagation shot. struct MomentTensor2DSources{T <: Real} <: Sources positions::Matrix{<:Real} tf::Matrix{T} - momtens::Vector{MomentTensor2D} + momtens::MomentTensor2D domfreq::T @doc """ MomentTensorSources{T<:Real}( positions::Matrix{<:Real}, tf::Matrix{<:T}, - momtens::Vector{MomentTensor2D}, + momtens::MomentTensor2D domfreq::T ) Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function MomentTensor2DSources{T}(positions::Matrix{<:Real}, tf::Matrix{T}, momtens::Vector{MomentTensor2D}, domfreq::T) where {T <: Real} + function MomentTensor2DSources{T}(positions::Matrix{<:Real}, tf::Matrix{T}, momtens::MomentTensor2D, domfreq::T) where {T <: Real} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" return new(positions, tf, momtens, domfreq) From 036280dd7d2171819c58bd851c05f20d4df053b1 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Fri, 9 Jun 2023 18:40:40 +0200 Subject: [PATCH 005/111] slow progress --- Project.toml | 6 +- ..._example.jl => simple_example_acoustic.jl} | 0 src/SeismicWaves.jl | 7 +- src/abstract_types.jl | 2 + src/input_params.jl | 14 ++ src/models/acoustic/acou_params.jl | 14 -- src/models/cpmlcoeffs.jl | 10 +- .../backends/Elastic2D_Iso_CPML_Serial.jl | 120 ++++++++++++------ src/models/elastic/ela_forward.jl | 25 ++-- src/models/elastic/ela_init_bc.jl | 2 +- src/models/elastic/ela_material_properties.jl | 20 +-- src/models/elastic/ela_models.jl | 78 +++++++++--- src/models/elastic/ela_params.jl | 13 -- src/receivers.jl | 2 +- src/sources.jl | 29 ++++- 15 files changed, 221 insertions(+), 121 deletions(-) rename examples/{simple_example.jl => simple_example_acoustic.jl} (100%) create mode 100644 src/input_params.jl diff --git a/Project.toml b/Project.toml index 6114ae6..0a3d62b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,10 +1,11 @@ name = "SeismicWaves" uuid = "f2cc81fa-a164-11e9-3f65-e3f851c759e3" -authors = ["Andrea Zunino","Giacomo Aloisi"] +authors = ["Andrea Zunino", "Giacomo Aloisi"] version = "0.4.0" [deps] CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +ComputedFieldTypes = "459fdd68-db75-56b8-8c15-d717a790f88e" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -15,9 +16,8 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [compat] julia = "1.7" - [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] \ No newline at end of file +test = ["Test"] diff --git a/examples/simple_example.jl b/examples/simple_example_acoustic.jl similarity index 100% rename from examples/simple_example.jl rename to examples/simple_example_acoustic.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 7512876..235f004 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -13,13 +13,16 @@ export CPMLBoundaryConditionParameters, ReflectiveBoundaryConditionParameters export VpAcousticCDMaterialProperty #export Sources, Receivers, Shot -export ScalarSources, ScalarReceivers, Shot +export Shot +export ScalarSources, ScalarReceivers +export MomentTensorSources, VectorReceivers export swforward!, swmisfit!, swgradient! export build_wavesim export gaussource1D, rickersource1D include("abstract_types.jl") +include("input_params.jl") include("traits/boundarycondition.jl") include("traits/shooting.jl") include("traits/snappable.jl") @@ -34,7 +37,7 @@ include("solve.jl") include("models/cpmlcoeffs.jl") include("models/acoustic/acou_abstract_types.jl") -include("models/acoustic/material_properties.jl") +include("models/acoustic/acou_material_properties.jl") include("models/acoustic/acou_models.jl") include("models/acoustic/acou_params.jl") include("models/acoustic/acou_forward.jl") diff --git a/src/abstract_types.jl b/src/abstract_types.jl index bc27c68..3fa29c0 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -10,3 +10,5 @@ abstract type MaterialProperties{N} end abstract type Sources end abstract type Receivers end + +abstract type MomentTensor end diff --git a/src/input_params.jl b/src/input_params.jl new file mode 100644 index 0000000..3d15bc7 --- /dev/null +++ b/src/input_params.jl @@ -0,0 +1,14 @@ + +""" +Reflective boundary conditions parameters for wave simulations +""" +Base.@kwdef struct ReflectiveBoundaryConditionParameters <: InputBoundaryConditionParameters end + +""" +CPML boundary conditions parameters for wave simulations +""" +Base.@kwdef struct CPMLBoundaryConditionParameters <: InputBoundaryConditionParameters + halo::Int = 20 + rcoef::Real = 0.0001 + freeboundtop::Bool = true +end diff --git a/src/models/acoustic/acou_params.jl b/src/models/acoustic/acou_params.jl index 54f26ac..4fe8a5f 100644 --- a/src/models/acoustic/acou_params.jl +++ b/src/models/acoustic/acou_params.jl @@ -24,17 +24,3 @@ function InputParametersAcoustic( return InputParametersAcoustic{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) end - -""" -Reflective boundary conditions parameters for acoustic wave simulations -""" -Base.@kwdef struct ReflectiveBoundaryConditionParameters <: InputBoundaryConditionParameters end - -""" -CPML boundary conditions parameters for acoustic wave simulations -""" -Base.@kwdef struct CPMLBoundaryConditionParameters <: InputBoundaryConditionParameters - halo::Int = 20 - rcoef::Real = 0.0001 - freeboundtop::Bool = true -end diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 4c181d9..15e6283 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -31,6 +31,7 @@ struct CPMLCoefficients backend.zeros(halo), backend.zeros(halo), backend.zeros(halo) + ) end end end @@ -38,6 +39,8 @@ end # Default type constructor CPMLCoefficients(halo) = CPMLCoefficients{Float64}(halo) +##################################### + function compute_CPML_coefficients!( cpmlcoeffs::CPMLCoefficients, vel_max::Real, @@ -48,9 +51,9 @@ function compute_CPML_coefficients!( f0::Real ) # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) - alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) - npower = 2.0 # CPML power coefficient - d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile + alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) + npower = 2.0 # CPML power coefficient + d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") @@ -64,6 +67,7 @@ function compute_CPML_coefficients!( copyto!(cpmlcoeffs.b_hr, b_hr) end + function calc_Kab_CPML( halo::Integer, dt::Float64, diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 5f07352..aa5ad0c 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -94,11 +94,11 @@ function precomp_elaprop!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf) #------------------------------------------------------------- # pre-interpolate properties at half distances between nodes #------------------------------------------------------------- - # ρ_ihalf_jhalf (nx-1,ny-1) ?? + # ρ_ihalf_jhalf (nx-1,nz-1) ?? @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 - # μ_ihalf (nx-1,ny) ?? - # μ_ihalf (nx,ny-1) ?? + # μ_ihalf (nx-1,nz) ?? + # μ_ihalf (nx,nz-1) ?? if harmonicaver_μ==true # harmonic mean @. μ_ihalf = 1.0 / ( 1.0./μ[2:end,:] + 1.0 / μ[1:end-1,:] ) @@ -107,7 +107,7 @@ function precomp_elaprop!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf) @. μ_ihalf = (μ[2:end,:] + μ[1:end-1,:]) / 2.0 @. μ_jhalf = (μ[:,2:end] + μ[:,1:end-1]) / 2.0 end - # λ_ihalf (nx-1,ny) ?? + # λ_ihalf (nx-1,nz) ?? @. λ_ihalf = (λ[2:end,:] + λ[1:end-1,:]) / 2.0 return @@ -147,23 +147,25 @@ function update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z # x boundaries if i <= halo # left boundary - ψ_∂σxx∂x[i,j] = b_x_l[i] * ψ_∂σxx∂x[i,j] + a_x_l[i] * ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] elseif i >= nx - halo + 1 # right boundary - ii = i - (nx - halo) + 1 - ψ_∂σxx∂x[ii,j] = b_x_r[ii] * ψ_∂σxx∂x[ii,j] + a_x_r[ii] * ∂σxx∂x_bkw + # ii = i - (nx - halo) + 1 + ii = i - (nx - 2*halo) + 1 # == ii = i - (nx - halo) + 1 + halo + ψ_∂σxx∂x[ii,j] = b_x[i2] * ψ_∂σxx∂x[ii,j] + a_x[ii] * ∂σxx∂x_bkw ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii,j] end # y boundaries if j <= halo && freetop==false # top boundary - ψ_∂σxz∂z[i,j] = b_z_l[j] * ψ_∂σxz∂z[i,j] + a_z_l[j] * ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] = b_z[j] * ψ_∂σxz∂z[i,j] + a_z[j] * ∂σxz∂z_bkw ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] - elseif j >= ny - halo + 1 + elseif j >= nz - halo + 1 # bottom boundary - jj = j - (ny - halo) + 1 - ψ_∂σxz∂z[i,jj] = b_z_r[jj] * ψ_∂σxz∂z[i,jj] + a_z_r[jj] * ∂σxz∂z_bkw + # jj = j - (nz - halo) + 1 + jj = j - (nz - 2*halo) + 1 + ψ_∂σxz∂z[i,jj] = b_z[jj] * ψ_∂σxz∂z[i,jj] + a_z[jj] * ∂σxz∂z_bkw ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,jj] end ##======================= @@ -221,23 +223,25 @@ function update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ # x boundaries if i <= halo + 1 # left boundary - ψ_∂σxz∂x[i,j] = b_x_l_half[i] * ψ_∂σxx∂x[i,j] + ψ_∂σxz∂x[i,j] + a_x_l_half[i]*∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] elseif i >= nx - halo # right boundary - ii = i - (nx - halo) + 1 - ψ_∂σxz∂x[ii,j] = b_x_l_half[ii] * ψ_∂σxx∂x[ii,j] + ψ_∂σxz∂x[ii,j] + a_x_l_half[ii]*∂σxz∂x_fwd + # ii = i - (nx - halo) + 1 + ii = i - (nx - 2*halo) + 1 + ψ_∂σxz∂x[ii,j] = b_x_half[ii] * ψ_∂σxz∂x[ii,j] + ψ_∂σxz∂x[ii,j] + a_x_half[ii]*∂σxz∂x_fwd ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[ii,j] end # y boundaries if j <= halo +1 && freetop==false # + 1 # top boundary - ψ_∂σzz∂z[i,j] = b_z_r_half[j] * ψ_∂σzz∂z[i,j] + a_z_r_half[j]*∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] = b_z_half[j] * ψ_∂σzz∂z[i,j] + a_z_half[j]*∂σzz∂z_fwd ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] - elseif j >= ny - halo + elseif j >= nz - halo # bottom boundary - jj = j - (ny - halo) + 1 - ψ_∂σzz∂z[i,jj] = b_z_r_half[jj] * ψ_∂σzz∂z[i,jj] + a_z_r_half[jj]*∂σzz∂z_fwd + # jj = j - (nz - halo) + 1 + jj = j - (nz - 2*halo) + 1 + ψ_∂σzz∂z[i,jj] = b_z_half[jj] * ψ_∂σzz∂z[i,jj] + a_z_half[jj]*∂σzz∂z_fwd ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,jj] end ##======================= @@ -313,24 +317,25 @@ function update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_ # x boundaries if i <= halo + 1 # left boundary - ψ_∂vx∂x[i,j] = b_x_l_half[i] * ψ_∂vx∂x[i,j] + a_x_l_half[i]*∂vx∂x_fwd + ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] elseif i >= nx - halo # right boundary - ii = i - (nx - halo) + 1 - ψ_∂vx∂x[ii,j] = b_x_l_half[ii] * ψ_∂vx∂x[ii,j] + a_x_l_half[ii]*∂vx∂x_fwd + # ii = i - (nx - halo) + 1 + ii = i - (nx - 2*halo) + 1 + ψ_∂vx∂x[ii,j] = b_x_half[ii] * ψ_∂vx∂x[ii,j] + a_x_half[ii]*∂vx∂x_fwd ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[ii,j] end # y boundaries if j <= halo && freetop==false # top boundary - ψ_∂vz∂z[i,j] = b_z_r[j] * ψ_∂vz∂z[i,j] + a_z_r[j]*∂vz∂z_bkd + ψ_∂vz∂z[i,j] = b_z[j] * ψ_∂vz∂z[i,j] + a_z[j]*∂vz∂z_bkd ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] - - elseif j >= ny - halo + 1 + elseif j >= nz - halo + 1 # bottom boundary - jj = j - (ny - halo) + 1 - ψ_∂vz∂z[i,jj] = b_z_r[jj] * ψ_∂vz∂z[i,jj] + a_z_r[jj]*∂vz∂z_bkd + # jj = j - (nz - halo) + 1 + jj = j - (nz - 2*halo) + 1 + ψ_∂vz∂z[i,jj] = b_z[jj] * ψ_∂vz∂z[i,jj] + a_z[jj]*∂vz∂z_bkd ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,jj] end ##======================= @@ -389,12 +394,13 @@ function update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z # x boundaries if i <= halo # left boundary - ψ_∂vz∂x[i,j] = b_x_l[i] * ψ_∂vz∂x[i,j] + a_x_l[i]*∂vz∂x_bkd + ψ_∂vz∂x[i,j] = b_x[i] * ψ_∂vz∂x[i,j] + a_x[i]*∂vz∂x_bkd ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] elseif i >= nx - halo + 1 # right boundary - ii = i - (nx - halo) + 1 - ψ_∂vz∂x[ii,j] = b_x_r[ii] * ψ_∂vz∂x[ii,j] + a_x_r[ii]*∂vz∂x_bkd + # ii = i - (nx - halo) + 1 + ii = i - (nx - 2*halo) + 1 + ψ_∂vz∂x[ii,j] = b_x[ii] * ψ_∂vz∂x[ii,j] + a_x[ii]*∂vz∂x_bkd ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[ii,j] end # y boundaries @@ -402,9 +408,10 @@ function update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z # top boundary ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] - elseif j >= ny - halo + elseif j >= nz - halo # bottom boundary - jj = j - (ny - halo) + 1 + #jj = j - (nz - halo) + 1 + jj = j - (nz - 2*halo) + 1 ψ_∂vx∂z[i,jj] = b_z_half[jj] * ψ_∂vx∂z[i,jj] + a_z_half[jj]*∂vx∂z_fwd ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,jj] end @@ -428,7 +435,39 @@ end -function forward_onestep_CPML!(vx,vz,σxx,σzz,σxz, +function forward_onestep_CPML!( ψ ) + + + begin + + # along x + sd = 1 + a_x = cpmlcoeff[sd].a_l + a_x = cpmlcoeff[sd].a_r + a_x_half = cpmlcoeff[sd].a_hl + a_x_half = cpmlcoeff[sd].a_hr + + b_x = cpmlcoeff[sd].b_l + b_x = cpmlcoeff[sd].b_r + b_x_half = cpmlcoeff[sd].b_hl + b_x_half = cpmlcoeff[sd].b_hr + + # along z + sd = 2 + a_z = cpmlcoeff[sd].a_l + a_z = cpmlcoeff[sd].a_r + a_z_half = cpmlcoeff[sd].a_hl + a_z_half = cpmlcoeff[sd].a_hr + + b_z = cpmlcoeff[sd].b_l + b_z = cpmlcoeff[sd].b_r + b_z_half = cpmlcoeff[sd].b_hl + b_z_half = cpmlcoeff[sd].b_hr + + end + + + vx,vz,σxx,σzz,σxz, λ_ihalf, ρ,ρ_ihalf_jhalf, μ,μ_ihalf,μ_jhalf, @@ -437,10 +476,7 @@ function forward_onestep_CPML!(vx,vz,σxx,σzz,σxz, ψ_∂σxz∂x,ψ_∂σzz∂z, ψ_∂vx∂x,ψ_∂vz∂z, ψ_∂vx∂z,ψ_∂vz∂x, - a_x_l, a_x_r, a_x_l_half, a_x_r_half, - a_z_l, a_z_r, a_z_l_half, a_z_r_half, - b_x_l, b_x_r, b_x_l_half, b_x_r_half, - b_z_l, b_z_r, b_z_l_half, b_z_r_half, + Mxx,Mzz,Mxz, possrcs_a, srctf_a, posrecs_a, traces_a, it, freetop, save_trace) @@ -449,17 +485,17 @@ function forward_onestep_CPML!(vx,vz,σxx,σzz,σxz, factz = 1.0/(24.0*dz) # update velocities vx and vz - update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z, + update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ.ψ_∂σxx∂x,ψ.ψ_∂σxz∂z, b_x,b_z,a_x,a_z,freetop) - update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, + update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ.ψ_∂σxz∂x,ψ.ψ_∂σzz∂z, b_x_half,b_z_half,a_x_half,a_z_half,freetop) # update stresses σxx, σzz and σxz - update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half,ψ_∂vx∂x,ψ_∂vz∂z, + update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half,ψ.ψ_∂vx∂x,ψ.ψ_∂vz∂z, b_z,a_x_half,a_z,freetop) - update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,ψ_∂vx∂z,ψ_∂vz∂x, + update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,ψ.ψ_∂vx∂z,ψ.ψ_∂vz∂x, a_x,a_z_half,freetop) @@ -513,8 +549,8 @@ end function correlate_gradient!( ) # _dt2 = 1 / dt^2 - # nx, ny = size(curgrad) - # for j in 1:ny + # nx, nz = size(curgrad) + # for j in 1:nz # for i in 1:nx # curgrad[i, j] = curgrad[i, j] + (adjcur[i, j] * (pcur[i, j] - 2.0 * pold[i, j] + pveryold[i, j]) * _dt2) # end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 1da4cf1..1586989 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -29,17 +29,22 @@ swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryCo # Time loop for it in 1:nt # Compute one forward step - model.backend.forward_onestep_CPML!(model.velpartic..., model.stress..., - model.λ_ihalf - model.ρ, model.ρ_ihalf_jhalf, - model.μ, model.μ_ihalf, model.μ_jhalf, - model.dt, model.gridspacing..., - model.ψ..., - model.a_coeffs..., - model.b_coeffs..., - Mxx,Mzz,Mxz, - possrcs_a, srctf_a, posrecs_a, traces_a, it, + model.backend.forward_onestep_CPML!(model, possrcs_a, srctf_a, posrecs_a, traces_a, it, freetop, save_trace) + + + + # model.velpartic..., model.stress..., + # model.λ_ihalf + # model.ρ, model.ρ_ihalf_jhalf, + # model.μ, model.μ_ihalf, model.μ_jhalf, + # model.dt, model.gridspacing..., + # model.ψ..., + # model.a_coeffs..., + # model.b_coeffs..., + # Mxx,Mzz,Mxz, + # possrcs_a, srctf_a, posrecs_a, traces_a, it, + # freetop, save_trace) # Print timestep info if it % model.infoevery == 0 diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl index 7dfa5f5..28ed161 100644 --- a/src/models/elastic/ela_init_bc.jl +++ b/src/models/elastic/ela_init_bc.jl @@ -17,7 +17,7 @@ init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimul, srcs::Sources) model.dt, model.halo, model.rcoef, - model.gridspacing[n] * model.halo, + model.gridspacing[n] * model.halo, ## <<-- Check: dx*(n-1)? srcs.domfreq ) end diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index 4aa0e93..c3896ca 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -1,18 +1,18 @@ Base.@kwdef struct ElasticIsoMaterialProperty{N} <: MaterialProperties{N} - λ::Array{<:Float64, N} - μ::Array{<:Float64, N} - ρ::Array{<:Float64, N} + λ::Array{<:AbstractFloat, N} + μ::Array{<:AbstractFloat, N} + ρ::Array{<:AbstractFloat, N} end Base.@kwdef struct ElasticIsoMaterialProperty_Compute2D{N} <: MaterialProperties{N} - λ::Array{<:Float64, N} - μ::Array{<:Float64, N} - ρ::Array{<:Float64, N} - λ_ihalf::Array{<:Float64, N} - μ_ihalf::Array{<:Float64, N} - μ_jhalf::Array{<:Float64, N} - ρ_ihalf_jhalf::Array{<:Float64, N} + λ::Array{<:AbstractFloat, N} + μ::Array{<:AbstractFloat, N} + ρ::Array{<:AbstractFloat, N} + λ_ihalf::Array{<:AbstractFloat, N} + μ_ihalf::Array{<:AbstractFloat, N} + μ_jhalf::Array{<:AbstractFloat, N} + ρ_ihalf_jhalf::Array{<:AbstractFloat, N} end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 0f65dbd..9232602 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -39,6 +39,7 @@ end @views function update_matprop!(model::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} + # Update material properties model.matprop.λ .= matprop.λ model.matprop.μ .= matprop.μ @@ -61,6 +62,57 @@ end ########################################################### +struct Elasticψdomain2D{T<:AstractFloat} + ψ_∂σxx∂x::Array{T,2} + ψ_∂σxz∂z::Array{T,2} + ψ_∂σxz∂x::Array{T,2} + ψ_∂σzz∂z::Array{T,2} + ψ_∂vx∂x::Array{T,2} + ψ_∂vz∂z::Array{T,2} + ψ_∂vz∂x::Array{T,2} + ψ_∂vx∂z::Array{T,2} + + function Elasticψdomain2D(backend,ns,N,halo) + + ψ_ns = [ns...] + ψ_ns[N] = 2*halo + + ψ_∂σxx∂x = backend.zeros(ψ_ns...) + ψ_∂σxz∂z = backend.zeros(ψ_ns...) + ψ_∂σxz∂x = backend.zeros(ψ_ns...) + ψ_∂σzz∂z = backend.zeros(ψ_ns...) + ψ_∂vx∂x = backend.zeros(ψ_ns...) + ψ_∂vz∂z = backend.zeros(ψ_ns...) + ψ_∂vz∂x = backend.zeros(ψ_ns...) + ψ_∂vx∂z = backend.zeros(ψ_ns...) + + T = eltype(ψ_∂σxx∂x) + return new{T}(ψ_∂σxx∂x, + ψ_∂σxz∂z, + ψ_∂σxz∂x, + ψ_∂σzz∂z, + ψ_∂vx∂x, + ψ_∂vz∂z, + ψ_∂vz∂x, + ψ_∂vx∂z) + end +end + + +# struct ElasticψRegion3D{T<:AstractFloat} +# ψ_∂σxx∂x::Array{T} +# ψ_∂σxz∂z::Array{T} +# ψ_∂σxz∂x::Array{T} +# ψ_∂σzz∂z::Array{T} +# ψ_∂vx∂x::Array{T} +# ψ_∂vz∂z::Array{T} +# ψ_∂vz∂x::Array{T} +# ψ_∂vx∂z::Array{T} +# end + + + + struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Physics ls::NTuple{N, <:Real} @@ -71,7 +123,6 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} dt::Real # BDC and CPML parameters halo::Integer - rcoef::Real freetop::Bool # Gradient computation setup gradient::Bool @@ -103,13 +154,13 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Backend backend::Module + function ElasticIsoCPMLWaveSimul{N}( ns::NTuple{N, <:Integer}, gridspacing::NTuple{N, <:Real}, nt::Integer, dt::Real, halo::Integer, - rcoef::Real; parall::Symbol=:threads, freetop::Bool=true, gradient::Bool=false, @@ -169,21 +220,15 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # ψ_∂vz∂x halo # ψ_∂vx∂z halo ## - ψ = [] - for i in 1:N - ψ_ns = [ns...] - ψ_ns[i] = halo - append!(ψ, [backend.zeros(ψ_ns...) for _ in 1:(N*2^N)]) + if N==2 # 2D + ψ = Elasticψdomain2D(backend,ns,N,halo) + else + error("Only elastic 2D is currently implemented.") end + # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients(halo, backend) for _ in 1:N]...) - # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) - a_coeffs = [] - b_coeffs = [] - for i in 1:N - append!(a_coeffs, [cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr]) - append!(b_coeffs, [cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr]) - end + cpmlcoeffs = [CPMLCoefficients(halo, backend) for _ in 1:N] + # Initialize gradient arrays if needed if gradient error("Gradient for elastic calculations not yet implemented!") @@ -267,8 +312,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} velpartic, stress, ψ, - a_coeffs, - b_coeffs, + cpmlcoeff, gradient ? adj : nothing, gradient ? ψ_adj : nothing, gradient ? grad : nothing, diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl index 490ee9f..3171032 100644 --- a/src/models/elastic/ela_params.jl +++ b/src/models/elastic/ela_params.jl @@ -25,16 +25,3 @@ function InputParametersElastic( return InputParametersElastic{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) end -""" -Reflective boundary conditions parameters for acoustic wave simulations -""" -Base.@kwdef struct ReflectiveBoundaryConditionParameters <: InputBoundaryConditionParameters end - -""" -CPML boundary conditions parameters for acoustic wave simulations -""" -Base.@kwdef struct CPMLBoundaryConditionParameters <: InputBoundaryConditionParameters - halo::Int = 20 - rcoef::Real = 0.0001 - freeboundtop::Bool = true -end diff --git a/src/receivers.jl b/src/receivers.jl index bb83f47..3b15963 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -61,7 +61,7 @@ Type representing a multi-receiver configuration for a wave propagation shot. ndim::Integer=2, observed::Union{Array{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing - ) where {T <: Real} + ) where {N,T <: Real} @assert size(positions, 1) > 0 "There must be at least one receiver!" seismograms = zeros(T, nt, N, size(positions, 1)) if observed !== nothing diff --git a/src/sources.jl b/src/sources.jl index 01bb40f..9c4b6db 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -30,20 +30,32 @@ ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, do """ Type representing a 2D moment tensor. """ -struct MomentTensor2D{T <: Real} +struct MomentTensor2D{T <: Real} <: MomentTensor Mxx::Vector{T} Mzz::Vector{T} Mxz::Vector{T} end +""" +Type representing a 2D moment tensor. +""" +struct MomentTensor3D{T <: Real} <: MomentTensor + Mxx::Vector{T} + Myy::Vector{T} + Mzz::Vector{T} + Mxy::Vector{T} + Mxz::Vector{T} + Myz::Vector{T} +end + """ Type representing a multi-source configuration for a wave propagation shot. """ -struct MomentTensor2DSources{T <: Real} <: Sources +struct MomentTensorSources{N, T <: Real} <: Sources positions::Matrix{<:Real} tf::Matrix{T} - momtens::MomentTensor2D + momtens::MomentTensor domfreq::T @doc """ @@ -56,10 +68,17 @@ struct MomentTensor2DSources{T <: Real} <: Sources Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function MomentTensor2DSources{T}(positions::Matrix{<:Real}, tf::Matrix{T}, momtens::MomentTensor2D, domfreq::T) where {T <: Real} + function MomentTensorSources{N,T}(positions::Matrix{<:Real}, tf::Matrix{T}, momtens::MomentTensor, domfreq::T) where {N, T <: Real} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" - return new(positions, tf, momtens, domfreq) + if N==1 + @assert typeof(momtens)==MomentTensor2D + elseif N==2 + @assert typeof(momtens)==MomentTensor3D + else + error("MomentTensorSources: Moment tensor neither 2D nor 3D.") + end + return new{N,T}(positions, tf, momtens, domfreq) end end From df502bded459f2cca99687f920aa82cec74830e1 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Mon, 23 Oct 2023 11:16:26 +0200 Subject: [PATCH 006/111] working on ela... --- src/models/cpmlcoeffs.jl | 53 ++++++++++- .../backends/Elastic2D_Iso_CPML_Serial.jl | 90 ++++++++----------- src/models/elastic/ela_models.jl | 77 +++++++--------- 3 files changed, 124 insertions(+), 96 deletions(-) diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 15e6283..d9c4bcd 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -1,3 +1,54 @@ + +struct CPMLCoefficientsAxis + a::Any + a_h::Any + b::Any + b_h::Any + + function CPMLCoefficientsAxis(halo::Integer, backend::Module, + sizehalfgrdplusone::Bool=false) + if sizehalfgrdplusone + return new( + backend.zeros(halo), + backend.zeros(halo + 1), + backend.zeros(halo), + backend.zeros(halo + 1), + ) + else + return new( + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo) + ) + end + end +end + +function compute_CPML_coefficientsAxis!( + cpmlcoeffs::CPMLCoefficients, + vel_max::Real, + dt::Real, + halo::Integer, + rcoef::Real, + thickness::Real, + f0::Real +) + # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) + alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) + npower = 2.0 # CPML power coefficient + d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile + a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") + a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") + + copyto!(cpmlcoeffs.a, cat(a_l,a_r)) + copyto!(cpmlcoeffs.a_h, cat(a_hl,a_hr)) + copyto!(cpmlcoeffs.b, cat(b_l,b_r)) + copyto!(cpmlcoeffs.b_h, cat(b_hl,b_hr)) +end + +################################################################# + struct CPMLCoefficients a_l::Any a_r::Any @@ -37,7 +88,7 @@ struct CPMLCoefficients end # Default type constructor -CPMLCoefficients(halo) = CPMLCoefficients{Float64}(halo) +# CPMLCoefficients(halo) = CPMLCoefficients{Float64}(halo) ##################################### diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index aa5ad0c..9440af1 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -435,68 +435,56 @@ end -function forward_onestep_CPML!( ψ ) - - - begin - - # along x - sd = 1 - a_x = cpmlcoeff[sd].a_l - a_x = cpmlcoeff[sd].a_r - a_x_half = cpmlcoeff[sd].a_hl - a_x_half = cpmlcoeff[sd].a_hr - - b_x = cpmlcoeff[sd].b_l - b_x = cpmlcoeff[sd].b_r - b_x_half = cpmlcoeff[sd].b_hl - b_x_half = cpmlcoeff[sd].b_hr - - # along z - sd = 2 - a_z = cpmlcoeff[sd].a_l - a_z = cpmlcoeff[sd].a_r - a_z_half = cpmlcoeff[sd].a_hl - a_z_half = cpmlcoeff[sd].a_hr - - b_z = cpmlcoeff[sd].b_l - b_z = cpmlcoeff[sd].b_r - b_z_half = cpmlcoeff[sd].b_hl - b_z_half = cpmlcoeff[sd].b_hr - - end - - - vx,vz,σxx,σzz,σxz, - λ_ihalf, - ρ,ρ_ihalf_jhalf, - μ,μ_ihalf,μ_jhalf, - dt,dx,dz, - ψ_∂σxx∂x,ψ_∂σxz∂z, - ψ_∂σxz∂x,ψ_∂σzz∂z, - ψ_∂vx∂x,ψ_∂vz∂z, - ψ_∂vx∂z,ψ_∂vz∂x, - - Mxx,Mzz,Mxz, +function forward_onestep_CPML!(model, possrcs_a, srctf_a, posrecs_a, traces_a, it, freetop, save_trace) - + + vx = model.velpartic.vx + vz = model.velpartic.vz + σxx = model.stress.σxx + σzz = model.stress.σzz + σxz = model.stress.σxz + + psi = model.ψ + + a_x = cpmlcoeffs[1].a + a_x_half = cpmlcoeffs[1].a_h + b_x = cpmlcoeffs[1].b + b_x_half = cpmlcoeffs[1].b_h + + a_z = cpmlcoeffs[2].a + a_z_half = cpmlcoeffs[2].a_h + b_z = cpmlcoeffs[2].b + b_z_half = cpmlcoeffs[2].b_h + + λ_ihal = matprop.λ_ihal + ρ = matprop.ρ + ρ_ihalf_jhalf = matprop.ρ_ihalf_jhalf + μ = matprop.μ + μ_ihalf = matprop.μ_ihalf + μ_jhalf = matprop.μ_jhalf + + Mxx = model.momtens.Mxx + Mzz = model.momtens.Mzz + Mxz = model.momtens.Mxz + + ## factx = 1.0/(24.0*dx) factz = 1.0/(24.0*dz) # update velocities vx and vz - update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ.ψ_∂σxx∂x,ψ.ψ_∂σxz∂z, + update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, b_x,b_z,a_x,a_z,freetop) - update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ.ψ_∂σxz∂x,ψ.ψ_∂σzz∂z, - b_x_half,b_z_half,a_x_half,a_z_half,freetop) + update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, + psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) # update stresses σxx, σzz and σxz - update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half,ψ.ψ_∂vx∂x,ψ.ψ_∂vz∂z, - b_z,a_x_half,a_z,freetop) + update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half, + psi.ψ_∂vx∂x,psi.ψ_∂vz∂z,b_z,a_x_half,a_z,freetop) - update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,ψ.ψ_∂vx∂z,ψ.ψ_∂vz∂x, - a_x,a_z_half,freetop) + update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half, + psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) # inject sources diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 9232602..abc0dca 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -60,8 +60,10 @@ end return scaled_tf end + ########################################################### + struct Elasticψdomain2D{T<:AstractFloat} ψ_∂σxx∂x::Array{T,2} ψ_∂σxz∂z::Array{T,2} @@ -85,7 +87,7 @@ struct Elasticψdomain2D{T<:AstractFloat} ψ_∂vz∂z = backend.zeros(ψ_ns...) ψ_∂vz∂x = backend.zeros(ψ_ns...) ψ_∂vx∂z = backend.zeros(ψ_ns...) - + T = eltype(ψ_∂σxx∂x) return new{T}(ψ_∂σxx∂x, ψ_∂σxz∂z, @@ -99,18 +101,21 @@ struct Elasticψdomain2D{T<:AstractFloat} end -# struct ElasticψRegion3D{T<:AstractFloat} -# ψ_∂σxx∂x::Array{T} -# ψ_∂σxz∂z::Array{T} -# ψ_∂σxz∂x::Array{T} -# ψ_∂σzz∂z::Array{T} -# ψ_∂vx∂x::Array{T} -# ψ_∂vz∂z::Array{T} -# ψ_∂vz∂x::Array{T} -# ψ_∂vx∂z::Array{T} -# end +struct Velpartic2D{T<:AbstractFloat} + vx::Array{T,2} + vz::Array{T,2} +end + + +struct Stress2D{T<:AbstractFloat} + σxx::Array{T,2} + σzz::Array{T,2} + σxz::Array{T,2} +end + +############################################################## struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} @@ -134,14 +139,12 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} infoevery::Integer # Material properties matprop::ElasticIsoMaterialProperty - # # CPML coefficients - # cpmlcoeffs::NTuple{N, CPMLCoefficients} # Forward computation arrays velpartic::Any # 2D: 2 comp, 3D: 3 comp stress::Any # 2D: 3 arrays, 3D: 6 arrays + # CPML coefficients + cpmlcoeffs::Any ψ::Any - a_coeffs::Any - b_coeffs::Any # Gradient computation arrays adj::Any ψ_adj::Any @@ -200,25 +203,11 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} backend = select_backend(ElasticIsoCPMLWaveSimul{N}, parall) # Initialize computational arrays - velpartic = [backend.zeros(ns...) for _ in 1:N] # vx, vy[, vz] - stress = [backend.zeros(ns...) for _ in 1:(N-1)*3] # σxx, σxz, σzz[, σyz, σxy, σyy] - - ## 2D: - # ρ_ihalf_jhalf::Any - # μ_ihalf::Any - # μ_jhalf::Any - # λ_ihalf::Any - ## - # Initialize CPML arrays - ## 2D: - # ψ_∂σxx∂x halo - # ψ_∂σxz∂z halo - # ψ_∂σxz∂x halo - # ψ_∂σzz∂z halo - # ψ_∂vx∂x halo - # ψ_∂vz∂z halo - # ψ_∂vz∂x halo - # ψ_∂vx∂z halo + if N==2 + velpartic = Velpartic2D([backend.zeros(ns...) for _ in 1:N]...) # vx, vy[, vz] + stress = Stress2D([backend.zeros(ns...) for _ in 1:(N-1)*3]...) # vx, vy[, vz] + end + ## if N==2 # 2D ψ = Elasticψdomain2D(backend,ns,N,halo) @@ -227,7 +216,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} end # Initialize CPML coefficients - cpmlcoeffs = [CPMLCoefficients(halo, backend) for _ in 1:N] + cpmlcoeffs = [CPMLCoefficientsAxis(halo, backend) for _ in 1:N] # Initialize gradient arrays if needed if gradient @@ -311,8 +300,8 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} matprop, velpartic, stress, - ψ, cpmlcoeff, + ψ, gradient ? adj : nothing, gradient ? ψ_adj : nothing, gradient ? grad : nothing, @@ -332,14 +321,14 @@ end @views function reset!(model::ElasticIsoCPMLWaveSimul{N}) where {N} # Reset computational arrays - for p in eachindex(model.velpartics) - model.velpartic[p] .= 0.0 + for p in fieldnames(model.velpartic) + getfield(model.velpartic,p) .= 0.0 end - for p in eachindex(model.stress) - model.stress[p] .= 0.0 + for p in fieldnames(model.stress) + getfield(model.stress,p) .= 0.0 end - for p in eachindex(model.ψ) - model.ψ[p] .= 0.0 + for p in fieldnames(model.ψ) + getfield(model.ψ, p) .= 0.0 end # Reset gradient arrays @@ -350,8 +339,8 @@ end for p in eachindex(model.grad) model.grad[p] .= 0.0 end - for p in eachindex(model.ψ_adj) - model.ψ_adj[p] .= 0.0 + for p in fieldnames(model.ψ_adj) + getfield(model.ψ_adj, p) .= 0.0 end end end From 8604987a4832e0afee3d34cd6ecfaeed3bccf8da Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Thu, 30 Nov 2023 12:18:17 +0100 Subject: [PATCH 007/111] wip... --- .../backends/Elastic2D_Iso_CPML_Serial.jl | 16 ++++++++++------ src/models/elastic/ela_forward.jl | 6 ++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 9440af1..27f58ae 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -89,25 +89,29 @@ zeros = Base.zeros -function precomp_elaprop!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf) +function precomp_elaprop!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; + harmonicaver_μ=true) #------------------------------------------------------------- # pre-interpolate properties at half distances between nodes #------------------------------------------------------------- # ρ_ihalf_jhalf (nx-1,nz-1) ?? + # arithmetic mean for ρ @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 # μ_ihalf (nx-1,nz) ?? # μ_ihalf (nx,nz-1) ?? if harmonicaver_μ==true - # harmonic mean + # harmonic mean for μ @. μ_ihalf = 1.0 / ( 1.0./μ[2:end,:] + 1.0 / μ[1:end-1,:] ) @. μ_jhalf = 1.0 / ( 1.0./μ[:,2:end] + 1.0 / μ[:,1:end-1] ) else + # arithmetic mean for μ @. μ_ihalf = (μ[2:end,:] + μ[1:end-1,:]) / 2.0 @. μ_jhalf = (μ[:,2:end] + μ[:,1:end-1]) / 2.0 end # λ_ihalf (nx-1,nz) ?? + # arithmetic mean for λ @. λ_ihalf = (λ[2:end,:] + λ[1:end-1,:]) / 2.0 return @@ -472,17 +476,17 @@ function forward_onestep_CPML!(model, factx = 1.0/(24.0*dx) factz = 1.0/(24.0*dz) - # update velocities vx and vz + # update velocity vx update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, b_x,b_z,a_x,a_z,freetop) - + # update velocity vz update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) - # update stresses σxx, σzz and σxz + # update stresses σxx and σzz update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half, psi.ψ_∂vx∂x,psi.ψ_∂vz∂z,b_z,a_x_half,a_z,freetop) - + # update stress σxz update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half, psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 1586989..8386d86 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -14,7 +14,7 @@ swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryCo # Wrap sources and receivers arrays possrcs_a = model.backend.Data.Array(possrcs) posrecs_a = model.backend.Data.Array(posrecs) - srctf_a = model.backend.Data.Array(srctf) + srctf_a = model.backend.Data.Array(srctf) traces_a = model.backend.Data.Array(traces) ## ONLY 2D for now!!! @@ -22,7 +22,6 @@ swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryCo Mzz = model.backend.Data.Array(momtens.Mzz) Mxz = model.backend.Data.Array(momtens.Mxz) - # Reset wavesim reset!(model) @@ -32,8 +31,6 @@ swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryCo model.backend.forward_onestep_CPML!(model, possrcs_a, srctf_a, posrecs_a, traces_a, it, freetop, save_trace) - - # model.velpartic..., model.stress..., # model.λ_ihalf # model.ρ, model.ρ_ihalf_jhalf, @@ -65,4 +62,5 @@ swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryCo # Save traces traces .= Array(traces_a) + return end From 8d88a870f68ea2a337d8273a3b170434912a0fcc Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Fri, 15 Dec 2023 17:55:44 +0100 Subject: [PATCH 008/111] update --- .../backends/Elastic2D_Iso_CPML_Serial.jl | 47 ++++++++------ src/models/elastic/ela_forward.jl | 53 +++++++-------- src/models/elastic/ela_models.jl | 64 +++++++++---------- 3 files changed, 85 insertions(+), 79 deletions(-) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 27f58ae..4591f29 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -103,8 +103,8 @@ function precomp_elaprop!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; # μ_ihalf (nx,nz-1) ?? if harmonicaver_μ==true # harmonic mean for μ - @. μ_ihalf = 1.0 / ( 1.0./μ[2:end,:] + 1.0 / μ[1:end-1,:] ) - @. μ_jhalf = 1.0 / ( 1.0./μ[:,2:end] + 1.0 / μ[:,1:end-1] ) + @. μ_ihalf = 1.0 / ( 1.0/μ[2:end,:] + 1.0 / μ[1:end-1,:] ) + @. μ_jhalf = 1.0 / ( 1.0/μ[:,2:end] + 1.0 / μ[:,1:end-1] ) else # arithmetic mean for μ @. μ_ihalf = (μ[2:end,:] + μ[1:end-1,:]) / 2.0 @@ -439,17 +439,22 @@ end -function forward_onestep_CPML!(model, - possrcs_a, srctf_a, posrecs_a, traces_a, it, - freetop, save_trace) +function forward_onestep_CPML!(wavsim::ElasticIsoWaveSimul{N}, + possrcs_a::Array{<:Integer,2}, + srctf_a::Matrix{<:Real}, + posrecs_a::Array{<:Integer,2}, + traces_a::Array{<:Real,N+1}, + it::Integer, + freetop::Bool, + save_trace::Bool) where {N} - vx = model.velpartic.vx - vz = model.velpartic.vz - σxx = model.stress.σxx - σzz = model.stress.σzz - σxz = model.stress.σxz + vx = wavsim.velpartic.vx + vz = wavsim.velpartic.vz + σxx = wavsim.stress.σxx + σzz = wavsim.stress.σzz + σxz = wavsim.stress.σxz - psi = model.ψ + psi = wavsim.ψ a_x = cpmlcoeffs[1].a a_x_half = cpmlcoeffs[1].a_h @@ -468,9 +473,9 @@ function forward_onestep_CPML!(model, μ_ihalf = matprop.μ_ihalf μ_jhalf = matprop.μ_jhalf - Mxx = model.momtens.Mxx - Mzz = model.momtens.Mzz - Mxz = model.momtens.Mxz + Mxx = wavsim.momtens.Mxx + Mzz = wavsim.momtens.Mzz + Mxz = wavsim.momtens.Mxz ## factx = 1.0/(24.0*dx) @@ -509,12 +514,12 @@ function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_a, dt, possrcs, it) if it<=lensrctf for s in axes(possrcs, 1) - irec = floor(Int, possrcs[s, 1]) - jrec = floor(Int, possrcs[s, 2]) + irec = possrcs[s, 1] + jrec = possrcs[s, 2] - σxx[isrc,jsrc] = σxx[isrc,jsrc] + Mxx[s] * srctf_a[it] * dt - σzz[isrc,jsrc] = σzz[isrc,jsrc] + Mzz[s] * srctf_a[it] * dt - σxz[isrc,jsrc] = σxz[isrc,jsrc] + Mxz[s] * srctf_a[it] * dt + σxx[isrc,jsrc] += Mxx[s] * srctf_a[it] * dt + σzz[isrc,jsrc] += Mzz[s] * srctf_a[it] * dt + σxz[isrc,jsrc] += Mxz[s] * srctf_a[it] * dt end end @@ -526,8 +531,8 @@ end function record_receivers!(vx,vz,traces_a, posrecs, it) for ir in axes(posrecs, 1) - irec = floor(Int, posrecs[ir, 1]) - jrec = floor(Int, posrecs[ir, 2]) + irec = posrecs[ir, 1] + jrec = posrecs[ir, 2] # interpolate velocities on the same grid? N=2 # 2D for i=1:N diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 8386d86..c06c59a 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -1,66 +1,67 @@ -swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) + +swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) @views function swforward_1shot!( ::CPMLBoundaryCondition, - model::ElasticIsoWaveSimul{N}, + wavsim::ElasticIsoWaveSimul{N}, possrcs, posrecs, srctf, - traces + recs ) where {N} # Numerics - nt = model.nt + nt = wavsim.nt # Wrap sources and receivers arrays - possrcs_a = model.backend.Data.Array(possrcs) - posrecs_a = model.backend.Data.Array(posrecs) - srctf_a = model.backend.Data.Array(srctf) - traces_a = model.backend.Data.Array(traces) + possrcs_a = wavsim.backend.Data.Array(possrcs) + posrecs_a = wavsim.backend.Data.Array(posrecs) + srctf_a = wavsim.backend.Data.Array(srctf) + traces_a = wavsim.backend.Data.Array(recs.seismograms) ## ONLY 2D for now!!! - Mxx = model.backend.Data.Array(momtens.Mxx) - Mzz = model.backend.Data.Array(momtens.Mzz) - Mxz = model.backend.Data.Array(momtens.Mxz) + Mxx = wavsim.backend.Data.Array(momtens.Mxx) + Mzz = wavsim.backend.Data.Array(momtens.Mzz) + Mxz = wavsim.backend.Data.Array(momtens.Mxz) # Reset wavesim - reset!(model) + reset!(wavsim) # Time loop for it in 1:nt # Compute one forward step - model.backend.forward_onestep_CPML!(model, possrcs_a, srctf_a, posrecs_a, traces_a, it, + wavsim.backend.forward_onestep_CPML!(wavsim, possrcs_a, srctf_a, posrecs_a, traces_a, it, freetop, save_trace) - # model.velpartic..., model.stress..., - # model.λ_ihalf - # model.ρ, model.ρ_ihalf_jhalf, - # model.μ, model.μ_ihalf, model.μ_jhalf, - # model.dt, model.gridspacing..., - # model.ψ..., - # model.a_coeffs..., - # model.b_coeffs..., + # wavsim.velpartic..., wavsim.stress..., + # wavsim.λ_ihalf + # wavsim.ρ, wavsim.ρ_ihalf_jhalf, + # wavsim.μ, wavsim.μ_ihalf, wavsim.μ_jhalf, + # wavsim.dt, wavsim.gridspacing..., + # wavsim.ψ..., + # wavsim.a_coeffs..., + # wavsim.b_coeffs..., # Mxx,Mzz,Mxz, # possrcs_a, srctf_a, posrecs_a, traces_a, it, # freetop, save_trace) # Print timestep info - if it % model.infoevery == 0 + if it % wavsim.infoevery == 0 @debug @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, - model.dt * (it - 1), + wavsim.dt * (it - 1), maximum(abs.(Array(pcur))) ) end # Save snapshot - if snapenabled(model) && it % model.snapevery == 0 + if snapenabled(wavsim) && it % wavsim.snapevery == 0 @debug @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) - model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)] .= Array(pcur) + wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)] .= Array(pcur) end end # Save traces - traces .= Array(traces_a) + copyto!(recs.seismograms, traces_a) return end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index abc0dca..1426ba0 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,19 +2,19 @@ # Functions for all ElasticIsoWaveSimul subtypes -@views function check_matprop(model::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} +@views function check_matprop(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} # Checks vp = sqrt((matprop.λ .+ 2.*matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(vp) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.ns)" + @assert size(vp) == wavsim.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(wavsim.ns)" @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" @assert all(matprop.ρ .> 0) "Density must be positive!" # Check courant condition - vp_max = get_maximum_func(model)(vp) - tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) - courant = vel_max * model.dt * tmp + vp_max = get_maximum_func(wavsim)(vp) + tmp = sqrt(sum(1 ./ wavsim.gridspacing .^ 2)) + courant = vel_max * wavsim.dt * tmp @debug "Courant number: $(courant)" if courant > 1.0 @warn "Courant condition not satisfied! [$(courant)]" @@ -25,37 +25,37 @@ end function check_numerics( - model::ElasticIsoWaveSimul, + wavsim::ElasticIsoWaveSimul, shot::Shot; min_ppw::Integer=10 ) # Check points per wavelengh - vel_min = get_minimum_func(model)(sqrt(model.matprop.μ ./ model.matprop.ρ)) # min Vs - h_max = maximum(model.gridspacing) + vel_min = get_minimum_func(wavsim)(sqrt(wavsim.matprop.μ ./ wavsim.matprop.ρ)) # min Vs + h_max = maximum(wavsim.gridspacing) ppw = vel_min / shot.srcs.domfreq / h_max @debug "Points per wavelength: $(ppw)" @assert ppw >= min_ppw "Not enough points per wavelengh!" end -@views function update_matprop!(model::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} +@views function update_matprop!(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} # Update material properties - model.matprop.λ .= matprop.λ - model.matprop.μ .= matprop.μ - model.matprop.ρ .= matprop.ρ + wavsim.matprop.λ .= matprop.λ + wavsim.matprop.μ .= matprop.μ + wavsim.matprop.ρ .= matprop.ρ # the following on device? - precomp_elaprop!(model.matprop.ρ,model.matprop.μ,model.matprop.λ, - model.matprop.ρ_ihalf_jhalf, - model.matprop.μ_ihalf,model.matprop.μ_jhalf, - model.matprop.λ_ihalf) + precomp_elaprop!(wavsim.matprop.ρ,wavsim.matprop.μ,wavsim.matprop.λ, + wavsim.matprop.ρ_ihalf_jhalf, + wavsim.matprop.μ_ihalf,wavsim.matprop.μ_jhalf, + wavsim.matprop.λ_ihalf) return end -@views function scale_srctf(model::ElasticIsoWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} +@views function scale_srctf(wavsim::ElasticIsoWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} scaled_tf = copy(srctf) return scaled_tf end @@ -182,7 +182,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} ns_cpml = freetop ? ns[1:(end-1)] : ns @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" - # Compute model sizes + # Compute wavsim sizes ls = gridspacing .* (ns .- 1) # Initialize material properties if N==2 @@ -318,29 +318,29 @@ end # Specific functions for ElasticIsoCPMLWaveSimul -@views function reset!(model::ElasticIsoCPMLWaveSimul{N}) where {N} +@views function reset!(wavsim::ElasticIsoCPMLWaveSimul{N}) where {N} # Reset computational arrays - for p in fieldnames(model.velpartic) - getfield(model.velpartic,p) .= 0.0 + for p in fieldnames(wavsim.velpartic) + getfield(wavsim.velpartic,p) .= 0.0 end - for p in fieldnames(model.stress) - getfield(model.stress,p) .= 0.0 + for p in fieldnames(wavsim.stress) + getfield(wavsim.stress,p) .= 0.0 end - for p in fieldnames(model.ψ) - getfield(model.ψ, p) .= 0.0 + for p in fieldnames(wavsim.ψ) + getfield(wavsim.ψ, p) .= 0.0 end # Reset gradient arrays - if model.gradient - for p in eachindex(model.adj) - model.adj[p][:] .= 0.0 + if wavsim.gradient + for p in eachindex(wavsim.adj) + wavsim.adj[p][:] .= 0.0 end - for p in eachindex(model.grad) - model.grad[p] .= 0.0 + for p in eachindex(wavsim.grad) + wavsim.grad[p] .= 0.0 end - for p in fieldnames(model.ψ_adj) - getfield(model.ψ_adj, p) .= 0.0 + for p in fieldnames(wavsim.ψ_adj) + getfield(wavsim.ψ_adj, p) .= 0.0 end end end From a135cedc5cfaa8ac367d7fa97bc432745d7dd26f Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Tue, 19 Dec 2023 17:50:10 +0100 Subject: [PATCH 009/111] wip... --- src/SeismicWaves.jl | 19 ++-- src/checks.jl | 13 +-- src/models/acoustic/acou_models.jl | 12 +-- src/models/backend_selection.jl | 65 +++++++++++ .../backends/Elastic2D_Iso_CPML_Serial.jl | 35 +----- src/models/elastic/ela_forward.jl | 4 +- src/models/elastic/ela_material_properties.jl | 65 +++++++++-- src/models/elastic/ela_models.jl | 101 +++++++++--------- src/sources.jl | 2 +- src/wrappers.jl | 76 +++---------- 10 files changed, 221 insertions(+), 171 deletions(-) create mode 100644 src/models/backend_selection.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 25e5b69..f911197 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -9,21 +9,25 @@ using ParallelStencil using Logging using DocStringExtensions +# main struct for wave simulation +export WaveSimul +export build_wavesim +# input parameters export InputParametersAcoustic, InputParametersAcousticVariableDensity +# boundary conditions export CPMLBoundaryConditionParameters, ReflectiveBoundaryConditionParameters +# material properties export VpAcousticCDMaterialProperty, VpRhoAcousticVDMaterialProperty -export WaveSimul - -#export Sources, Receivers, Shot +# export sources, receivers and shots export Shot -export ScalarSources, ScalarReceivers -export MomentTensorSources, VectorReceivers +export ScalarSources, MomentTensorSources, +export ScalarReceivers, VectorReceivers +# forward, misfit and gradient functions export swforward!, swmisfit!, swgradient! -export build_wavesim +# source time functions export gaussstf, gaussderivstf, rickerstf - include("abstract_types.jl") include("input_params.jl") @@ -39,6 +43,7 @@ include("checks.jl") include("boundarycond.jl") include("models/cpmlcoeffs.jl") +include("models/backend_selection.jl") include("models/acoustic/acou_abstract_types.jl") include("models/acoustic/acou_material_properties.jl") diff --git a/src/checks.jl b/src/checks.jl index 9c35f07..5df0d1b 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -25,11 +25,12 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s tyreceiver <: ScalarReceivers return - elseif tysim==ElasticIsoCPMLWaveSimul{N} && - tymatprop==MomentTensor2DSources && - tysource<:MomentTensor2DSources && - tyreceiver<:MomentTensor2DSources + elseif tysim==ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< + tymatprop==ElasticIsoMaterialProperty{2} && + tysource <: MomentTensorSources && + tyreceiver <: VectorReceivers return + end return error("Types of WaveSimul, MaterialProperties and Sources/Receivers are incosistent \ @@ -59,7 +60,7 @@ function check_positions( Ndim = size(positions, 2) for s in axes(positions, 1) for c in 1:Ndim - @assert (0 <= positions[s, c] <= model.ls[c]) "Position $(positions[s,:]) is not inside the grid!" + @assert (0 <= positions[s, c] <= model.domainextent[c]) "Position $(positions[s,:]) is not inside the grid!" end end return @@ -79,7 +80,7 @@ function check_positions( @assert ( model.gridspacing[c] * model.halo <= positions[s, c] <= - model.ls[c] - (model.gridspacing[c] * model.halo) + model.domainextent[c] - (model.gridspacing[c] * model.halo) ) "Position $(positions[s,:]) is inside the CPML region!" end end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 967c7da..a0d869a 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -61,7 +61,7 @@ end struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} # Physics - ls::NTuple{N, <:Real} + domainextent::NTuple{N, <:Real} # Numerics ns::NTuple{N, <:Integer} gridspacing::NTuple{N, <:Real} @@ -139,7 +139,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Compute model sizes - ls = gridspacing .* (ns .- 1) + domainextent = gridspacing .* (ns .- 1) # Initialize material properties matprop = VpAcousticCDMaterialProperty(zeros(ns...)) @@ -238,7 +238,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} end return new( - ls, + domainextent, ns, gridspacing, nt, @@ -374,7 +374,7 @@ end struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} # Physics - ls::NTuple{N, <:Real} + domainextent::NTuple{N, <:Real} # Numerics ns::NTuple{N, <:Integer} gridspacing::NTuple{N, <:Real} @@ -452,7 +452,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Compute model sizes - ls = gridspacing .* (ns .- 1) + domainextent = gridspacing .* (ns .- 1) # Initialize material properties matprop = VpRhoAcousticVDMaterialProperty(zeros(ns...), zeros(ns...)) @@ -564,7 +564,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} end return new( - ls, + domainextent, ns, gridspacing, nt, diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl new file mode 100644 index 0000000..a706599 --- /dev/null +++ b/src/models/backend_selection.jl @@ -0,0 +1,65 @@ + + +select_backend(wavesim_type::Type{<:WaveSimul}, parall::Symbol) = + select_backend(BoundaryConditionTrait(wavesim_type), GridTrait(wavesim_type), wavesim_type, Val{parall}) + +function select_backend( + ::BoundaryConditionTrait, + ::GridTrait, + wavesim_type::Type{<:WaveSimul}, + ::Type{Val{parall}} +) where {parall} + parasym = [:serial, :threads, :GPU, :threadpersrc] + error( + "No backend found for model of type $(wavesim_type) and `parall` $(parall). Argument `parall` must be one of the following symbols: $parasym." + ) +end + +## Remark: +## CD = constant density +## VD = variable density + +# Backend selections for AcousticCDCPMLWaveSimul +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:serial}}) = + Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:serial}}) = + Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:serial}}) = + Acoustic3D_CD_CPML_Serial + +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = + Acoustic1D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = + Acoustic2D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threads}}) = + Acoustic3D_CD_CPML_Threads + +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = + Acoustic1D_CD_CPML_GPU +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = + Acoustic2D_CD_CPML_GPU +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:GPU}}) = + Acoustic3D_CD_CPML_GPU + +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threadpersrc}}) = + Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threadpersrc}}) = + Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threadpersrc}}) = + Acoustic3D_CD_CPML_Serial + +# Backend selections for AcousticVDStaggeredCPMLWaveSimul +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = + Acoustic1D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = + Acoustic1D_VD_CPML_GPU + +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = + Acoustic2D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = + Acoustic2D_VD_CPML_GPU + + +# Backend selections for ElasticIsoWaveSimul +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimul{2}}, ::Type{Val{:serial}}) = + Elastic2D_Iso_CPML_Serial diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 4591f29..31d1de5 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -89,36 +89,6 @@ zeros = Base.zeros -function precomp_elaprop!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; - harmonicaver_μ=true) - - #------------------------------------------------------------- - # pre-interpolate properties at half distances between nodes - #------------------------------------------------------------- - # ρ_ihalf_jhalf (nx-1,nz-1) ?? - # arithmetic mean for ρ - @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ - ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 - # μ_ihalf (nx-1,nz) ?? - # μ_ihalf (nx,nz-1) ?? - if harmonicaver_μ==true - # harmonic mean for μ - @. μ_ihalf = 1.0 / ( 1.0/μ[2:end,:] + 1.0 / μ[1:end-1,:] ) - @. μ_jhalf = 1.0 / ( 1.0/μ[:,2:end] + 1.0 / μ[:,1:end-1] ) - else - # arithmetic mean for μ - @. μ_ihalf = (μ[2:end,:] + μ[1:end-1,:]) / 2.0 - @. μ_jhalf = (μ[:,2:end] + μ[:,1:end-1]) / 2.0 - end - # λ_ihalf (nx-1,nz) ?? - # arithmetic mean for λ - @. λ_ihalf = (λ[2:end,:] + λ[1:end-1,:]) / 2.0 - - return -end - - - function update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, freetop) if freetop @@ -440,6 +410,7 @@ end function forward_onestep_CPML!(wavsim::ElasticIsoWaveSimul{N}, + matprop::ElasticIsoMaterialProperty{N}, possrcs_a::Array{<:Integer,2}, srctf_a::Matrix{<:Real}, posrecs_a::Array{<:Integer,2}, @@ -448,6 +419,8 @@ function forward_onestep_CPML!(wavsim::ElasticIsoWaveSimul{N}, freetop::Bool, save_trace::Bool) where {N} + @assert N==2 + vx = wavsim.velpartic.vx vz = wavsim.velpartic.vz σxx = wavsim.stress.σxx @@ -477,7 +450,7 @@ function forward_onestep_CPML!(wavsim::ElasticIsoWaveSimul{N}, Mzz = wavsim.momtens.Mzz Mxz = wavsim.momtens.Mxz - ## + ## pre-scale coefficients factx = 1.0/(24.0*dx) factz = 1.0/(24.0*dz) diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index c06c59a..e9e200a 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -4,8 +4,8 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC @views function swforward_1shot!( ::CPMLBoundaryCondition, wavsim::ElasticIsoWaveSimul{N}, - possrcs, - posrecs, + possrcs::Matrix{<:Integer}, + posrecs::Matrix{<:Integer}, srctf, recs ) where {N} diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index c3896ca..38f4fb1 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -6,13 +6,62 @@ Base.@kwdef struct ElasticIsoMaterialProperty{N} <: MaterialProperties{N} end +# Material properties for 2D simulations +Base.@kwdef struct ElasticIsoMaterialProperty2D <: ElasticIsoMaterialProperty{2} + λ::Array{<:AbstractFloat,2} + μ::Array{<:AbstractFloat,2} + ρ::Array{<:AbstractFloat,2} + λ_ihalf::Array{<:AbstractFloat,2} + μ_ihalf::Array{<:AbstractFloat,2} + μ_jhalf::Array{<:AbstractFloat,2} + ρ_ihalf_jhalf::Array{<:AbstractFloat,2} + + # function ElasticIsoMaterialProperty{N}(ρ::Array{<:AbstractFloat, N}, + # μ::Array{<:AbstractFloat, N}, + # λ::Array{<:AbstractFloat, N}) where {N} -Base.@kwdef struct ElasticIsoMaterialProperty_Compute2D{N} <: MaterialProperties{N} - λ::Array{<:AbstractFloat, N} - μ::Array{<:AbstractFloat, N} - ρ::Array{<:AbstractFloat, N} - λ_ihalf::Array{<:AbstractFloat, N} - μ_ihalf::Array{<:AbstractFloat, N} - μ_jhalf::Array{<:AbstractFloat, N} - ρ_ihalf_jhalf::Array{<:AbstractFloat, N} + # @assert ndims(λ)==2 + # nx,ny = size(λ) + # tyrho = eltype(λ) + # ρ_ihalf_jhalf = zeros(tyrho,nx-1,ny-1) + # μ_ihalf = zeros(tyrho,nx-1,ny) + # μ_jhalf = zeros(tyrho,nx, ny-1) + # λ_ihalf = zeros(tyrho,nx-1,ny) + # precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; + # harmonicaver_μ=true) + + # return new{N}(λ,μ,ρ,λ_ihalf,μ_ihalf,μ_jhalf,ρ_ihalf_jhalf) + # end +end + + + +function precomp_elaprop!(matprop::ElasticIsoMaterialProperty{2}; harmonicaver_μ=true) + +# function precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; +# harmonicaver_μ=true) + + #------------------------------------------------------------- + # pre-interpolate properties at half distances between nodes + #------------------------------------------------------------- + # ρ_ihalf_jhalf (nx-1,nz-1) ?? + # arithmetic mean for ρ + @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ + ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 + # μ_ihalf (nx-1,nz) ?? + # μ_ihalf (nx,nz-1) ?? + if harmonicaver_μ==true + # harmonic mean for μ + @. μ_ihalf = 1.0 / ( 1.0/μ[2:end,:] + 1.0 / μ[1:end-1,:] ) + @. μ_jhalf = 1.0 / ( 1.0/μ[:,2:end] + 1.0 / μ[:,1:end-1] ) + else + # arithmetic mean for μ + @. μ_ihalf = (μ[2:end,:] + μ[1:end-1,:]) / 2.0 + @. μ_jhalf = (μ[:,2:end] + μ[:,1:end-1]) / 2.0 + end + # λ_ihalf (nx-1,nz) ?? + # arithmetic mean for λ + @. λ_ihalf = (λ[2:end,:] + λ[1:end-1,:]) / 2.0 + + return end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 1426ba0..85a2258 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -6,7 +6,7 @@ # Checks vp = sqrt((matprop.λ .+ 2.*matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(vp) == wavsim.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(wavsim.ns)" + @assert size(vp) == wavsim.gridsize "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(wavsim.gridsize)" @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" @assert all(matprop.ρ .> 0) "Density must be positive!" @@ -35,6 +35,7 @@ function check_numerics( ppw = vel_min / shot.srcs.domfreq / h_max @debug "Points per wavelength: $(ppw)" @assert ppw >= min_ppw "Not enough points per wavelengh!" + return end @@ -46,10 +47,7 @@ end wavsim.matprop.ρ .= matprop.ρ # the following on device? - precomp_elaprop!(wavsim.matprop.ρ,wavsim.matprop.μ,wavsim.matprop.λ, - wavsim.matprop.ρ_ihalf_jhalf, - wavsim.matprop.μ_ihalf,wavsim.matprop.μ_jhalf, - wavsim.matprop.λ_ihalf) + precomp_elaprop!(wavsim.matprop) return end @@ -64,7 +62,7 @@ end ########################################################### -struct Elasticψdomain2D{T<:AstractFloat} +struct Elasticψdomain2D{T<:AbstractFloat} ψ_∂σxx∂x::Array{T,2} ψ_∂σxz∂z::Array{T,2} ψ_∂σxz∂x::Array{T,2} @@ -74,19 +72,19 @@ struct Elasticψdomain2D{T<:AstractFloat} ψ_∂vz∂x::Array{T,2} ψ_∂vx∂z::Array{T,2} - function Elasticψdomain2D(backend,ns,N,halo) + function Elasticψdomain2D(backend,gridsize,N,halo) - ψ_ns = [ns...] - ψ_ns[N] = 2*halo + ψ_gridsize = [gridsize...] + ψ_gridsize[N] = 2*halo - ψ_∂σxx∂x = backend.zeros(ψ_ns...) - ψ_∂σxz∂z = backend.zeros(ψ_ns...) - ψ_∂σxz∂x = backend.zeros(ψ_ns...) - ψ_∂σzz∂z = backend.zeros(ψ_ns...) - ψ_∂vx∂x = backend.zeros(ψ_ns...) - ψ_∂vz∂z = backend.zeros(ψ_ns...) - ψ_∂vz∂x = backend.zeros(ψ_ns...) - ψ_∂vx∂z = backend.zeros(ψ_ns...) + ψ_∂σxx∂x = backend.zeros(ψ_gridsize...) + ψ_∂σxz∂z = backend.zeros(ψ_gridsize...) + ψ_∂σxz∂x = backend.zeros(ψ_gridsize...) + ψ_∂σzz∂z = backend.zeros(ψ_gridsize...) + ψ_∂vx∂x = backend.zeros(ψ_gridsize...) + ψ_∂vz∂z = backend.zeros(ψ_gridsize...) + ψ_∂vz∂x = backend.zeros(ψ_gridsize...) + ψ_∂vx∂z = backend.zeros(ψ_gridsize...) T = eltype(ψ_∂σxx∂x) return new{T}(ψ_∂σxx∂x, @@ -120,9 +118,9 @@ end struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Physics - ls::NTuple{N, <:Real} + domainextent::NTuple{N, <:Real} # Numerics - ns::NTuple{N, <:Integer} + gridsize::NTuple{N, <:Integer} gridspacing::NTuple{N, <:Real} nt::Integer dt::Real @@ -159,11 +157,12 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} function ElasticIsoCPMLWaveSimul{N}( - ns::NTuple{N, <:Integer}, + gridsize::NTuple{N, <:Integer}, gridspacing::NTuple{N, <:Real}, nt::Integer, dt::Real, halo::Integer, + rcoef::Real; parall::Symbol=:threads, freetop::Bool=true, gradient::Bool=false, @@ -172,28 +171,28 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} infoevery::Union{<:Integer, Nothing}=nothing ) where {N} # Check numerics - @assert all(ns .> 0) "All numbers of grid points must be positive!" - @assert all(gridspacing .> 0) "All cell sizes must be positive!" + @assert all(gridsize .> 0) "All numbers of grid points must be positive!" + @assert all(gridspacing .> 0) "All grid spacings must be positive!" @assert nt > 0 "Number of timesteps must be positive!" @assert dt > 0 "Timestep size must be positive!" # Check BDC parameters @assert halo >= 0 "CPML halo size must be non-negative!" - ns_cpml = freetop ? ns[1:(end-1)] : ns - @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" + gridsize_cpml = freetop ? gridsize[1:(end-1)] : gridsize + @assert all(n -> n >= 2halo + 3, gridsize_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Compute wavsim sizes - ls = gridspacing .* (ns .- 1) + domainextent = gridspacing .* (gridsize .- 1) # Initialize material properties if N==2 - matprop = ElasticIsoMaterialProperty_Compute2D(λ=backend.zeros(ns...), - μ=backend.zeros(ns...), - ρ=backend.zerons(ns...), - λ_ihalf=backend.zeros((ns.-1)...), - μ_ihalf=backend.zeros((ns.-[1,0])...), - μ_jhalf=backend.zeros((ns.-[0,1])...), - ρ_ihalf_jhalf=backend.zeros((ns.-1)...), - ) + matprop = ElasticIsoMaterialProperty2D(λ=backend.zeros(gridsize...), + μ=backend.zeros(gridsize...), + ρ=backend.zeros(gridsize...), + λ_ihalf=backend.zeros((gridsize.-1)...), + μ_ihalf=backend.zeros((gridsize.-[1,0])...), + μ_jhalf=backend.zeros((gridsize.-[0,1])...), + ρ_ihalf_jhalf=backend.zeros((gridsize.-1)...) + ) else error("Only elastic 2D is currently implemented.") @@ -204,13 +203,13 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Initialize computational arrays if N==2 - velpartic = Velpartic2D([backend.zeros(ns...) for _ in 1:N]...) # vx, vy[, vz] - stress = Stress2D([backend.zeros(ns...) for _ in 1:(N-1)*3]...) # vx, vy[, vz] + velpartic = Velpartic2D([backend.zeros(gridsize...) for _ in 1:N]...) # vx, vy[, vz] + stress = Stress2D([backend.zeros(gridsize...) for _ in 1:(N-1)*3]...) # vx, vy[, vz] end ## if N==2 # 2D - ψ = Elasticψdomain2D(backend,ns,N,halo) + ψ = Elasticψdomain2D(backend,gridsize,N,halo) else error("Only elastic 2D is currently implemented.") end @@ -223,19 +222,19 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} error("Gradient for elastic calculations not yet implemented!") # # Current gradient array - # curgrad = backend.zeros(ns...) + # curgrad = backend.zeros(gridsize...) # # Adjoint arrays - # adj = backend.zeros(ns...) + # adj = backend.zeros(gridsize...) # # Initialize CPML arrays # ψ_adj = [] # ξ_adj = [] # for i in 1:N - # ψ_ns = [ns...] - # ξ_ns = [ns...] - # ψ_ns[i] = halo + 1 - # ξ_ns[i] = halo - # append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - # append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + # ψ_gridsize = [gridsize...] + # ξ_gridsize = [gridsize...] + # ψ_gridsize[i] = halo + 1 + # ξ_gridsize[i] = halo + # append!(ψ_adj, [backend.zeros(ψ_gridsize...), backend.zeros(ψ_gridsize...)]) + # append!(ξ_adj, [backend.zeros(ξ_gridsize...), backend.zeros(ξ_gridsize...)]) # end # # Checkpointing setup # if check_freq !== nothing @@ -244,7 +243,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # # Time step of last checkpoint # last_checkpoint = floor(Int, nt / check_freq) * check_freq # # Checkpointing arrays - # save_buffer = backend.zeros(ns..., check_freq + 2) # pressure window buffer + # save_buffer = backend.zeros(gridsize..., check_freq + 2) # pressure window buffer # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints @@ -256,15 +255,15 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # # Preallocate future checkpoints # for it in 1:(nt+1) # if it % check_freq == 0 - # checkpoints[it] = backend.zeros(ns...) - # checkpoints[it-1] = backend.zeros(ns...) + # checkpoints[it] = backend.zeros(gridsize...) + # checkpoints[it-1] = backend.zeros(gridsize...) # checkpoints_ψ[it] = copy.(ψ) # checkpoints_ξ[it] = copy.(ξ) # end # end # else # no checkpointing # last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) - # save_buffer = backend.zeros(ns..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) + # save_buffer = backend.zeros(gridsize..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) @@ -275,7 +274,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} end # Initialize snapshots array - snapshots = (snapevery !== nothing ? [zeros(ns..., div(nt, snapevery)) for _ in 1:N] : nothing) + snapshots = (snapevery !== nothing ? [zeros(gridsize..., div(nt, snapevery)) for _ in 1:N] : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -284,8 +283,8 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} end return new( - ls, - ns, + domainextent, + gridsize, gridspacing, nt, dt, diff --git a/src/sources.jl b/src/sources.jl index 336d40f..d9604cf 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -34,7 +34,7 @@ Default type constructor for Float64. """ ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, domfreq) -####################################################33 +#################################################### """ Type representing a 2D moment tensor. diff --git a/src/wrappers.jl b/src/wrappers.jl index a126ea5..417a884 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -332,63 +332,21 @@ build_concrete_wavesim( kwargs... ) -####################################################### - -select_backend(wavesim_type::Type{<:WaveSimul}, parall::Symbol) = - select_backend(BoundaryConditionTrait(wavesim_type), GridTrait(wavesim_type), wavesim_type, Val{parall}) - -function select_backend( - ::BoundaryConditionTrait, - ::GridTrait, - wavesim_type::Type{<:WaveSimul}, - ::Type{Val{parall}} -) where {parall} - parasym = [:serial, :threads, :GPU, :threadpersrc] - error( - "No backend found for model of type $(wavesim_type) and `parall` $(parall). Argument `parall` must be one of the following symbols: $parasym." - ) -end +build_concrete_wavesim( + params::InputParametersElasticIso{N}, + cpmlparams::CPMLBoundaryConditionParameters; + parall, + kwargs... +) where {N} = ElasticIsoCPMLWaveSimul{N}( + params.gridsize, + params.gridspacing, + params.ntimesteps, + params.dt, + cpmlparams.halo, + cpmlparams.rcoef; + freetop=cpmlparams.freeboundtop, + parall, + kwargs... +) -## Remark: -## CD = constant density -## VD = variable density - -# Backend selections for AcousticCDCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:serial}}) = - Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:serial}}) = - Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:serial}}) = - Acoustic3D_CD_CPML_Serial - -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = - Acoustic1D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = - Acoustic2D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threads}}) = - Acoustic3D_CD_CPML_Threads - -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = - Acoustic1D_CD_CPML_GPU -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = - Acoustic2D_CD_CPML_GPU -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:GPU}}) = - Acoustic3D_CD_CPML_GPU - -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threadpersrc}}) = - Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threadpersrc}}) = - Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threadpersrc}}) = - Acoustic3D_CD_CPML_Serial - -# Backend selections for AcousticVDStaggeredCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = - Acoustic1D_VD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = - Acoustic1D_VD_CPML_GPU - -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = - Acoustic2D_VD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = - Acoustic2D_VD_CPML_GPU +####################################################### From 3b6d50d7b3cc298cf7b2affb63abb8bd8d3e94b2 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Tue, 9 Jan 2024 17:26:19 +0100 Subject: [PATCH 010/111] updates... --- src/SeismicWaves.jl | 2 +- src/models/cpmlcoeffs.jl | 2 +- .../backends/Elastic2D_Iso_CPML_Serial.jl | 16 ++++++---------- src/models/elastic/ela_forward.jl | 10 +++++++--- src/receivers.jl | 12 ++++++------ 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index f911197..531e7af 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -20,7 +20,7 @@ export CPMLBoundaryConditionParameters, ReflectiveBoundaryConditionParameters export VpAcousticCDMaterialProperty, VpRhoAcousticVDMaterialProperty # export sources, receivers and shots export Shot -export ScalarSources, MomentTensorSources, +export ScalarSources, MomentTensorSources export ScalarReceivers, VectorReceivers # forward, misfit and gradient functions export swforward!, swmisfit!, swgradient! diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 4d9c91a..8319ba0 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -26,7 +26,7 @@ struct CPMLCoefficientsAxis end function compute_CPML_coefficientsAxis!( - cpmlcoeffs::CPMLCoefficients, + cpmlcoeffs::CPMLCoefficientsAxis, vel_max::Real, dt::Real, halo::Integer, diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 31d1de5..4e82c17 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -156,15 +156,14 @@ function update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) end - end - + end return end -function update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z,b_x_half,b_z_half, - a_x_half,a_z_half,freetop) +function update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, + b_x_half,b_z_half,a_x_half,a_z_half,freetop) if freetop for j = 1:2 @@ -232,7 +231,6 @@ function update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ end end - return end @@ -403,7 +401,6 @@ function update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z end end - return end @@ -470,7 +467,8 @@ function forward_onestep_CPML!(wavsim::ElasticIsoWaveSimul{N}, # inject sources - inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_a, dt, possrcs, it) + inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_a, dt, possrcs, it) + # record receivers if save_trace record_receivers!(vx,vz,traces_a, posrecs, it) @@ -495,8 +493,7 @@ function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_a, dt, possrcs, it) σxz[isrc,jsrc] += Mxz[s] * srctf_a[it] * dt end - end - + end return end @@ -517,7 +514,6 @@ end function correlate_gradient!( ) - # _dt2 = 1 / dt^2 # nx, nz = size(curgrad) # for j in 1:nz diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index e9e200a..d3753cf 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -46,11 +46,15 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Print timestep info if it % wavsim.infoevery == 0 + # # Move the cursor to the beginning to overwrite last line + # ter = REPL.Terminals.TTYTerminal("", stdin, stdout, stderr) + # REPL.Terminals.clear_line(ter) + # REPL.Terminals.cmove_line_up(ter) @debug @sprintf( - "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", + "Iteration: %d, simulation time: %g [s]", it, - wavsim.dt * (it - 1), - maximum(abs.(Array(pcur))) + wavsim.dt * (it - 1) + ) ) end diff --git a/src/receivers.jl b/src/receivers.jl index c6a4fa2..a8ed2f9 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -74,10 +74,10 @@ ScalarReceivers(positions, nt; observed=nothing, invcov=nothing, windows=nothing @doc raw""" Type representing a multi-receiver configuration for a wave propagation shot. """ -# The following using the package ComputedFieldTypes.jl -@computed struct VectorReceivers{N,T<:Real} <: Receivers - positions::Matrix{<:Real} - seismograms::Array{N+1} +# What about using the package ComputedFieldTypes.jl? @computed ... +struct VectorReceivers{N,T<:Real} <: Receivers + positions::Matrix{T} + seismograms::Array{T} observed::Matrix{T} invcov::AbstractMatrix{T} @@ -94,7 +94,7 @@ Type representing a multi-receiver configuration for a wave propagation shot. invcov::Union{AbstractMatrix{T}, Nothing}=nothing ) where {N,T <: Real} @assert size(positions, 1) > 0 "There must be at least one receiver!" - seismograms = zeros(T, nt, N, size(positions, 1)) + seismograms = zeros(T, nt, ndim, size(positions, 1)) ## N+1 !!! <<<<<<<<--------------<<<< if observed !== nothing @assert size(seismograms) == size(observed) "Size of observed data is not (# timesteps, # receivers)!" else @@ -105,7 +105,7 @@ Type representing a multi-receiver configuration for a wave propagation shot. else invcov = nothing end - return new{N,T}(positions, seismograms, observed, invcov) + return new{ndim,T}(positions, seismograms, observed, invcov) end end From 24218fd373ccbbdea28568f4aab4911db4771493 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Wed, 10 Jan 2024 15:19:09 +0100 Subject: [PATCH 011/111] new arg in build_wavesim --- src/SeismicWaves.jl | 25 +++++++- src/input_params.jl | 14 ----- src/models/acoustic/acou_params.jl | 62 +++++++++---------- src/models/elastic/ela_abstract_types.jl | 2 + src/models/elastic/ela_forward.jl | 1 - src/models/elastic/ela_material_properties.jl | 6 +- src/models/elastic/ela_models.jl | 24 +++---- src/wrappers.jl | 13 ++-- 8 files changed, 79 insertions(+), 68 deletions(-) delete mode 100644 src/input_params.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 531e7af..9e2ecc9 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -30,7 +30,6 @@ export gaussstf, gaussderivstf, rickerstf include("abstract_types.jl") -include("input_params.jl") include("traits/boundarycondition.jl") include("traits/shooting.jl") include("traits/snappable.jl") @@ -43,8 +42,8 @@ include("checks.jl") include("boundarycond.jl") include("models/cpmlcoeffs.jl") -include("models/backend_selection.jl") +# Acoustic include("models/acoustic/acou_abstract_types.jl") include("models/acoustic/acou_material_properties.jl") include("models/acoustic/acou_models.jl") @@ -53,10 +52,26 @@ include("models/acoustic/acou_forward.jl") include("models/acoustic/acou_gradient.jl") include("models/acoustic/acou_init_bc.jl") +# Elastic +include("models/elastic/ela_abstract_types.jl") +include("models/elastic/ela_material_properties.jl") +include("models/elastic/ela_models.jl") +include("models/elastic/ela_params.jl") +include("models/elastic/ela_forward.jl") +#include("models/elastic/ela_gradient.jl") +include("models/elastic/ela_init_bc.jl") + + +# Backend selection +include("models/backend_selection.jl") +# Misfit include("misfits.jl") +# Generic solve include("solve.jl") +# Main functions include("wrappers.jl") +# Acoustic backends include("models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl") include("models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl") include("models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl") @@ -83,6 +98,12 @@ include("models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl") ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") + +# Elastic backends +include("models/acoustic/backends/Elastic2D_Iso_CPML_Serial.jl") + + +# Utils include("utils.jl") diff --git a/src/input_params.jl b/src/input_params.jl deleted file mode 100644 index 3d15bc7..0000000 --- a/src/input_params.jl +++ /dev/null @@ -1,14 +0,0 @@ - -""" -Reflective boundary conditions parameters for wave simulations -""" -Base.@kwdef struct ReflectiveBoundaryConditionParameters <: InputBoundaryConditionParameters end - -""" -CPML boundary conditions parameters for wave simulations -""" -Base.@kwdef struct CPMLBoundaryConditionParameters <: InputBoundaryConditionParameters - halo::Int = 20 - rcoef::Real = 0.0001 - freeboundtop::Bool = true -end diff --git a/src/models/acoustic/acou_params.jl b/src/models/acoustic/acou_params.jl index b41b50a..b83a3ee 100644 --- a/src/models/acoustic/acou_params.jl +++ b/src/models/acoustic/acou_params.jl @@ -35,40 +35,40 @@ function InputParametersAcoustic( return InputParametersAcoustic{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) end -@doc """ -$(TYPEDEF) +# @doc """ +# $(TYPEDEF) -Parameters for variable-density acoustic wave simulations. +# Parameters for variable-density acoustic wave simulations. -$(TYPEDFIELDS) -""" -struct InputParametersAcousticVariableDensity{N} <: InputParameters{N} - "Number of time steps" - ntimesteps::Int - "Time step" - dt::Real - "Grid size for each dimension" - gridsize::NTuple{N, <:Int} - "Grid spacing in each direction" - gridspacing::NTuple{N, <:Real} - "Kind of boundary conditions" - boundcond::InputBoundaryConditionParameters -end +# $(TYPEDFIELDS) +# """ +# struct InputParametersAcousticVariableDensity{N} <: InputParameters{N} +# "Number of time steps" +# ntimesteps::Int +# "Time step" +# dt::Real +# "Grid size for each dimension" +# gridsize::NTuple{N, <:Int} +# "Grid spacing in each direction" +# gridspacing::NTuple{N, <:Real} +# "Kind of boundary conditions" +# boundcond::InputBoundaryConditionParameters +# end -function InputParametersAcousticVariableDensity( - ntimesteps::Int, - dt::Real, - gridsize::AbstractVector{<:Int}, - gridspacing::AbstractVector{<:Real}, - boundcond::InputBoundaryConditionParameters -) - # Check dimensionality - N = length(gridsize) - @assert N == length(gridspacing) "Dimensionality mismatch between number of grid points and grid step sizes!" - @assert N > 0 "Dimensionality must positive!" - @assert N <= 3 "Dimensionality must be less than or equal to 3!" +# function InputParametersAcousticVariableDensity( +# ntimesteps::Int, +# dt::Real, +# gridsize::AbstractVector{<:Int}, +# gridspacing::AbstractVector{<:Real}, +# boundcond::InputBoundaryConditionParameters +# ) +# # Check dimensionality +# N = length(gridsize) +# @assert N == length(gridspacing) "Dimensionality mismatch between number of grid points and grid step sizes!" +# @assert N > 0 "Dimensionality must positive!" +# @assert N <= 3 "Dimensionality must be less than or equal to 3!" - return InputParametersAcousticVariableDensity{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) -end +# return InputParametersAcousticVariableDensity{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) +# end diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index 0e5d254..bd00d32 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -2,3 +2,5 @@ abstract type ElasticWaveSimul{N} <: WaveSimul{N} end abstract type ElasticIsoWaveSimul{N} <: ElasticWaveSimul{N} end + +abstract type ElasticMaterialProperties{N} <: MaterialProperties{N} end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index d3753cf..f2fdebb 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -54,7 +54,6 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC "Iteration: %d, simulation time: %g [s]", it, wavsim.dt * (it - 1) - ) ) end diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index 38f4fb1..0dc2c09 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -1,5 +1,5 @@ -Base.@kwdef struct ElasticIsoMaterialProperty{N} <: MaterialProperties{N} +Base.@kwdef struct ElasticIsoMaterialProperties{N} <: ElasticMaterialProperties{N} λ::Array{<:AbstractFloat, N} μ::Array{<:AbstractFloat, N} ρ::Array{<:AbstractFloat, N} @@ -7,7 +7,7 @@ end # Material properties for 2D simulations -Base.@kwdef struct ElasticIsoMaterialProperty2D <: ElasticIsoMaterialProperty{2} +Base.@kwdef struct ElasticIsoMaterialProperties2D <: ElasticMaterialProperties{2} λ::Array{<:AbstractFloat,2} μ::Array{<:AbstractFloat,2} ρ::Array{<:AbstractFloat,2} @@ -36,7 +36,7 @@ end -function precomp_elaprop!(matprop::ElasticIsoMaterialProperty{2}; harmonicaver_μ=true) +function precomp_elaprop!(matprop::ElasticIsoMaterialProperties{2}; harmonicaver_μ=true) # function precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; # harmonicaver_μ=true) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 85a2258..469b975 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,9 +2,9 @@ # Functions for all ElasticIsoWaveSimul subtypes -@views function check_matprop(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} +@views function check_matprop(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperties{N}) where {N} # Checks - vp = sqrt((matprop.λ .+ 2.*matprop.μ) ./ matprop.ρ) + vp = sqrt((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(vp) == wavsim.gridsize "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(wavsim.gridsize)" @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @@ -39,7 +39,7 @@ function check_numerics( end -@views function update_matprop!(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperty{N}) where {N} +@views function update_matprop!(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperties{N}) where {N} # Update material properties wavsim.matprop.λ .= matprop.λ @@ -136,7 +136,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Logging parameters infoevery::Integer # Material properties - matprop::ElasticIsoMaterialProperty + matprop::ElasticIsoMaterialProperties # Forward computation arrays velpartic::Any # 2D: 2 comp, 3D: 3 comp stress::Any # 2D: 3 arrays, 3D: 6 arrays @@ -185,14 +185,14 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} domainextent = gridspacing .* (gridsize .- 1) # Initialize material properties if N==2 - matprop = ElasticIsoMaterialProperty2D(λ=backend.zeros(gridsize...), - μ=backend.zeros(gridsize...), - ρ=backend.zeros(gridsize...), - λ_ihalf=backend.zeros((gridsize.-1)...), - μ_ihalf=backend.zeros((gridsize.-[1,0])...), - μ_jhalf=backend.zeros((gridsize.-[0,1])...), - ρ_ihalf_jhalf=backend.zeros((gridsize.-1)...) - ) + matprop = ElasticIsoMaterialProperties2D(λ=backend.zeros(gridsize...), + μ=backend.zeros(gridsize...), + ρ=backend.zeros(gridsize...), + λ_ihalf=backend.zeros((gridsize.-1)...), + μ_ihalf=backend.zeros((gridsize.-[1,0])...), + μ_jhalf=backend.zeros((gridsize.-[0,1])...), + ρ_ihalf_jhalf=backend.zeros((gridsize.-1)...) + ) else error("Only elastic 2D is currently implemented.") diff --git a/src/wrappers.jl b/src/wrappers.jl index 417a884..837bad4 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -214,7 +214,7 @@ function swgradient!( out = nothing with_logger(logger) do # Build wavesim - wavesim = build_wavesim(params; parall=parall, infoevery=infoevery, gradient=true, check_freq=check_freq, smooth_radius=smooth_radius) + wavesim = build_wavesim(params,matprop; parall=parall, infoevery=infoevery, gradient=true, check_freq=check_freq, smooth_radius=smooth_radius) # Solve simulation out = run_swgradient!(wavesim, matprop, shots; compute_misfit=compute_misfit, misfit=misfit) end @@ -285,13 +285,13 @@ Builds a wave similation based on the input paramters `params` and keyword argum - `snapevery::Union{<:Integer, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). - `infoevery::Union{<:Integer, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function build_wavesim(params::InputParameters; parall, kwargs...) +function build_wavesim(params::InputParameters, matprop::MaterialProperties; parall, kwargs...) if parall==:threadpersrc nthr = Threads.nthreads() #println(" build_wavesim :threadpersrc") - wsim = [build_concrete_wavesim(params, params.boundcond; parall, kwargs...) for s=1:nthr] + wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for s=1:nthr] else - wsim = build_concrete_wavesim(params, params.boundcond; parall, kwargs...) + wsim = build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) end return wsim end @@ -300,6 +300,7 @@ end build_concrete_wavesim( params::InputParametersAcoustic{N}, + ::VpAcousticCDMaterialProperty cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... @@ -317,6 +318,7 @@ build_concrete_wavesim( build_concrete_wavesim( params::InputParametersAcousticVariableDensity{N}, + ::VpRhoAcousticVDMaterialProperty, cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... @@ -333,7 +335,8 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersElasticIso{N}, + params::InputParametersElastic{N}, + ::ElasticIsoMaterialProperties, cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... From 918af77576849a4e5eed4e621242e247e4d36a99 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Wed, 10 Jan 2024 17:53:06 +0100 Subject: [PATCH 012/111] work in prog... breaking changes --- examples/forward_example.jl | 2 +- .../constant_density/gradient_check_fd.jl | 6 +++--- .../variable_density/gradient_check_fd.jl | 8 ++++---- examples/simple_example_acoustic.jl | 4 ++-- examples/simple_example_wavesim.jl | 4 ++-- src/HMCseiswaves.jl | 2 +- src/SeismicWaves.jl | 17 ++++++++++++----- src/checks.jl | 6 +++--- src/misfits.jl | 8 ++++---- .../acoustic/acou_material_properties.jl | 10 +++++----- src/models/acoustic/acou_models.jl | 16 ++++++++-------- src/models/backend_selection.jl | 2 +- .../backends/Elastic2D_Iso_CPML_Serial.jl | 14 +++++++++----- src/models/elastic/ela_abstract_types.jl | 1 + src/models/elastic/ela_material_properties.jl | 6 +++--- src/models/elastic/ela_models.jl | 19 +++++++++++-------- src/models/elastic/ela_params.jl | 13 +++++++++++-- src/wrappers.jl | 14 +++++++------- test/test_forward_constant_density.jl | 8 ++++---- test/utils/setup_models.jl | 10 +++++----- 20 files changed, 97 insertions(+), 73 deletions(-) diff --git a/examples/forward_example.jl b/examples/forward_example.jl index fd85ab1..9c1f57e 100644 --- a/examples/forward_example.jl +++ b/examples/forward_example.jl @@ -17,7 +17,7 @@ function forward_example() velmod[i, j] = 2000.0 + 12.0 * (j - 1) end end - matprop = VpAcousticCDMaterialProperty(velmod) + matprop = VpAcousticCDMaterialProperties(velmod) ##======================================== # shots definition nshots = 6 diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index 7712d3f..614a186 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -27,9 +27,9 @@ function setup(nt, c0, c0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) # create constant and gaussian velocity model lx = (nx - 1) * dx ly = (ny - 1) * dy - matprop_const = VpAcousticCDMaterialProperty(c0 .* ones(nx, ny)) + matprop_const = VpAcousticCDMaterialProperties(c0 .* ones(nx, ny)) # gaussian perturbed model - matprop_gauss = VpAcousticCDMaterialProperty(gaussian_vel_2D(nx, ny, c0, c0max, r)) + matprop_gauss = VpAcousticCDMaterialProperties(gaussian_vel_2D(nx, ny, c0, c0max, r)) ##======================================== # shots definition @@ -104,7 +104,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) println("Computing ($i, $j) gradient with FD") vp_perturbed = copy(matprop_const.vp) vp_perturbed[i, j] += dm - matprop_perturbed = VpAcousticCDMaterialProperty(vp_perturbed) + matprop_perturbed = VpAcousticCDMaterialProperties(vp_perturbed) @time new_misfit = with_logger(error_logger) do swmisfit!(wavesim, matprop_perturbed, shots_obs) end diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index 24c3f0d..0ae18c1 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -27,9 +27,9 @@ function setup(nt, c0, c0max, rho0, rho0max, r, dx, dy, dt, halo, rcoef, nx, ny, # create constant and gaussian velocity model lx = (nx - 1) * dx ly = (ny - 1) * dy - matprop_const = VpRhoAcousticVDMaterialProperty(c0 .* ones(nx, ny), rho0 .* ones(nx, ny)) + matprop_const = VpRhoAcousticVDMaterialProperties(c0 .* ones(nx, ny), rho0 .* ones(nx, ny)) # gaussian perturbed model - matprop_gauss = VpRhoAcousticVDMaterialProperty(gaussian_vel_2D(nx, ny, c0, c0max, r), gaussian_vel_2D(nx, ny, rho0, rho0max, r)) + matprop_gauss = VpRhoAcousticVDMaterialProperties(gaussian_vel_2D(nx, ny, c0, c0max, r), gaussian_vel_2D(nx, ny, rho0, rho0max, r)) ##======================================== # shots definition @@ -121,7 +121,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) println("Computing ($i, $j) gradient wrt vp with FD") vp_perturbed = copy(matprop_const.vp) vp_perturbed[i, j] += dm_vp - matprop_perturbed = VpRhoAcousticVDMaterialProperty(vp_perturbed, matprop_const.rho) + matprop_perturbed = VpRhoAcousticVDMaterialProperties(vp_perturbed, matprop_const.rho) @time new_misfit = with_logger(error_logger) do swmisfit!(wavesim, matprop_perturbed, shots_obs) end @@ -136,7 +136,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) println("Computing ($i, $j) gradient wrt rho with FD") rho_perturbed = copy(matprop_const.rho) rho_perturbed[i, j] += dm_rho - matprop_perturbed = VpRhoAcousticVDMaterialProperty(matprop_const.vp, rho_perturbed) + matprop_perturbed = VpRhoAcousticVDMaterialProperties(matprop_const.vp, rho_perturbed) @time new_misfit = with_logger(error_logger) do swmisfit!(wavesim, matprop_perturbed, shots_obs) end diff --git a/examples/simple_example_acoustic.jl b/examples/simple_example_acoustic.jl index e0c999d..73a06b1 100644 --- a/examples/simple_example_acoustic.jl +++ b/examples/simple_example_acoustic.jl @@ -39,7 +39,7 @@ function exacouprob(parall=:serial) # bottom = repeat(velmod[:, end:end], 1, npad) # velmod = hcat(velmod, bottom) - matprop = VpAcousticCDMaterialProperty(velmod) + matprop = VpAcousticCDMaterialProperties(velmod) ##======================================== # shots definition @@ -113,7 +113,7 @@ function exacouprob(parall=:serial) newvelmod = matprop.vp .- 0.2 newvelmod[30:40, 33:44] *= 0.9 - matprop_grad = VpAcousticCDMaterialProperty(newvelmod) + matprop_grad = VpAcousticCDMaterialProperties(newvelmod) @time grad = swgradient!(params, matprop_grad, diff --git a/examples/simple_example_wavesim.jl b/examples/simple_example_wavesim.jl index beeef19..b597680 100644 --- a/examples/simple_example_wavesim.jl +++ b/examples/simple_example_wavesim.jl @@ -41,7 +41,7 @@ function exacouprob_wavsim(parall=:serial) # bottom = repeat(velmod[:, end:end], 1, npad) # velmod = hcat(velmod, bottom) - matprop = VpAcousticCDMaterialProperty(velmod) + matprop = VpAcousticCDMaterialProperties(velmod) ##======================================== # shots definition @@ -138,7 +138,7 @@ function exacouprob_wavsim(parall=:serial) newvelmod = matprop.vp .- 0.2 newvelmod[30:40, 33:44] *= 0.9 - matprop_grad = VpAcousticCDMaterialProperty(newvelmod) + matprop_grad = VpAcousticCDMaterialProperties(newvelmod) ## check_freq = ceil(Int, sqrt(params.ntimesteps)) #nothing #200 #ceil(Int, sqrt(params.ntimesteps)) diff --git a/src/HMCseiswaves.jl b/src/HMCseiswaves.jl index c7cc1cd..8127084 100644 --- a/src/HMCseiswaves.jl +++ b/src/HMCseiswaves.jl @@ -69,7 +69,7 @@ function (acouprob::AcouWavCDProb)(vecvel::Vector{Float64}, kind::Symbol) # reshape vector to 2D array velNd = reshape(vecvel, acouprob.inpars.gridsize...) - matprop = VpAcousticCDMaterialProperty(velNd) + matprop = VpAcousticCDMaterialProperties(velNd) @assert length(acouprob.shots[1].recs.observed) != 0 diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 9e2ecc9..e58df0f 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -13,11 +13,12 @@ using DocStringExtensions export WaveSimul export build_wavesim # input parameters -export InputParametersAcoustic, InputParametersAcousticVariableDensity +export InputParametersAcoustic, InputParametersElastic # boundary conditions export CPMLBoundaryConditionParameters, ReflectiveBoundaryConditionParameters # material properties -export VpAcousticCDMaterialProperty, VpRhoAcousticVDMaterialProperty +export VpAcousticCDMaterialProperties, VpRhoAcousticVDMaterialProperties +export ElasticIsoMaterialProperties # export sources, receivers and shots export Shot export ScalarSources, MomentTensorSources @@ -71,11 +72,17 @@ include("solve.jl") # Main functions include("wrappers.jl") -# Acoustic backends + +# Acoustic serial backend include("models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl") include("models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl") include("models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl") +# Elastic serial backend +include("models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl") + + +# Acoustic parallel backends ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl") ParallelStencil.@reset_parallel_stencil() @@ -99,8 +106,8 @@ ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") -# Elastic backends -include("models/acoustic/backends/Elastic2D_Iso_CPML_Serial.jl") +# Elastic parallel backends + # Utils diff --git a/src/checks.jl b/src/checks.jl index 5df0d1b..58d9f67 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -15,18 +15,18 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s # Check that the subtypes of WaveSimul, MaterialProperties and Shot are consistent N = typeof(wavsim).parameters[1] if tysim == AcousticCDCPMLWaveSimul{N} && - tymatprop == VpAcousticCDMaterialProperty{N} && + tymatprop == VpAcousticCDMaterialProperties{N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return elseif tysim == AcousticVDStaggeredCPMLWaveSimul{N} && - tymatprop == VpRhoAcousticVDMaterialProperty{N} && + tymatprop == VpRhoAcousticVDMaterialProperties{N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return elseif tysim==ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< - tymatprop==ElasticIsoMaterialProperty{2} && + tymatprop==ElasticIsoMaterialProperties{2} && tysource <: MomentTensorSources && tyreceiver <: VectorReceivers return diff --git a/src/misfits.jl b/src/misfits.jl index 01cf012..620749e 100644 --- a/src/misfits.jl +++ b/src/misfits.jl @@ -44,14 +44,14 @@ Base.@kwdef struct ZerothOrderTikhonovRegularization{M <: MaterialProperties} <: alpha::Real end -function (regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperty{N}})(matprop::VpAcousticCDMaterialProperty{N}) where {N} +function (regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{N}})(matprop::VpAcousticCDMaterialProperties{N}) where {N} vp = matprop.vp vp_prior = regularization.matprop_prior.vp vp_norm_sq = norm(vp - vp_prior)^2 return regularization.alpha / 2 * vp_norm_sq end -function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperty{N}})(matprop::VpRhoAcousticVDMaterialProperty{N}) where {N} +function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{N}})(matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp @@ -61,13 +61,13 @@ function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMater return regularization.alpha / 2 * (vp_norm_sq + rho_norm_sq) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperty{N}}, matprop::VpAcousticCDMaterialProperty{N}) where {N} +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{N}}, matprop::VpAcousticCDMaterialProperties{N}) where {N} vp = matprop.vp vp_prior = regularization.matprop_prior.vp return regularization.alpha * (vp - vp_prior) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperty{N}}, matprop::VpRhoAcousticVDMaterialProperty{N}) where {N} +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{N}}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp diff --git a/src/models/acoustic/acou_material_properties.jl b/src/models/acoustic/acou_material_properties.jl index 87b852a..a414683 100644 --- a/src/models/acoustic/acou_material_properties.jl +++ b/src/models/acoustic/acou_material_properties.jl @@ -7,7 +7,7 @@ Material properties for acoustic constant-density simulation. $(TYPEDFIELDS) """ -struct VpAcousticCDMaterialProperty{N} <: MaterialProperties{N} +struct VpAcousticCDMaterialProperties{N} <: MaterialProperties{N} "P-wave velocity" vp::Array{<:Float64, N} end @@ -20,7 +20,7 @@ Material properties for acoustic variable-density simulation. $(TYPEDFIELDS) """ -mutable struct VpRhoAcousticVDMaterialProperty{N} <: MaterialProperties{N} +mutable struct VpRhoAcousticVDMaterialProperties{N} <: MaterialProperties{N} "P-wave velocity" vp::Array{<:Float64, N} "Density" @@ -29,7 +29,7 @@ mutable struct VpRhoAcousticVDMaterialProperty{N} <: MaterialProperties{N} interp_method::InterpolationMethod @doc """ - VpRhoAcousticVDMaterialProperty{N}( + VpRhoAcousticVDMaterialProperties{N}( vp::Array{<:Float64, N}, rho::Array{<:Float64, N}; interp_method::InterpolationMethod=ArithmeticAverageInterpolation(2) @@ -37,7 +37,7 @@ mutable struct VpRhoAcousticVDMaterialProperty{N} <: MaterialProperties{N} Constructor for material properties for acoustic variable-density simulation. """ - function VpRhoAcousticVDMaterialProperty{N}( + function VpRhoAcousticVDMaterialProperties{N}( vp::Array{<:Float64, N}, rho::Array{<:Float64, N}; interp_method::InterpolationMethod=ArithmeticAverageInterpolation(2) @@ -52,7 +52,7 @@ $(SIGNATURES) Constructor to avoid specifying dimensions to create material properties for acoustic variable-density simulation. """ -VpRhoAcousticVDMaterialProperty(vp, rho; kwargs...) = VpRhoAcousticVDMaterialProperty{length(size(vp))}(vp, rho; kwargs...) +VpRhoAcousticVDMaterialProperties(vp, rho; kwargs...) = VpRhoAcousticVDMaterialProperties{length(size(vp))}(vp, rho; kwargs...) interpolate(a::Array{<:Float64, N}, interp_method) where {N} = collect(interp(interp_method, a, i) for i in 1:N) interpolate_jacobian(a::Array{<:Float64, N}, interp_method) where {N} = collect(jacobian(interp_method, a, i) for i in 1:N) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index a0d869a..ff3ec25 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -39,7 +39,7 @@ end return scaled_tf end -@views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperty{N}) where {N} +@views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{N}) where {N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.ns)" @@ -48,7 +48,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperty{N}) where {N} +@views function update_matprop!(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{N}) where {N} # Update material properties copyto!(model.matprop.vp, matprop.vp) # Precompute factors @@ -83,7 +83,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} # Gradient smoothing parameters smooth_radius::Integer # Material properties - matprop::VpAcousticCDMaterialProperty + matprop::VpAcousticCDMaterialProperties # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} # Forward computation arrays @@ -141,7 +141,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} # Compute model sizes domainextent = gridspacing .* (ns .- 1) # Initialize material properties - matprop = VpAcousticCDMaterialProperty(zeros(ns...)) + matprop = VpAcousticCDMaterialProperties(zeros(ns...)) # Select backend backend = select_backend(AcousticCDCPMLWaveSimul{N}, parall) @@ -341,7 +341,7 @@ end return scaled_tf end -@views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperty{N}) where {N} +@views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == size(matprop.rho) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.ns)" @@ -351,7 +351,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperty{N}) where {N} +@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} # Update material properties copyto!(model.matprop.vp, matprop.vp) copyto!(model.matprop.rho, matprop.rho) @@ -396,7 +396,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} # Gradient smoothing parameters smooth_radius::Integer # Material properties - matprop::VpRhoAcousticVDMaterialProperty{N} + matprop::VpRhoAcousticVDMaterialProperties{N} # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} # Forward computation arrays @@ -454,7 +454,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} # Compute model sizes domainextent = gridspacing .* (ns .- 1) # Initialize material properties - matprop = VpRhoAcousticVDMaterialProperty(zeros(ns...), zeros(ns...)) + matprop = VpRhoAcousticVDMaterialProperties(zeros(ns...), zeros(ns...)) # Select backend backend = select_backend(AcousticVDStaggeredCPMLWaveSimul{N}, parall) diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index a706599..8fac6d1 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -11,7 +11,7 @@ function select_backend( ) where {parall} parasym = [:serial, :threads, :GPU, :threadpersrc] error( - "No backend found for model of type $(wavesim_type) and `parall` $(parall). Argument `parall` must be one of the following symbols: $parasym." + "No backend found for model of type $(wavesim_type) and `parall =` $(parall). Argument `parall` must be one of the following symbols: $parasym." ) end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 4e82c17..393ce0c 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -1,6 +1,10 @@ module Elastic2D_Iso_CPML_Serial + +# To get those structs into this module +using SeismicWaves: ElasticIsoCPMLWaveSimul,ElasticIsoMaterialProperties + # Dummy data module module Data Array = Base.Array @@ -334,7 +338,7 @@ function update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_ end -function update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half,a_x,a_z_half, +function update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half,a_x,a_z_half, freetop) if freetop @@ -406,12 +410,12 @@ end -function forward_onestep_CPML!(wavsim::ElasticIsoWaveSimul{N}, - matprop::ElasticIsoMaterialProperty{N}, +function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, + matprop::ElasticIsoMaterialProperties{N}, possrcs_a::Array{<:Integer,2}, srctf_a::Matrix{<:Real}, posrecs_a::Array{<:Integer,2}, - traces_a::Array{<:Real,N+1}, + traces_a::Array{<:Real}, it::Integer, freetop::Bool, save_trace::Bool) where {N} @@ -462,7 +466,7 @@ function forward_onestep_CPML!(wavsim::ElasticIsoWaveSimul{N}, update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half, psi.ψ_∂vx∂x,psi.ψ_∂vz∂z,b_z,a_x_half,a_z,freetop) # update stress σxz - update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,dt,b_x,b_z_half, + update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half, psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index bd00d32..1370112 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -4,3 +4,4 @@ abstract type ElasticWaveSimul{N} <: WaveSimul{N} end abstract type ElasticIsoWaveSimul{N} <: ElasticWaveSimul{N} end abstract type ElasticMaterialProperties{N} <: MaterialProperties{N} end +abstract type AbstrElasticIsoMaterialProperties{N} <: ElasticMaterialProperties{N} end diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index 0dc2c09..483394d 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -1,5 +1,5 @@ -Base.@kwdef struct ElasticIsoMaterialProperties{N} <: ElasticMaterialProperties{N} +Base.@kwdef struct ElasticIsoMaterialProperties{N} <: AbstrElasticIsoMaterialProperties{N} λ::Array{<:AbstractFloat, N} μ::Array{<:AbstractFloat, N} ρ::Array{<:AbstractFloat, N} @@ -7,7 +7,7 @@ end # Material properties for 2D simulations -Base.@kwdef struct ElasticIsoMaterialProperties2D <: ElasticMaterialProperties{2} +Base.@kwdef struct ElasticIsoMaterialProperties2D <: AbstrElasticIsoMaterialProperties{2} λ::Array{<:AbstractFloat,2} μ::Array{<:AbstractFloat,2} ρ::Array{<:AbstractFloat,2} @@ -16,7 +16,7 @@ Base.@kwdef struct ElasticIsoMaterialProperties2D <: ElasticMaterialProperties{2 μ_jhalf::Array{<:AbstractFloat,2} ρ_ihalf_jhalf::Array{<:AbstractFloat,2} - # function ElasticIsoMaterialProperty{N}(ρ::Array{<:AbstractFloat, N}, + # function ElasticIsoMaterialProperties{N}(ρ::Array{<:AbstractFloat, N}, # μ::Array{<:AbstractFloat, N}, # λ::Array{<:AbstractFloat, N}) where {N} diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 469b975..89ef415 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -126,6 +126,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} dt::Real # BDC and CPML parameters halo::Integer + rcoef::Real freetop::Bool # Gradient computation setup gradient::Bool @@ -136,7 +137,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Logging parameters infoevery::Integer # Material properties - matprop::ElasticIsoMaterialProperties + matprop::AbstrElasticIsoMaterialProperties # Forward computation arrays velpartic::Any # 2D: 2 comp, 3D: 3 comp stress::Any # 2D: 3 arrays, 3D: 6 arrays @@ -154,7 +155,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} checkpoints_ψ::Any # Backend backend::Module - + parall::Symbol function ElasticIsoCPMLWaveSimul{N}( gridsize::NTuple{N, <:Integer}, @@ -163,7 +164,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} dt::Real, halo::Integer, rcoef::Real; - parall::Symbol=:threads, + parall::Symbol=:serial, freetop::Bool=true, gradient::Bool=false, check_freq::Union{<:Integer, Nothing}=nothing, @@ -183,6 +184,10 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Compute wavsim sizes domainextent = gridspacing .* (gridsize .- 1) + + # Select backend + backend = select_backend(ElasticIsoCPMLWaveSimul{N}, parall) + # Initialize material properties if N==2 matprop = ElasticIsoMaterialProperties2D(λ=backend.zeros(gridsize...), @@ -198,9 +203,6 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} error("Only elastic 2D is currently implemented.") end - # Select backend - backend = select_backend(ElasticIsoCPMLWaveSimul{N}, parall) - # Initialize computational arrays if N==2 velpartic = Velpartic2D([backend.zeros(gridsize...) for _ in 1:N]...) # vx, vy[, vz] @@ -299,7 +301,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} matprop, velpartic, stress, - cpmlcoeff, + cpmlcoeffs, ψ, gradient ? adj : nothing, gradient ? ψ_adj : nothing, @@ -308,7 +310,8 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} gradient ? save_buffer : nothing, gradient ? checkpoints : nothing, gradient ? checkpoints_ψ : nothing, - backend + backend, + parall ) end end diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl index 3171032..b3e9ee3 100644 --- a/src/models/elastic/ela_params.jl +++ b/src/models/elastic/ela_params.jl @@ -1,11 +1,20 @@ -""" -Parameters for acoustic wave simulations +@doc """ +$(TYPEDEF) + +Parameters for elastic wave simulations + +$(TYPEDFIELDS) """ struct InputParametersElastic{N} <: InputParameters{N} + "Number of time steps" ntimesteps::Int + "Time step" dt::Real + "Grid size for each dimension" gridsize::NTuple{N, <:Int} + "Grid spacing in each direction" gridspacing::NTuple{N, <:Real} + "Kind of boundary conditions" boundcond::InputBoundaryConditionParameters end diff --git a/src/wrappers.jl b/src/wrappers.jl index 837bad4..c5bb21a 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -42,7 +42,7 @@ function swforward!( out = nothing with_logger(logger) do # Build wavesim - wavesim = build_wavesim(params; parall=parall, snapevery=snapevery, infoevery=infoevery, gradient=false) + wavesim = build_wavesim(params, matprop; parall=parall, snapevery=snapevery, infoevery=infoevery, gradient=false) # Solve simulation out = run_swforward!(wavesim, matprop, shots) end @@ -122,7 +122,7 @@ function swmisfit!( out = nothing with_logger(logger) do # Build wavesim - wavesim = build_wavesim(params; parall=parall, gradient=false) + wavesim = build_wavesim(params, matprop; parall=parall, gradient=false) # Compute misfit out = run_swmisfit!(wavesim, matprop, shots; misfit=misfit) end @@ -214,7 +214,7 @@ function swgradient!( out = nothing with_logger(logger) do # Build wavesim - wavesim = build_wavesim(params,matprop; parall=parall, infoevery=infoevery, gradient=true, check_freq=check_freq, smooth_radius=smooth_radius) + wavesim = build_wavesim(params, matprop; parall=parall, infoevery=infoevery, gradient=true, check_freq=check_freq, smooth_radius=smooth_radius) # Solve simulation out = run_swgradient!(wavesim, matprop, shots; compute_misfit=compute_misfit, misfit=misfit) end @@ -285,7 +285,7 @@ Builds a wave similation based on the input paramters `params` and keyword argum - `snapevery::Union{<:Integer, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). - `infoevery::Union{<:Integer, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function build_wavesim(params::InputParameters, matprop::MaterialProperties; parall, kwargs...) +function build_wavesim(params::InputParameters, matprop::MaterialProperties; parall::Symbol, kwargs...) if parall==:threadpersrc nthr = Threads.nthreads() #println(" build_wavesim :threadpersrc") @@ -300,7 +300,7 @@ end build_concrete_wavesim( params::InputParametersAcoustic{N}, - ::VpAcousticCDMaterialProperty + ::VpAcousticCDMaterialProperties, cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... @@ -317,8 +317,8 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersAcousticVariableDensity{N}, - ::VpRhoAcousticVDMaterialProperty, + params::InputParametersAcoustic{N}, + ::VpRhoAcousticVDMaterialProperties, cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index 548736c..fc443ab 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -23,7 +23,7 @@ with_logger(error_logger) do nx = 501 r = 100 vel = gaussian_vel_1D(nx, c0, c0max, r) - matprop = VpAcousticCDMaterialProperty(vel) + matprop = VpAcousticCDMaterialProperties(vel) # numerics nt = 500 dx = 2.5 @@ -76,7 +76,7 @@ with_logger(error_logger) do nx = 501 r = 100 vel = gaussian_vel_1D(nx, c0, c0max, r) - matprop = VpAcousticCDMaterialProperty(vel) + matprop = VpAcousticCDMaterialProperties(vel) # numerics nt = 500 dx = 2.5 @@ -133,7 +133,7 @@ with_logger(error_logger) do nx = ny = 801 r = 150 vel = gaussian_vel_2D(nx, ny, c0, c0max, r) - matprop = VpAcousticCDMaterialProperty(vel) + matprop = VpAcousticCDMaterialProperties(vel) # numerics nt = 700 dx = dy = 2.5 @@ -189,7 +189,7 @@ with_logger(error_logger) do nx = ny = 801 r = 150 vel = gaussian_vel_2D(nx, ny, c0, c0max, r) - matprop = VpAcousticCDMaterialProperty(vel) + matprop = VpAcousticCDMaterialProperties(vel) # numerics nt = 700 dx = dy = 2.5 diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index 05cc4ea..8d7a678 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -24,7 +24,7 @@ end function setup_constant_vel_1D_CPML(nt, dt, nx, dx, c0, f0, halo, rcoef) # constant velocity setup lx = (nx - 1) * dx - vel = VpAcousticCDMaterialProperty(c0 .* ones(nx)) + vel = VpAcousticCDMaterialProperties(c0 .* ones(nx)) # input parameters params = InputParametersAcoustic(nt, dt, [nx], [dx], CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) @@ -47,7 +47,7 @@ end function setup_constant_vel_rho_1D_CPML(nt, dt, nx, dx, c0, ρ0, t0, f0, halo, rcoef) # constant velocity setup lx = (nx - 1) * dx - matprop = VpRhoAcousticVDMaterialProperty(c0 .* ones(nx), ρ0 .* ones(nx)) + matprop = VpRhoAcousticVDMaterialProperties(c0 .* ones(nx), ρ0 .* ones(nx)) # input parameters params = InputParametersAcousticVariableDensity(nt, dt, [nx], [dx], CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) @@ -71,7 +71,7 @@ function setup_constant_vel_2D_CPML(nt, dt, nx, ny, dx, dy, c0, f0, halo, rcoef) # constant velocity setup lx = (nx - 1) * dx ly = (ny - 1) * dy - vel = VpAcousticCDMaterialProperty(c0 .* ones(nx, ny)) + vel = VpAcousticCDMaterialProperties(c0 .* ones(nx, ny)) # input parameters params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) @@ -95,7 +95,7 @@ function setup_constant_vel_rho_2D_CPML(nt, dt, nx, ny, dx, dy, c0, ρ0, t0, f0, # constant velocity setup lx = (nx - 1) * dx ly = (ny - 1) * dy - matprop = VpRhoAcousticVDMaterialProperty(c0 .* ones(nx, ny), ρ0 .* ones(nx, ny)) + matprop = VpRhoAcousticVDMaterialProperties(c0 .* ones(nx, ny), ρ0 .* ones(nx, ny)) # input parameters params = InputParametersAcousticVariableDensity(nt, dt, [nx, ny], [dx, dy], CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) @@ -119,7 +119,7 @@ function setup_constant_vel_3D_CPML(nt, dt, nx, ny, nz, dx, dy, dz, c0, f0, halo lx = (nx - 1) * dx ly = (ny - 1) * dy lz = (nz - 1) * dz - vel = VpAcousticCDMaterialProperty(c0 .* ones(nx, ny, nz)) + vel = VpAcousticCDMaterialProperties(c0 .* ones(nx, ny, nz)) # input parameters params = InputParametersAcoustic(nt, dt, [nx, ny, nz], [dx, dy, dz], CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) From 7c04e24b864b16e60d6ac43b5274f19e30691c56 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Fri, 12 Jan 2024 13:01:09 +0100 Subject: [PATCH 013/111] refactor init_shot!, etc. --- src/SeismicWaves.jl | 1 + src/checks.jl | 3 +- src/models/acoustic/acou_forward.jl | 152 ++++++++++++------ src/models/acoustic/acou_gradient.jl | 72 +++++---- src/models/acoustic/acou_models.jl | 18 +-- src/models/cpmlcoeffs.jl | 26 +-- src/models/elastic/ela_forward.jl | 14 +- src/models/elastic/ela_init_bc.jl | 17 +- src/models/elastic/ela_material_properties.jl | 16 +- src/models/elastic/ela_models.jl | 10 +- src/receivers.jl | 27 ++-- src/shot.jl | 20 +-- src/solve.jl | 35 ++-- src/sources.jl | 29 ++-- 14 files changed, 270 insertions(+), 170 deletions(-) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index e58df0f..51aba98 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -22,6 +22,7 @@ export ElasticIsoMaterialProperties # export sources, receivers and shots export Shot export ScalarSources, MomentTensorSources +export MomentTensor2D, MomentTensor3D export ScalarReceivers, VectorReceivers # forward, misfit and gradient functions export swforward!, swmisfit!, swgradient! diff --git a/src/checks.jl b/src/checks.jl index 58d9f67..a8cedbe 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -19,6 +19,7 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s tysource <: ScalarSources && tyreceiver <: ScalarReceivers return + elseif tysim == AcousticVDStaggeredCPMLWaveSimul{N} && tymatprop == VpRhoAcousticVDMaterialProperties{N} && tysource <: ScalarSources && @@ -34,7 +35,7 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s end return error("Types of WaveSimul, MaterialProperties and Sources/Receivers are incosistent \ - \n $(typeof(wavsim)), $(typeof(matprop)), $(typeof(shots[1].srcs)), $(typeof(shots[1].recs))") + \n $(typeof(wavsim)), \n $(typeof(matprop)), \n $(typeof(shots[1].srcs)), $(typeof(shots[1].recs))") end function check_shot(model::WaveSimul, shot::Shot; kwargs...) diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 48e1f84..b7164d4 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -1,104 +1,156 @@ -swforward_1shot!(model::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) + +swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) + +# Scaling for AcousticCDWaveSimul +@views function possrcrec_scaletf(wavsim::AcousticCDCMPLWaveSimul{N}, + shot::Shot) where {N} + # find nearest grid points indexes for both sources and receivers + possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) + posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + + # source time function + # scale with boxcar and timestep size + scal_srctf = shot.srcs.tf ./ prod(wavsim.gridspacing) .* (wavsim.dt^2) + # scale with velocity squared at each source position + for s in axes(scal_srctf, 2) + scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 + end + + return possrcs,posrecs,scal_srctf +end + @views function swforward_1shot!( ::CPMLBoundaryCondition, - model::AcousticCDWaveSimul{N}, - possrcs, - posrecs, - srctf, - recs -) where {N} + wavsim::AcousticCDCPMLWaveSimul{N}, + shot::Shot + # possrcs, + # posrecs, + # srctf, + # recs + ) where {N} + + # scale source time function, etc. + possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsim,shot) + # Pressure arrays - pold = model.pold - pcur = model.pcur - pnew = model.pnew + pold = wavsim.pold + pcur = wavsim.pcur + pnew = wavsim.pnew # Numerics - nt = model.nt + nt = wavsim.nt # Wrap sources and receivers arrays - possrcs_a = model.backend.Data.Array(possrcs) - posrecs_a = model.backend.Data.Array(posrecs) - srctf_a = model.backend.Data.Array(srctf) - traces_a = model.backend.Data.Array(recs.seismograms) + possrcs_bk = wavsim.backend.Data.Array(possrcs) + posrecs_bk = wavsim.backend.Data.Array(posrecs) + srctf_bk = wavsim.backend.Data.Array(scal_srctf) + traces_bk = wavsim.backend.Data.Array(recs.seismograms) # Reset wavesim - reset!(model) + reset!(wavsim) # Time loop for it in 1:nt # Compute one forward step - pold, pcur, pnew = model.backend.forward_onestep_CPML!( - pold, pcur, pnew, model.fact, - model.gridspacing..., model.halo, - model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_a, srctf_a, posrecs_a, traces_a, it + pold, pcur, pnew = wavsim.backend.forward_onestep_CPML!( + pold, pcur, pnew, wavsim.fact, + wavsim.gridspacing..., wavsim.halo, + wavsim.ψ..., wavsim.ξ..., wavsim.a_coeffs..., wavsim.b_coeffs..., + possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info - if it % model.infoevery == 0 + if it % wavsim.infoevery == 0 @debug @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, - model.dt * (it - 1), + wavsim.dt * (it - 1), maximum(abs.(Array(pcur))) ) end # Save snapshot - if snapenabled(model) && it % model.snapevery == 0 + if snapenabled(wavsim) && it % wavsim.snapevery == 0 @debug @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) - copyto!(model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)], pcur) + copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], pcur) end end # Save traces - copyto!(recs.seismograms, traces_a) + copyto!(recs.seismograms, traces_bk) +end + + +##################################################### + +# Scaling for AcousticVDStaggeredCPMLWaveSimul +@views function possrcrec_scaletf(wavsim::AcousticVDStaggeredCPMLWaveSimul{N}, + shot::Shot) where {N} + # find nearest grid points indexes for both sources and receivers + possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) + posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + + # source time function + # scale with boxcar and timestep size + scal_srctf = shot.srcs.tf ./ prod(wavsim.gridspacing) .* (wavsim.dt) + # scale with velocity squared times density at each source position (its like dividing by m0) + for s in axes(scal_srctf, 2) + scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 * wavsim.matprop.rho[positions[s, :]...] + end + + return possrcs,posrecs,scal_srctf end + @views function swforward_1shot!( ::CPMLBoundaryCondition, - model::AcousticVDStaggeredCPMLWaveSimul{N}, - possrcs, - posrecs, - srctf, - recs -) where {N} + wavsim::AcousticVDStaggeredCPMLWaveSimul{N}, + shot::Shot + # possrcs, + # posrecs, + # srctf, + # recs + ) where {N} + + # scale source time function, etc. + possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsime,shot) + # Pressure and velocity arrays - pcur = model.pcur - vcur = model.vcur + pcur = wavsim.pcur + vcur = wavsim.vcur # Numerics - nt = model.nt + nt = wavsim.nt # Wrap sources and receivers arrays - possrcs_a = model.backend.Data.Array(possrcs) - posrecs_a = model.backend.Data.Array(posrecs) - srctf_a = model.backend.Data.Array(srctf) - traces_a = model.backend.Data.Array(recs.seismograms) + possrcs_bk = wavsim.backend.Data.Array(possrcs) + posrecs_bk = wavsim.backend.Data.Array(posrecs) + srctf_bk = wavsim.backend.Data.Array(scal_srctf) + traces_bk = wavsim.backend.Data.Array(recs.seismograms) # Reset wavesim - reset!(model) + reset!(wavsim) # Time loop for it in 1:nt # Compute one forward step - model.backend.forward_onestep_CPML!( - pcur, vcur..., model.fact_m0, model.fact_m1_stag..., - model.gridspacing..., model.halo, - model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_a, srctf_a, posrecs_a, traces_a, it + wavsim.backend.forward_onestep_CPML!( + pcur, vcur..., wavsim.fact_m0, wavsim.fact_m1_stag..., + wavsim.gridspacing..., wavsim.halo, + wavsim.ψ..., wavsim.ξ..., wavsim.a_coeffs..., wavsim.b_coeffs..., + possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info - if it % model.infoevery == 0 + if it % wavsim.infoevery == 0 @debug @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, - model.dt * (it - 1), + wavsim.dt * (it - 1), maximum(abs.(Array(pcur))) ) end # Save snapshot - if snapenabled(model) && it % model.snapevery == 0 + if snapenabled(wavsim) && it % wavsim.snapevery == 0 @debug @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) - copyto!(model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)], pcur) + copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], pcur) end end # Save traces - copyto!(recs.seismograms, traces_a) + copyto!(recs.seismograms, traces_bk) end diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 5d45031..0eaff5f 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -4,12 +4,17 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @views function swgradient_1shot!( ::CPMLBoundaryCondition, model::AcousticCDWaveSimul{N}, - possrcs, - posrecs, - srctf, - recs, + shot::Shot, + # possrcs, + # posrecs, + # srctf, + # recs, misfit )::Array{<:Real} where {N} + + # scale source time function, etc. + possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsim,shot) + # Numerics nt = model.nt # Initialize pressure and factors arrays @@ -21,10 +26,10 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = adjcur = model.adjcur adjnew = model.adjnew # Wrap sources and receivers arrays - possrcs_a = model.backend.Data.Array(possrcs) - posrecs_a = model.backend.Data.Array(posrecs) - srctf_a = model.backend.Data.Array(srctf) - traces_a = model.backend.Data.Array(recs.seismograms) + possrcs_bk = model.backend.Data.Array(possrcs) + posrecs_bk = model.backend.Data.Array(posrecs) + srctf_bk = model.backend.Data.Array(scal_srctf) + traces_bk = model.backend.Data.Array(recs.seismograms) # Reset wavesim reset!(model) @@ -35,7 +40,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = pold, pcur, pnew, model.fact, model.gridspacing..., model.halo, model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_a, srctf_a, posrecs_a, traces_a, it + possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info if it % model.infoevery == 0 @@ -62,13 +67,13 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = end @info "Saving seismograms" - copyto!(recs.seismograms, traces_a) + copyto!(recs.seismograms, traces_bk) @debug "Computing residuals" - residuals_a = model.backend.Data.Array(dχ_du(misfit, recs)) + residuals_bk = model.backend.Data.Array(dχ_du(misfit, recs)) # Prescale residuals (fact = vel^2 * dt^2) - model.backend.prescale_residuals!(residuals_a, posrecs_a, model.fact) + model.backend.prescale_residuals!(residuals_bk, posrecs_bk, model.fact) @debug "Computing gradients" # Current checkpoint @@ -79,8 +84,8 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = adjold, adjcur, adjnew = model.backend.forward_onestep_CPML!( adjold, adjcur, adjnew, model.fact, model.gridspacing..., model.halo, - model.ψ_adj..., model.ξ_adj..., model.a_coeffs..., model.b_coeffs..., - posrecs_a, residuals_a, nothing, nothing, it; # adjoint sources positions are receivers + model.ψ_bkdj..., model.ξ_bkdj..., model.a_coeffs..., model.b_coeffs..., + posrecs_bk, residuals_bk, nothing, nothing, it; # adjoint sources positions are receivers save_trace=false ) # Print timestep info @@ -115,7 +120,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = pold, pcur, pnew, model.fact, model.gridspacing..., model.halo, model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_a, srctf_a, nothing, nothing, recit; + possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false ) if recit % model.infoevery == 0 @@ -148,12 +153,17 @@ end @views function swgradient_1shot!( ::CPMLBoundaryCondition, model::AcousticVDStaggeredCPMLWaveSimul{N}, - possrcs, - posrecs, - srctf, - recs, + shot::Shot, + # possrcs, + # posrecs, + # srctf, + # recs, misfit -)::Array{<:Real} where {N} + )::Array{<:Real} where {N} + + # scale source time function, etc. + possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsime,shot) + # Numerics nt = model.nt # Initialize pressure and velocities arrays @@ -163,10 +173,10 @@ end adjpcur = model.adjpcur adjvcur = model.adjvcur # Wrap sources and receivers arrays - possrcs_a = model.backend.Data.Array(possrcs) - posrecs_a = model.backend.Data.Array(posrecs) - srctf_a = model.backend.Data.Array(srctf) - traces_a = model.backend.Data.Array(recs.seismograms) + possrcs_bk = model.backend.Data.Array(possrcs) + posrecs_bk = model.backend.Data.Array(posrecs) + srctf_bk = model.backend.Data.Array(scal_srctf) + traces_bk = model.backend.Data.Array(recs.seismograms) # Reset wavesim reset!(model) @@ -177,7 +187,7 @@ end pcur, vcur..., model.fact_m0, model.fact_m1_stag..., model.gridspacing..., model.halo, model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_a, srctf_a, posrecs_a, traces_a, it + possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info if it % model.infoevery == 0 @@ -206,13 +216,13 @@ end end @info "Saving seismograms" - copyto!(recs.seismograms, traces_a) + copyto!(recs.seismograms, traces_bk) @debug "Computing residuals" - residuals_a = model.backend.Data.Array(dχ_du(misfit, recs)) + residuals_bk = model.backend.Data.Array(dχ_du(misfit, recs)) # Prescale residuals (fact = vel^2 * rho * dt) - model.backend.prescale_residuals!(residuals_a, posrecs_a, model.fact_m0) + model.backend.prescale_residuals!(residuals_bk, posrecs_bk, model.fact_m0) @debug "Computing gradients" # Current checkpoint @@ -223,8 +233,8 @@ end model.backend.backward_onestep_CPML!( adjpcur, adjvcur..., model.fact_m0, model.fact_m1_stag..., model.gridspacing..., model.halo, - model.ψ_adj..., model.ξ_adj..., model.a_coeffs..., model.b_coeffs..., - posrecs_a, residuals_a, it; # adjoint sources positions are receivers + model.ψ_bkdj..., model.ξ_bkdj..., model.a_coeffs..., model.b_coeffs..., + posrecs_bk, residuals_bk, it; # adjoint sources positions are receivers ) # Print timestep info if it % model.infoevery == 0 @@ -257,7 +267,7 @@ end pcur, vcur..., model.fact_m0, model.fact_m1_stag..., model.gridspacing..., model.halo, model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_a, srctf_a, nothing, nothing, recit; + possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false ) if recit % model.infoevery == 0 diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index ff3ec25..8114fdb 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -29,15 +29,15 @@ end # Functions for all AcousticCDWaveSimul subtypes -@views function scale_srctf(model::AcousticCDWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} - # scale with boxcar and timestep size - scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt^2) - # scale with velocity squared at each source position - for s in axes(scaled_tf, 2) - scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] .^ 2 - end - return scaled_tf -end +# @views function scale_srctf(model::AcousticCDWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} +# # scale with boxcar and timestep size +# scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt^2) +# # scale with velocity squared at each source position +# for s in axes(scaled_tf, 2) +# scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] .^ 2 +# end +# return scaled_tf +# end @views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{N}) where {N} # Checks diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 8319ba0..9dccf17 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -9,17 +9,17 @@ struct CPMLCoefficientsAxis sizehalfgrdplusone::Bool=false) if sizehalfgrdplusone return new( - backend.zeros(halo), - backend.zeros(halo + 1), - backend.zeros(halo), - backend.zeros(halo + 1), + backend.zeros(2 * halo), + backend.zeros(2 * (halo+1) +1 ), + backend.zeros(2 * halo), + backend.zeros(2 * (halo+1) +1), ) else return new( - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo) + backend.zeros(2 * halo), + backend.zeros(2 * (halo+1)), + backend.zeros(2 * halo), + backend.zeros(2 * (halo+1)) ) end end @@ -41,10 +41,12 @@ function compute_CPML_coefficientsAxis!( a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") - copyto!(cpmlcoeffs.a, cat(a_l,a_r)) - copyto!(cpmlcoeffs.a_h, cat(a_hl,a_hr)) - copyto!(cpmlcoeffs.b, cat(b_l,b_r)) - copyto!(cpmlcoeffs.b_h, cat(b_hl,b_hr)) + @show size(a_hl),size(a_hr),size(cpmlcoeffs.a_h) + + copyto!(cpmlcoeffs.a, vcat(a_l,a_r)) + copyto!(cpmlcoeffs.a_h, vcat(a_hl,a_hr)) + copyto!(cpmlcoeffs.b, vcat(b_l,b_r)) + copyto!(cpmlcoeffs.b_h, vcat(b_hl,b_hr)) end ################################################################# diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index f2fdebb..c39ff1b 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -3,7 +3,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::ElasticIsoWaveSimul{N}, + wavsim::ElasticIsoCPMLWaveSimul{N}, possrcs::Matrix{<:Integer}, posrecs::Matrix{<:Integer}, srctf, @@ -13,10 +13,10 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Numerics nt = wavsim.nt # Wrap sources and receivers arrays - possrcs_a = wavsim.backend.Data.Array(possrcs) - posrecs_a = wavsim.backend.Data.Array(posrecs) - srctf_a = wavsim.backend.Data.Array(srctf) - traces_a = wavsim.backend.Data.Array(recs.seismograms) + possrcs_bk = wavsim.backend.Data.Array(possrcs) + posrecs_bk = wavsim.backend.Data.Array(posrecs) + srctf_bk = wavsim.backend.Data.Array(srctf) + traces_bk = wavsim.backend.Data.Array(recs.seismograms) ## ONLY 2D for now!!! Mxx = wavsim.backend.Data.Array(momtens.Mxx) @@ -29,7 +29,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Time loop for it in 1:nt # Compute one forward step - wavsim.backend.forward_onestep_CPML!(wavsim, possrcs_a, srctf_a, posrecs_a, traces_a, it, + wavsim.backend.forward_onestep_CPML!(wavsim, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it, freetop, save_trace) # wavsim.velpartic..., wavsim.stress..., @@ -65,6 +65,6 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC end # Save traces - copyto!(recs.seismograms, traces_a) + copyto!(recs.seismograms, traces_bk) return end diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl index 28ed161..a35dfc1 100644 --- a/src/models/elastic/ela_init_bc.jl +++ b/src/models/elastic/ela_init_bc.jl @@ -11,7 +11,8 @@ init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimul, srcs::Sources) ) N = length(model.cpmlcoeffs) for n in 1:N - compute_CPML_coefficients!( + #@show n,typeof(model.cpmlcoeffs[n]) + compute_CPML_coefficientsAxis!( model.cpmlcoeffs[n], get_maximum_func(model)( sqrt.((model.matprop.λ+2.0*model.matprop.μ)./model.matprop.ρ) ), model.dt, @@ -23,9 +24,15 @@ init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimul, srcs::Sources) end if model.freetop && N >= 1 - model.cpmlcoeffs[N].a_l .= 0.0 - model.cpmlcoeffs[N].a_hl .= 0.0 - model.cpmlcoeffs[N].b_l .= 1.0 - model.cpmlcoeffs[N].b_hl .= 1.0 + lastcoe = model.cpmlcoeffs[N] + + lastcoe.a[1:length(lastcoe.a)÷2] .= 0.0 + lastcoe.a_h[1:length(lastcoe.a_h)÷2] .= 0.0 + lastcoe.b[1:length(lastcoe.b)÷2] .= 1.0 + lastcoe.b_h[1:length(lastcoe.b_h)÷2] .= 1.0 + # model.cpmlcoeffs[N].a_l .= 0.0 + # model.cpmlcoeffs[N].a_hl .= 0.0 + # model.cpmlcoeffs[N].b_l .= 1.0 + # model.cpmlcoeffs[N].b_hl .= 1.0 end end diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index 483394d..a5b38f3 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -36,7 +36,7 @@ end -function precomp_elaprop!(matprop::ElasticIsoMaterialProperties{2}; harmonicaver_μ=true) +function precomp_elaprop!(matprop::ElasticIsoMaterialProperties2D; harmonicaver_μ=true) # function precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; # harmonicaver_μ=true) @@ -46,22 +46,22 @@ function precomp_elaprop!(matprop::ElasticIsoMaterialProperties{2}; harmonicaver #------------------------------------------------------------- # ρ_ihalf_jhalf (nx-1,nz-1) ?? # arithmetic mean for ρ - @. ρ_ihalf_jhalf = (ρ[2:end,2:end]+ρ[2:end,1:end-1]+ - ρ[1:end-1,2:end]+ρ[1:end-1,1:end-1])/4.0 + @. matprop.ρ_ihalf_jhalf = (matprop.ρ[2:end,2:end]+matprop.ρ[2:end,1:end-1]+ + matprop.ρ[1:end-1,2:end]+matprop.ρ[1:end-1,1:end-1])/4.0 # μ_ihalf (nx-1,nz) ?? # μ_ihalf (nx,nz-1) ?? if harmonicaver_μ==true # harmonic mean for μ - @. μ_ihalf = 1.0 / ( 1.0/μ[2:end,:] + 1.0 / μ[1:end-1,:] ) - @. μ_jhalf = 1.0 / ( 1.0/μ[:,2:end] + 1.0 / μ[:,1:end-1] ) + @. matprop.μ_ihalf = 1.0 / ( 1.0/matprop.μ[2:end,:] + 1.0 / matprop.μ[1:end-1,:] ) + @. matprop.μ_jhalf = 1.0 / ( 1.0/matprop.μ[:,2:end] + 1.0 / matprop.μ[:,1:end-1] ) else # arithmetic mean for μ - @. μ_ihalf = (μ[2:end,:] + μ[1:end-1,:]) / 2.0 - @. μ_jhalf = (μ[:,2:end] + μ[:,1:end-1]) / 2.0 + @. matprop.μ_ihalf = (matprop.μ[2:end,:] + matprop.μ[1:end-1,:]) / 2.0 + @. matprop.μ_jhalf = (matprop.μ[:,2:end] + matprop.μ[:,1:end-1]) / 2.0 end # λ_ihalf (nx-1,nz) ?? # arithmetic mean for λ - @. λ_ihalf = (λ[2:end,:] + λ[1:end-1,:]) / 2.0 + @. matprop.λ_ihalf = (matprop.λ[2:end,:] + matprop.λ[1:end-1,:]) / 2.0 return end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 89ef415..e773b7f 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -4,7 +4,7 @@ @views function check_matprop(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperties{N}) where {N} # Checks - vp = sqrt((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) + vp = sqrt.((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(vp) == wavsim.gridsize "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(wavsim.gridsize)" @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @@ -12,8 +12,8 @@ @assert all(matprop.ρ .> 0) "Density must be positive!" # Check courant condition - vp_max = get_maximum_func(wavsim)(vp) - tmp = sqrt(sum(1 ./ wavsim.gridspacing .^ 2)) + vel_max = get_maximum_func(wavsim)(vp) + tmp = sqrt.(sum(1 ./ wavsim.gridspacing .^ 2)) courant = vel_max * wavsim.dt * tmp @debug "Courant number: $(courant)" if courant > 1.0 @@ -30,7 +30,7 @@ function check_numerics( min_ppw::Integer=10 ) # Check points per wavelengh - vel_min = get_minimum_func(wavsim)(sqrt(wavsim.matprop.μ ./ wavsim.matprop.ρ)) # min Vs + vel_min = get_minimum_func(wavsim)(sqrt.(wavsim.matprop.μ ./ wavsim.matprop.ρ)) # min Vs h_max = maximum(wavsim.gridspacing) ppw = vel_min / shot.srcs.domfreq / h_max @debug "Points per wavelength: $(ppw)" @@ -193,7 +193,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} matprop = ElasticIsoMaterialProperties2D(λ=backend.zeros(gridsize...), μ=backend.zeros(gridsize...), ρ=backend.zeros(gridsize...), - λ_ihalf=backend.zeros((gridsize.-1)...), + λ_ihalf=backend.zeros((gridsize.-[1,0])...), μ_ihalf=backend.zeros((gridsize.-[1,0])...), μ_jhalf=backend.zeros((gridsize.-[0,1])...), ρ_ihalf_jhalf=backend.zeros((gridsize.-1)...) diff --git a/src/receivers.jl b/src/receivers.jl index a8ed2f9..60be34f 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -71,14 +71,22 @@ ScalarReceivers(positions, nt; observed=nothing, invcov=nothing, windows=nothing -@doc raw""" +@doc """ +$(TYPEDEF) + Type representing a multi-receiver configuration for a wave propagation shot. + +$(TYPEDFIELDS) """ # What about using the package ComputedFieldTypes.jl? @computed ... struct VectorReceivers{N,T<:Real} <: Receivers + "Receiver positions" positions::Matrix{T} - seismograms::Array{T} - observed::Matrix{T} + "Array holding seismograms (as columns)" + seismograms::Array{T,3} + "Array holding observed seismograms (as columns)" + observed::Array{T,3} + "Inverse of the covariance matrix" invcov::AbstractMatrix{T} @doc raw""" @@ -87,9 +95,9 @@ struct VectorReceivers{N,T<:Real} <: Receivers Create a single shot wave propagation receivers configuration from receivers positions. """ function VectorReceivers{N,T}( - positions::Matrix{<:Real}, - nt::Integer; - ndim::Integer=2, + positions::Matrix{T}, + nt::Integer, + ndim::Integer=2; observed::Union{Array{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing ) where {N,T <: Real} @@ -98,17 +106,18 @@ struct VectorReceivers{N,T<:Real} <: Receivers if observed !== nothing @assert size(seismograms) == size(observed) "Size of observed data is not (# timesteps, # receivers)!" else - observed = nothing + observed = zeros(0,0,0) # (nt,ndim,npos) end if invcov !== nothing @assert size(invcov) == (nt, nt) "Size of invcov is not (# timesteps, # timesteps)!" else - invcov = nothing + invcov = zeros(0,0) end return new{ndim,T}(positions, seismograms, observed, invcov) + #return new(positions, seismograms, observed, invcov) end end # Default type constructor -VectorReceivers(positions, nt; observed=nothing, invcov=nothing) = VectorReceivers{Float64}(positions, nt; observed=observed, invcov=invcov) +VectorReceivers(positions, nt, ndim; observed=nothing, invcov=nothing) = VectorReceivers{ndim,Float64}(positions, nt, ndim; observed=observed, invcov=invcov) diff --git a/src/shot.jl b/src/shot.jl index 40cc69e..21dca28 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -15,24 +15,24 @@ end ################################################## -function init_shot!(model::WaveSimul, shot::Shot; kwargs...)::Tuple{Matrix{<:Int}, Matrix{<:Int}, Array{<:Real}} +function init_shot!(model::WaveSimul, shot::Shot; kwargs...)#::Tuple{Matrix{<:Int}, Matrix{<:Int}, Array{<:Real}} # Check shot configuration check_shot(model, shot; kwargs...) # Initialize boundary conditions based on current shot init_bdc!(model, shot.srcs) # Return allocated shot's arrays - return setup_shot(model, shot) + return #setup_shot(model, shot) end -@views function setup_shot(model::WaveSimul, shot::Shot)::Tuple{Matrix{<:Int}, Matrix{<:Int}, Array{<:Real}} - # find nearest grid points indexes for both sources and receivers - possrcs = find_nearest_grid_points(model, shot.srcs.positions) - posrecs = find_nearest_grid_points(model, shot.recs.positions) - # source time function (prescale if needed) - scaled_tf = scale_srctf(model, shot.srcs.tf, possrcs) +# @views function setup_shot(model::WaveSimul, shot::Shot)::Tuple{Matrix{<:Int}, Matrix{<:Int}, Array{<:Real}} +# # find nearest grid points indexes for both sources and receivers +# possrcs = find_nearest_grid_points(model, shot.srcs.positions) +# posrecs = find_nearest_grid_points(model, shot.recs.positions) +# # source time function (prescale if needed) +# scaled_tf = scale_srctf(model, shot.srcs.tf, possrcs) - return possrcs, posrecs, scaled_tf -end +# return possrcs, posrecs, scaled_tf +# end @views function find_nearest_grid_points(model::WaveSimul, positions::Matrix{<:Real})::Matrix{<:Int} # source time functions diff --git a/src/solve.jl b/src/solve.jl index 84c78b1..6a6938e 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -39,10 +39,11 @@ end recs = singleshot.recs # Initialize shot @info "Initializing shot" - possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) + #possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) + init_shot!(wavsim, singleshot) # Compute forward solver @info "Forward modelling for one shot" - swforward_1shot!(wavsim, possrcs, posrecs, srctf, recs) + swforward_1shot!(wavsim, singleshot) #possrcs, posrecs, srctf, recs) # Save shot's snapshots if takesnapshots @info "Saving snapshots" @@ -98,10 +99,12 @@ end recs = singleshot.recs # Initialize shot @info "Initializing shot" - possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) + #possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) + init_shot!(wavsim[w], singleshot) # Compute forward solver @info "Forward modelling for one shot" - swforward_1shot!(wavsim[w], possrcs, posrecs, srctf, recs) + #swforward_1shot!(wavsim[w], possrcs, posrecs, srctf, recs) + swforward_1shot!(wavsim[w], singleshot) # Save shot's snapshots if takesnapshots @info "Saving snapshots" @@ -177,15 +180,19 @@ end recs = singleshot.recs # Initialize shot @info "Initializing shot" - possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) + #possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) + init_shot!(wavsim, singleshot) @info "Checking invcov matrix" check_invcov_matrix(wavsim, recs.invcov) # Compute forward solver @info "Computing gradient solver" + # curgrad = swgradient_1shot!( + # wavsim, possrcs, + # posrecs, srctf, + # recs, misfit + # ) curgrad = swgradient_1shot!( - wavsim, possrcs, - posrecs, srctf, - recs, misfit + wavsim, singleshot, misfit ) # Accumulate gradient totgrad .+= curgrad @@ -246,15 +253,19 @@ end recs = singleshot.recs # Initialize shot @info "Initializing shot" - possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) + #possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) + init_shot!(wavsim[w], singleshot) @info "Checking invcov matrix" check_invcov_matrix(wavsim[w], recs.invcov) # Compute forward solver @info "Computing gradient solver" + # curgrad = swgradient_1shot!( + # wavsim[w], possrcs, + # posrecs, srctf, + # recs, misfit + # ) curgrad = swgradient_1shot!( - wavsim[w], possrcs, - posrecs, srctf, - recs, misfit + wavsim[w], singleshot, misfit ) # Accumulate gradient allgrad[s] = curgrad diff --git a/src/sources.jl b/src/sources.jl index d9604cf..d7a13e1 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -37,18 +37,18 @@ ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, do #################################################### """ -Type representing a 2D moment tensor. +Type representing vector components of a 2D moment tensor. """ -struct MomentTensor2D{T <: Real} <: MomentTensor +Base.@kwdef struct MomentTensor2D{T <: Real} <: MomentTensor Mxx::Vector{T} Mzz::Vector{T} Mxz::Vector{T} end """ -Type representing a 2D moment tensor. +Type representing vector components of a 2D moment tensor. """ -struct MomentTensor3D{T <: Real} <: MomentTensor +Base.@kwdef struct MomentTensor3D{T <: Real} <: MomentTensor Mxx::Vector{T} Myy::Vector{T} Mzz::Vector{T} @@ -62,7 +62,7 @@ end Type representing a multi-source configuration for a wave propagation shot. """ struct MomentTensorSources{N, T <: Real} <: Sources - positions::Matrix{<:Real} + positions::Matrix{T} tf::Matrix{T} momtens::MomentTensor domfreq::T @@ -77,13 +77,13 @@ struct MomentTensorSources{N, T <: Real} <: Sources Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function MomentTensorSources{N,T}(positions::Matrix{<:Real}, tf::Matrix{T}, momtens::MomentTensor, domfreq::T) where {N, T <: Real} + function MomentTensorSources{N,T}(positions::Matrix{T}, tf::Matrix{T}, momtens::MomentTensor, domfreq::T) where {N, T <: Real} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" - if N==1 - @assert typeof(momtens)==MomentTensor2D - elseif N==2 - @assert typeof(momtens)==MomentTensor3D + if N==2 + @assert typeof(momtens)<:MomentTensor2D + elseif N==3 + @assert typeof(momtens)<:MomentTensor3D else error("MomentTensorSources: Moment tensor neither 2D nor 3D.") end @@ -92,6 +92,13 @@ struct MomentTensorSources{N, T <: Real} <: Sources end # Default type constructor {Float64} -MomentTensorSources(positions, tf, momtens, domfreq) = MomentTensorSources{Float64}(positions, tf, momtens, domfreq) +MomentTensorSources(positions, tf, momtens, domfreq) = begin + if typeof(momtens)<:MomentTensor2D + ndim=2 + elseif typeof(momtens)<:MomentTensor3D + ndim=3 + end + MomentTensorSources{ndim,Float64}(positions, tf, momtens, domfreq) +end #################################################### From ab3922e6e7c65e95d46421d91aee651d55a13ae2 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Sun, 14 Jan 2024 12:12:06 +0100 Subject: [PATCH 014/111] updates... --- src/models/acoustic/acou_forward.jl | 4 +- src/models/acoustic/acou_models.jl | 18 ++++---- .../backends/Elastic2D_Iso_CPML_Serial.jl | 41 +++++++++++-------- src/models/elastic/ela_abstract_types.jl | 2 + src/models/elastic/ela_forward.jl | 36 ++++++++++++---- src/models/elastic/ela_models.jl | 14 ++----- 6 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index b7164d4..9315d86 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -1,8 +1,10 @@ +# Generic function swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) + # Scaling for AcousticCDWaveSimul -@views function possrcrec_scaletf(wavsim::AcousticCDCMPLWaveSimul{N}, +@views function possrcrec_scaletf(wavsim::AcousticCDCPMLWaveSimul{N}, shot::Shot) where {N} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 8114fdb..612642f 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -331,15 +331,15 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() end end -@views function scale_srctf(model::AcousticVDStaggeredWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} - # scale with boxcar and timestep size - scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt) - # scale with velocity squared times density at each source position (its like dividing by m0) - for s in axes(scaled_tf, 2) - scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] ^ 2 * model.matprop.rho[positions[s, :]...] - end - return scaled_tf -end +# @views function scale_srctf(model::AcousticVDStaggeredWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} +# # scale with boxcar and timestep size +# scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt) +# # scale with velocity squared times density at each source position (its like dividing by m0) +# for s in axes(scaled_tf, 2) +# scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] ^ 2 * model.matprop.rho[positions[s, :]...] +# end +# return scaled_tf +# end @views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} # Checks diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 393ce0c..61a1ee8 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -93,7 +93,7 @@ zeros = Base.zeros -function update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, +function update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, freetop) if freetop for j = 1:2 @@ -131,7 +131,7 @@ function update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z # right boundary # ii = i - (nx - halo) + 1 ii = i - (nx - 2*halo) + 1 # == ii = i - (nx - halo) + 1 + halo - ψ_∂σxx∂x[ii,j] = b_x[i2] * ψ_∂σxx∂x[ii,j] + a_x[ii] * ∂σxx∂x_bkw + ψ_∂σxx∂x[ii,j] = b_x[ii] * ψ_∂σxx∂x[ii,j] + a_x[ii] * ∂σxx∂x_bkw ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii,j] end # y boundaries @@ -166,7 +166,7 @@ end -function update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, +function update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, b_x_half,b_z_half,a_x_half,a_z_half,freetop) if freetop @@ -239,7 +239,7 @@ function update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ end -function update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, +function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, b_x_half,b_z,a_x_half,a_z,freetop) if freetop==true @@ -338,7 +338,7 @@ function update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_ end -function update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half,a_x,a_z_half, +function update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half,a_x,a_z_half, freetop) if freetop @@ -411,17 +411,26 @@ end function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, - matprop::ElasticIsoMaterialProperties{N}, possrcs_a::Array{<:Integer,2}, srctf_a::Matrix{<:Real}, posrecs_a::Array{<:Integer,2}, traces_a::Array{<:Real}, it::Integer, - freetop::Bool, - save_trace::Bool) where {N} + Mxx::Vector{<:Real}, + Mzz::Vector{<:Real}, + Mxz::Vector{<:Real}; + save_trace::Bool=true) where {N} @assert N==2 - + freetop = wavsim.freetop + cpmlcoeffs = wavsim.cpmlcoeffs + matprop = wavsim.matprop + dx = wavsim.gridspacing[1] + dz = wavsim.gridspacing[2] + dt = wavsim.dt + nx,nz = wavsim.gridsize[1:2] + halo = wavsim.halo + vx = wavsim.velpartic.vx vz = wavsim.velpartic.vz σxx = wavsim.stress.σxx @@ -440,33 +449,29 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, b_z = cpmlcoeffs[2].b b_z_half = cpmlcoeffs[2].b_h - λ_ihal = matprop.λ_ihal + λ_ihalf = matprop.λ_ihalf ρ = matprop.ρ ρ_ihalf_jhalf = matprop.ρ_ihalf_jhalf μ = matprop.μ μ_ihalf = matprop.μ_ihalf μ_jhalf = matprop.μ_jhalf - Mxx = wavsim.momtens.Mxx - Mzz = wavsim.momtens.Mzz - Mxz = wavsim.momtens.Mxz - ## pre-scale coefficients factx = 1.0/(24.0*dx) factz = 1.0/(24.0*dz) # update velocity vx - update_vx!(vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, + update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, b_x,b_z,a_x,a_z,freetop) # update velocity vz - update_vz!(vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, + update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) # update stresses σxx and σzz - update_σxxσzz!(σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half, + update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half, psi.ψ_∂vx∂x,psi.ψ_∂vz∂z,b_z,a_x_half,a_z,freetop) # update stress σxz - update_σxz!(σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half, + update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half, psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index 1370112..c99ab66 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -3,5 +3,7 @@ abstract type ElasticWaveSimul{N} <: WaveSimul{N} end abstract type ElasticIsoWaveSimul{N} <: ElasticWaveSimul{N} end + abstract type ElasticMaterialProperties{N} <: MaterialProperties{N} end + abstract type AbstrElasticIsoMaterialProperties{N} <: ElasticMaterialProperties{N} end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index c39ff1b..0b10ea1 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -1,22 +1,34 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) + @views function swforward_1shot!( ::CPMLBoundaryCondition, wavsim::ElasticIsoCPMLWaveSimul{N}, - possrcs::Matrix{<:Integer}, - posrecs::Matrix{<:Integer}, - srctf, - recs -) where {N} - + shot::Shot + # possrcs::Matrix{<:Integer}, + # posrecs::Matrix{<:Integer}, + # srctf, + # recs + ) where {N} + + @show propertynames(wavsim,true) + + # scale source time function, etc. + # find nearest grid points indexes for both sources and receivers + possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) + posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + + srctf = shot.srcs.tf + momtens = shot.srcs.momtens + # Numerics nt = wavsim.nt # Wrap sources and receivers arrays possrcs_bk = wavsim.backend.Data.Array(possrcs) posrecs_bk = wavsim.backend.Data.Array(posrecs) srctf_bk = wavsim.backend.Data.Array(srctf) - traces_bk = wavsim.backend.Data.Array(recs.seismograms) + traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) ## ONLY 2D for now!!! Mxx = wavsim.backend.Data.Array(momtens.Mxx) @@ -29,8 +41,14 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Time loop for it in 1:nt # Compute one forward step - wavsim.backend.forward_onestep_CPML!(wavsim, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it, - freetop, save_trace) + wavsim.backend.forward_onestep_CPML!(wavsim, + possrcs_bk, + srctf_bk, + posrecs_bk, + traces_bk, + it, + Mxx,Mzz,Mxz, + save_trace=true) # wavsim.velpartic..., wavsim.stress..., # wavsim.λ_ihalf diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index e773b7f..3c5586f 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -53,12 +53,6 @@ end end -@views function scale_srctf(wavsim::ElasticIsoWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} - scaled_tf = copy(srctf) - return scaled_tf -end - - ########################################################### @@ -323,13 +317,13 @@ end @views function reset!(wavsim::ElasticIsoCPMLWaveSimul{N}) where {N} # Reset computational arrays - for p in fieldnames(wavsim.velpartic) + for p in propertynames(wavsim.velpartic) getfield(wavsim.velpartic,p) .= 0.0 end - for p in fieldnames(wavsim.stress) + for p in propertynames(wavsim.stress) getfield(wavsim.stress,p) .= 0.0 end - for p in fieldnames(wavsim.ψ) + for p in propertynames(wavsim.ψ) getfield(wavsim.ψ, p) .= 0.0 end @@ -341,7 +335,7 @@ end for p in eachindex(wavsim.grad) wavsim.grad[p] .= 0.0 end - for p in fieldnames(wavsim.ψ_adj) + for p in propertynames(wavsim.ψ_adj) getfield(wavsim.ψ_adj, p) .= 0.0 end end From 5a938bf38d6c4742f4d27e3468a54c1e763c349f Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Sun, 14 Jan 2024 23:42:29 +0100 Subject: [PATCH 015/111] update --- .../backends/Elastic2D_Iso_CPML_Serial.jl | 47 +++++++++++-------- src/models/elastic/ela_forward.jl | 5 +- src/models/elastic/ela_models.jl | 31 +++++++----- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 61a1ee8..37104d6 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -239,7 +239,8 @@ function update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂ end -function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, +function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, + vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, b_x_half,b_z,a_x_half,a_z,freetop) if freetop==true @@ -338,7 +339,9 @@ function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ end -function update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half,a_x,a_z_half, +function update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, + μ_jhalf,b_x,b_z_half, + ψ_∂vx∂z,ψ_∂vz∂x,a_x,a_z_half, freetop) if freetop @@ -411,10 +414,10 @@ end function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, - possrcs_a::Array{<:Integer,2}, - srctf_a::Matrix{<:Real}, - posrecs_a::Array{<:Integer,2}, - traces_a::Array{<:Real}, + possrcs_bk::Array{<:Integer,2}, + srctf_bk::Matrix{<:Real}, + posrecs_bk::Array{<:Integer,2}, + traces_bk::Array{<:Real}, it::Integer, Mxx::Vector{<:Real}, Mzz::Vector{<:Real}, @@ -468,38 +471,42 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) # update stresses σxx and σzz - update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz,vx,vz,dt,λ_ihalf,μ_ihalf,b_x_half, - psi.ψ_∂vx∂x,psi.ψ_∂vz∂z,b_z,a_x_half,a_z,freetop) + update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, + vx,vz,dt,λ_ihalf,μ_ihalf, + psi.ψ_∂vx∂x,psi.ψ_∂vz∂z, + b_x_half,b_z,a_x_half,a_z,freetop) # update stress σxz - update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt,μ_jhalf,b_x,b_z_half, + update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, + μ_jhalf,b_x,b_z_half, psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) # inject sources - inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_a, dt, possrcs, it) + inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_bk, dt, possrcs_bk, it) # record receivers if save_trace - record_receivers!(vx,vz,traces_a, posrecs, it) + record_receivers!(vx,vz,traces_bk, posrecs_bk, it) end return end -function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_a, dt, possrcs, it) +function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) ## Inject the source as stress from moment tensor ## See Igel 2017 Computational Seismology (book) page 31, 2.6.1 + lensrctf = length(srctf_bk) if it<=lensrctf - for s in axes(possrcs, 1) - irec = possrcs[s, 1] - jrec = possrcs[s, 2] + for s in axes(possrcs_bk, 1) + isrc = possrcs_bk[s, 1] + jsrc = possrcs_bk[s, 2] - σxx[isrc,jsrc] += Mxx[s] * srctf_a[it] * dt - σzz[isrc,jsrc] += Mzz[s] * srctf_a[it] * dt - σxz[isrc,jsrc] += Mxz[s] * srctf_a[it] * dt + σxx[isrc,jsrc] += Mxx[s] * srctf_bk[it] * dt + σzz[isrc,jsrc] += Mzz[s] * srctf_bk[it] * dt + σxz[isrc,jsrc] += Mxz[s] * srctf_bk[it] * dt end end @@ -507,7 +514,7 @@ function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_a, dt, possrcs, it) end -function record_receivers!(vx,vz,traces_a, posrecs, it) +function record_receivers!(vx,vz,traces_bk, posrecs, it) for ir in axes(posrecs, 1) irec = posrecs[ir, 1] @@ -515,7 +522,7 @@ function record_receivers!(vx,vz,traces_a, posrecs, it) # interpolate velocities on the same grid? N=2 # 2D for i=1:N - traces_a[it,i,ir] = vx[irec, jrec] + traces_bk[it,i,ir] = vx[irec, jrec] end end return diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 0b10ea1..e7fa354 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -77,8 +77,9 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Save snapshot if snapenabled(wavsim) && it % wavsim.snapevery == 0 - @debug @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) - wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)] .= Array(pcur) + error("Snapshot for elastic not yet implemented...") + #@debug @sprintf("Snapping iteration: %d", it) + #wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)] .= Array(pcur) end end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 3c5586f..8972ce5 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -66,19 +66,26 @@ struct Elasticψdomain2D{T<:AbstractFloat} ψ_∂vz∂x::Array{T,2} ψ_∂vx∂z::Array{T,2} - function Elasticψdomain2D(backend,gridsize,N,halo) + function Elasticψdomain2D(backend,gridsize,halo) + @assert length(gridsize)==2 ψ_gridsize = [gridsize...] - ψ_gridsize[N] = 2*halo - - ψ_∂σxx∂x = backend.zeros(ψ_gridsize...) - ψ_∂σxz∂z = backend.zeros(ψ_gridsize...) - ψ_∂σxz∂x = backend.zeros(ψ_gridsize...) - ψ_∂σzz∂z = backend.zeros(ψ_gridsize...) - ψ_∂vx∂x = backend.zeros(ψ_gridsize...) - ψ_∂vz∂z = backend.zeros(ψ_gridsize...) - ψ_∂vz∂x = backend.zeros(ψ_gridsize...) - ψ_∂vx∂z = backend.zeros(ψ_gridsize...) + + @show gridsize,ψ_gridsize + gs1,gs2 = copy(ψ_gridsize),copy(ψ_gridsize) + gs1[1] = 2*halo + gs2[2] = 2*halo + + @show gs1,gs2 + + ψ_∂σxx∂x = backend.zeros( gs1...) + ψ_∂σxz∂z = backend.zeros( gs2...) + ψ_∂σxz∂x = backend.zeros( gs1...) + ψ_∂σzz∂z = backend.zeros( gs2...) + ψ_∂vx∂x = backend.zeros( gs1...) + ψ_∂vz∂z = backend.zeros( gs2...) + ψ_∂vz∂x = backend.zeros( gs1...) + ψ_∂vx∂z = backend.zeros( gs2...) T = eltype(ψ_∂σxx∂x) return new{T}(ψ_∂σxx∂x, @@ -205,7 +212,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} ## if N==2 # 2D - ψ = Elasticψdomain2D(backend,gridsize,N,halo) + ψ = Elasticψdomain2D(backend,gridsize,halo) else error("Only elastic 2D is currently implemented.") end From 395c0b1f9edbe946e3ecaeaa7d97dfdc837e2afe Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Mon, 15 Jan 2024 16:33:20 +0100 Subject: [PATCH 016/111] wip... working without cpml --- src/models/cpmlcoeffs.jl | 2 -- .../backends/Elastic2D_Iso_CPML_Serial.jl | 17 ++++++++++++++--- src/models/elastic/ela_forward.jl | 12 +++++------- src/models/elastic/ela_models.jl | 3 --- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 9dccf17..b5a8362 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -41,8 +41,6 @@ function compute_CPML_coefficientsAxis!( a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") - @show size(a_hl),size(a_hr),size(cpmlcoeffs.a_h) - copyto!(cpmlcoeffs.a, vcat(a_l,a_r)) copyto!(cpmlcoeffs.a_h, vcat(a_hl,a_hr)) copyto!(cpmlcoeffs.b, vcat(b_l,b_r)) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 37104d6..16d3701 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -158,7 +158,7 @@ function update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_ # update velocity vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) - + end end return @@ -465,10 +465,15 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, # update velocity vx update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, - b_x,b_z,a_x,a_z,freetop) + b_x,b_z,a_x,a_z,freetop) # update velocity vz update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) + #@show it,extrema(vx),extrema(vz) + if any(isnan.(vx)) || any(isnan.(vz)) + error("isnan vx or vz") + end + # update stresses σxx and σzz update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, @@ -479,10 +484,11 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, μ_jhalf,b_x,b_z_half, psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) - +#@show it,extrema(σxx),extrema(σzz),extrema(σxz) # inject sources inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_bk, dt, possrcs_bk, it) +#@show it,extrema(srctf_bk[it]) # record receivers if save_trace @@ -504,9 +510,14 @@ function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, isrc = possrcs_bk[s, 1] jsrc = possrcs_bk[s, 2] + # @show "A $it",σxx[isrc,jsrc],σzz[isrc,jsrc],σxz[isrc,jsrc] + # @show dt,srctf_bk[it],Mxx[s],Mzz[s],Mxz[s] + σxx[isrc,jsrc] += Mxx[s] * srctf_bk[it] * dt σzz[isrc,jsrc] += Mzz[s] * srctf_bk[it] * dt σxz[isrc,jsrc] += Mxz[s] * srctf_bk[it] * dt + + # @show "B $it",σxx[isrc,jsrc],σzz[isrc,jsrc],σxz[isrc,jsrc] end end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index e7fa354..71929ce 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -12,8 +12,6 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # recs ) where {N} - @show propertynames(wavsim,true) - # scale source time function, etc. # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) @@ -64,13 +62,13 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Print timestep info if it % wavsim.infoevery == 0 - # # Move the cursor to the beginning to overwrite last line + # Move the cursor to the beginning to overwrite last line # ter = REPL.Terminals.TTYTerminal("", stdin, stdout, stderr) # REPL.Terminals.clear_line(ter) # REPL.Terminals.cmove_line_up(ter) - @debug @sprintf( - "Iteration: %d, simulation time: %g [s]", - it, + @info @sprintf( + "Iteration: %d/%d, simulation time: %g [s]", + it,nt, wavsim.dt * (it - 1) ) end @@ -84,6 +82,6 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC end # Save traces - copyto!(recs.seismograms, traces_bk) + copyto!(shot.recs.seismograms, traces_bk) return end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 8972ce5..021dbea 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -71,13 +71,10 @@ struct Elasticψdomain2D{T<:AbstractFloat} @assert length(gridsize)==2 ψ_gridsize = [gridsize...] - @show gridsize,ψ_gridsize gs1,gs2 = copy(ψ_gridsize),copy(ψ_gridsize) gs1[1] = 2*halo gs2[2] = 2*halo - @show gs1,gs2 - ψ_∂σxx∂x = backend.zeros( gs1...) ψ_∂σxz∂z = backend.zeros( gs2...) ψ_∂σxz∂x = backend.zeros( gs1...) From ad58e0ea49f0b06a9450200bbde540a1b7c3f182 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Tue, 16 Jan 2024 13:32:33 +0100 Subject: [PATCH 017/111] testing snapshots --- .../backends/Elastic2D_Iso_CPML_Serial.jl | 98 +++++++++---------- src/models/elastic/ela_forward.jl | 22 +++-- 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 16d3701..1333d7f 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -123,14 +123,26 @@ function update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_ # C-PML stuff ##======================= # x boundaries - if i <= halo + + # con1 = (i <= halo) + # con2 = (i >= nx - halo + 1) + # if con1 || con2 + # ii = i + # if con2 + # ii = i - (nx - 2*halo) + 1 + # end + # # left or right boundary + # ψ_∂σxx∂x[ii,j] = b_x[ii] * ψ_∂σxx∂x[ii,j] + a_x[ii] * ∂σxx∂x_bkw + # ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii,j] + # end + + if i <= halo # # left boundary ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] elseif i >= nx - halo + 1 # right boundary - # ii = i - (nx - halo) + 1 - ii = i - (nx - 2*halo) + 1 # == ii = i - (nx - halo) + 1 + halo + ii = i - (nx - 2*halo) ψ_∂σxx∂x[ii,j] = b_x[ii] * ψ_∂σxx∂x[ii,j] + a_x[ii] * ∂σxx∂x_bkw ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii,j] end @@ -141,17 +153,16 @@ function update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_ ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] elseif j >= nz - halo + 1 # bottom boundary - # jj = j - (nz - halo) + 1 - jj = j - (nz - 2*halo) + 1 + jj = j - (nz - 2*halo) ψ_∂σxz∂z[i,jj] = b_z[jj] * ψ_∂σxz∂z[i,jj] + a_z[jj] * ∂σxz∂z_bkw ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,jj] end ##======================= - # # C-PML stuff + # # C-PML stuff + # # DO NOT delete this part! # ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw # ψ_∂σxz∂z[i,j] = b_z[j] * ψ_∂σxz∂z[i,j] + a_z[j] * ∂σxz∂z_bkw - # # derivatives # ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] # ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] @@ -198,35 +209,33 @@ function update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂ # C-PML stuff ##======================= # x boundaries - if i <= halo + 1 + if i <= halo # left boundary - ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] - elseif i >= nx - halo + elseif i >= nx - halo + 1 # right boundary - # ii = i - (nx - halo) + 1 - ii = i - (nx - 2*halo) + 1 - ψ_∂σxz∂x[ii,j] = b_x_half[ii] * ψ_∂σxz∂x[ii,j] + ψ_∂σxz∂x[ii,j] + a_x_half[ii]*∂σxz∂x_fwd + ii = i - (nx - 2*halo) + ψ_∂σxz∂x[ii,j] = b_x_half[ii] * ψ_∂σxz∂x[ii,j] + a_x_half[ii]*∂σxz∂x_fwd ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[ii,j] end # y boundaries - if j <= halo +1 && freetop==false # + 1 + if j <= halo && freetop==false # + 1 # top boundary ψ_∂σzz∂z[i,j] = b_z_half[j] * ψ_∂σzz∂z[i,j] + a_z_half[j]*∂σzz∂z_fwd ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] - elseif j >= nz - halo + elseif j >= nz - halo + 1 # bottom boundary - # jj = j - (nz - halo) + 1 - jj = j - (nz - 2*halo) + 1 + jj = j - (nz - 2*halo) ψ_∂σzz∂z[i,jj] = b_z_half[jj] * ψ_∂σzz∂z[i,jj] + a_z_half[jj]*∂σzz∂z_fwd ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,jj] end ##======================= - # # C-PML stuff + # # C-PML stuff + # # DO NOT delete this part! # ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd # ψ_∂σzz∂z[i,j] = b_z_half[j] * ψ_∂σzz∂z[i,j] + a_z_half[j]*∂σzz∂z_fwd - # ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] # ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] @@ -292,14 +301,13 @@ function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, # C-PML stuff ##======================= # x boundaries - if i <= halo + 1 + if i <= halo # left boundary ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] - elseif i >= nx - halo + elseif i >= nx - halo + 1 # right boundary - # ii = i - (nx - halo) + 1 - ii = i - (nx - 2*halo) + 1 + ii = i - (nx - 2*halo) ψ_∂vx∂x[ii,j] = b_x_half[ii] * ψ_∂vx∂x[ii,j] + a_x_half[ii]*∂vx∂x_fwd ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[ii,j] end @@ -310,17 +318,16 @@ function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] elseif j >= nz - halo + 1 # bottom boundary - # jj = j - (nz - halo) + 1 - jj = j - (nz - 2*halo) + 1 + jj = j - (nz - 2*halo) ψ_∂vz∂z[i,jj] = b_z[jj] * ψ_∂vz∂z[i,jj] + a_z[jj]*∂vz∂z_bkd ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,jj] end ##======================= - # # C-PML stuff + # # C-PML stuff + # # DO NOT delete this part! # ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd # ψ_∂vz∂z[i,j] = b_z[j] * ψ_∂vz∂z[i,j] + a_z[j]*∂vz∂z_bkd - # ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] # ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] @@ -377,29 +384,27 @@ function update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] elseif i >= nx - halo + 1 # right boundary - # ii = i - (nx - halo) + 1 - ii = i - (nx - 2*halo) + 1 + ii = i - (nx - 2*halo) ψ_∂vz∂x[ii,j] = b_x[ii] * ψ_∂vz∂x[ii,j] + a_x[ii]*∂vz∂x_bkd ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[ii,j] end # y boundaries - if j <= halo +1 && freetop==false + if j <= halo && freetop==false # top boundary ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] - elseif j >= nz - halo + elseif j >= nz - halo + 1 # bottom boundary - #jj = j - (nz - halo) + 1 - jj = j - (nz - 2*halo) + 1 + jj = j - (nz - 2*halo) ψ_∂vx∂z[i,jj] = b_z_half[jj] * ψ_∂vx∂z[i,jj] + a_z_half[jj]*∂vx∂z_fwd ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,jj] end ##======================= - # # C-PML stuff + # # C-PML stuff + # # DO NOT delete this part! # ψ_∂vz∂x[i,j] = b_x[i] * ψ_∂vz∂x[i,j] + a_x[i]*∂vz∂x_bkd # ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd - # ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] # ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] @@ -469,11 +474,6 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, # update velocity vz update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) - #@show it,extrema(vx),extrema(vz) - if any(isnan.(vx)) || any(isnan.(vz)) - error("isnan vx or vz") - end - # update stresses σxx and σzz update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, @@ -484,15 +484,13 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, μ_jhalf,b_x,b_z_half, psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) -#@show it,extrema(σxx),extrema(σzz),extrema(σxz) # inject sources inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_bk, dt, possrcs_bk, it) -#@show it,extrema(srctf_bk[it]) # record receivers if save_trace - record_receivers!(vx,vz,traces_bk, posrecs_bk, it) + record_receivers2D!(vx,vz,traces_bk, posrecs_bk, it) end return @@ -525,22 +523,20 @@ function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, end -function record_receivers!(vx,vz,traces_bk, posrecs, it) +function record_receivers2D!(vx,vz,traces_bk, posrecs, it) for ir in axes(posrecs, 1) irec = posrecs[ir, 1] jrec = posrecs[ir, 2] # interpolate velocities on the same grid? - N=2 # 2D - for i=1:N - traces_bk[it,i,ir] = vx[irec, jrec] - end + traces_bk[it,1,ir] = vx[irec, jrec] + traces_bk[it,2,ir] = vz[irec, jrec] end return end -function correlate_gradient!( ) +#function correlate_gradient!( ) # _dt2 = 1 / dt^2 # nx, nz = size(curgrad) # for j in 1:nz @@ -548,8 +544,8 @@ function correlate_gradient!( ) # curgrad[i, j] = curgrad[i, j] + (adjcur[i, j] * (pcur[i, j] - 2.0 * pold[i, j] + pveryold[i, j]) * _dt2) # end # end - return -end + # return +#end ######################################### diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 71929ce..45157f5 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -28,10 +28,14 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC srctf_bk = wavsim.backend.Data.Array(srctf) traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) - ## ONLY 2D for now!!! - Mxx = wavsim.backend.Data.Array(momtens.Mxx) - Mzz = wavsim.backend.Data.Array(momtens.Mzz) - Mxz = wavsim.backend.Data.Array(momtens.Mxz) + if N==2 + ## ONLY 2D for now!!! + Mxx = wavsim.backend.Data.Array(momtens.Mxx) + Mzz = wavsim.backend.Data.Array(momtens.Mzz) + Mxz = wavsim.backend.Data.Array(momtens.Mxz) + elseif N==3 + error("swforward_1shot!(): Elastic 3D not yet implemented!") + end # Reset wavesim reset!(wavsim) @@ -75,9 +79,13 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Save snapshot if snapenabled(wavsim) && it % wavsim.snapevery == 0 - error("Snapshot for elastic not yet implemented...") - #@debug @sprintf("Snapping iteration: %d", it) - #wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)] .= Array(pcur) + #error("Snapshot for elastic not yet implemented...") + @debug @sprintf("Snapping iteration: %d", it) + dummyidxs = fill(Colon(), N) + # Vx + wavsim.snapshots[1][dummyidxs..., div(it, wavsim.snapevery)] .= Array(wavsim.velpartic.vx) + # Vz + wavsim.snapshots[2][dummyidxs..., div(it, wavsim.snapevery)] .= Array(wavsim.velpartic.vz) end end From 0db9a4780eec0baf64b253516a59b0983b3592fa Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Wed, 17 Jan 2024 11:04:18 +0100 Subject: [PATCH 018/111] bump version --- Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index f81588b..0e70294 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SeismicWaves" uuid = "f2cc81fa-a164-11e9-3f65-e3f851c759e3" authors = ["Andrea Zunino", "Giacomo Aloisi"] -version = "0.6.0" +version = "0.7.0" [deps] CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" @@ -13,7 +13,7 @@ ParallelStencil = "94395366-693c-11ea-3b26-d9b7aac5d958" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [compat] -julia = "1.7" +julia = "1.8" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" From b563688d641d5d081b0d30e95874e9796698e62d Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Fri, 19 Jan 2024 14:19:01 +0100 Subject: [PATCH 019/111] fix free surface mirroring --- .../backends/Elastic2D_Iso_CPML_Serial.jl | 84 ++++++++++--------- src/models/elastic/ela_forward.jl | 2 +- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 1333d7f..648ee87 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -93,8 +93,8 @@ zeros = Base.zeros -function update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, - freetop) +function update_4thord_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, + freetop) if freetop for j = 1:2 for i = 3:nx-1 @@ -103,7 +103,14 @@ function update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_ # σxx derivative only in x so no problem ∂σxx∂x_bkw = factx * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) # image, mirroring σxz[i,j-2] = -σxz[i,j+1], etc. - ∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) + #∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) + if j==1 + # j bwd-> -2 -1|0 1 (mirror -2 and -1) + ∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) + elseif j==2 + # j bwd-> -2|-1 0 1 (mirror only -2) + ∂σxz∂z_bkw = factz * ( -σxz[i,j] -27.0*σxz[i,j-1] +27.0*σxz[i,j] -σxz[i,j+1] ) + end # update velocity vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) @@ -177,8 +184,8 @@ end -function update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, - b_x_half,b_z_half,a_x_half,a_z_half,freetop) +function update_4thord_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, + b_x_half,b_z_half,a_x_half,a_z_half,freetop) if freetop for j = 1:2 @@ -188,7 +195,14 @@ function update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂ # σxz derivative only in x so no problem ∂σxz∂x_fwd = factx * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) # image, mirroring σzz[i,j-1] = -σxz[i,j+2], etc. - ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + #∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + if j==1 + # j fwd-> -1 0| 1 2 (mirror -2 and -1) + ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + elseif j==2 + # j fwd-> -1|0 1 2 (mirror only -1) + ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + end # update velocity (ρ has been interpolated in advance) vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) @@ -248,9 +262,9 @@ function update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂ end -function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, - vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, - b_x_half,b_z,a_x_half,a_z,freetop) +function update_4thord_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, + vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, + b_x_half,b_z,a_x_half,a_z,freetop) if freetop==true # σxx, σzz @@ -263,13 +277,12 @@ function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd ∂vz∂z_bkd = -(1.0-2.0*μ_ihalf[i,j]/λ_ihalf[i,j])*∂vx∂x_fwd # σxx - σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + - λ_ihalf[i,j] * dt * ∂vz∂z_bkd - + # σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd + σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j] - λ_ihalf[i,j] / (λ_ihalf[i,j] +2 +μ_ihalf[i,j]) + 2*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd # σzz σzz[i,j] = 0.0 # we are on the free surface! end - + # j=2: we are just below the surface (1/2) j = 2 for i = 2:nx-2 @@ -280,12 +293,10 @@ function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, ∂vz∂z_bkd = factz * ( 0.0 -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) # σxx σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + - λ_ihalf[i,j] * dt * ∂vz∂z_bkd - + λ_ihalf[i,j] * dt * ∂vz∂z_bkd # σzz σzz[i,j] = σzz[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt* ∂vz∂z_bkd + λ_ihalf[i,j] * dt * ∂vx∂x_fwd - end end @@ -346,7 +357,7 @@ function update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, end -function update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, +function update_4thord_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, μ_jhalf,b_x,b_z_half, ψ_∂vx∂z,ψ_∂vz∂x,a_x,a_z_half, freetop) @@ -359,10 +370,8 @@ function update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, ∂vx∂z_fwd = factz * ( 0.0 -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) # vz derivative only in x so no problem ∂vz∂x_bkd = factx * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) - # σxz σxz[i,j] = σxz[i,j] + μ_jhalf[i,j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) - end end @@ -469,24 +478,27 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, factz = 1.0/(24.0*dz) # update velocity vx - update_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, - b_x,b_z,a_x,a_z,freetop) + update_4thord_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, + b_x,b_z,a_x,a_z,freetop) # update velocity vz - update_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, - psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) + update_4thord_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, + psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) + + # inject sources (external body force) + #inject_bodyforce_sources!(vx,vz,fx,fz,srctf_bk, dt, possrcs_bk,it) # update stresses σxx and σzz - update_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, - vx,vz,dt,λ_ihalf,μ_ihalf, - psi.ψ_∂vx∂x,psi.ψ_∂vz∂z, - b_x_half,b_z,a_x_half,a_z,freetop) + update_4thord_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, + vx,vz,dt,λ_ihalf,μ_ihalf, + psi.ψ_∂vx∂x,psi.ψ_∂vz∂z, + b_x_half,b_z,a_x_half,a_z,freetop) # update stress σxz - update_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, - μ_jhalf,b_x,b_z_half, - psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) + update_4thord_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, + μ_jhalf,b_x,b_z_half, + psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) - # inject sources - inject_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_bk, dt, possrcs_bk, it) + # inject sources (moment tensor type of internal force) + inject_momten_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_bk, dt, possrcs_bk, it) # record receivers if save_trace @@ -497,7 +509,7 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, end -function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) +function inject_momten_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) ## Inject the source as stress from moment tensor ## See Igel 2017 Computational Seismology (book) page 31, 2.6.1 @@ -508,16 +520,10 @@ function inject_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, isrc = possrcs_bk[s, 1] jsrc = possrcs_bk[s, 2] - # @show "A $it",σxx[isrc,jsrc],σzz[isrc,jsrc],σxz[isrc,jsrc] - # @show dt,srctf_bk[it],Mxx[s],Mzz[s],Mxz[s] - σxx[isrc,jsrc] += Mxx[s] * srctf_bk[it] * dt σzz[isrc,jsrc] += Mzz[s] * srctf_bk[it] * dt σxz[isrc,jsrc] += Mxz[s] * srctf_bk[it] * dt - - # @show "B $it",σxx[isrc,jsrc],σzz[isrc,jsrc],σxz[isrc,jsrc] end - end return end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 45157f5..4bf5ada 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -71,7 +71,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # REPL.Terminals.clear_line(ter) # REPL.Terminals.cmove_line_up(ter) @info @sprintf( - "Iteration: %d/%d, simulation time: %g [s]", + "Iteration: %d/%d, simulation time: %g s", it,nt, wavsim.dt * (it - 1) ) From 2703a4c871ba6bef60f7f2aed4fc8708d24365f2 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Fri, 19 Jan 2024 15:30:04 +0100 Subject: [PATCH 020/111] fix free surface, again... --- src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl | 6 +++--- src/models/elastic/ela_models.jl | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 648ee87..108c980 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -201,7 +201,7 @@ function update_4thord_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) elseif j==2 # j fwd-> -1|0 1 2 (mirror only -1) - ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] -27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) end # update velocity (ρ has been interpolated in advance) vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) @@ -278,7 +278,7 @@ function update_4thord_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, ∂vz∂z_bkd = -(1.0-2.0*μ_ihalf[i,j]/λ_ihalf[i,j])*∂vx∂x_fwd # σxx # σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd - σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j] - λ_ihalf[i,j] / (λ_ihalf[i,j] +2 +μ_ihalf[i,j]) + 2*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j] - λ_ihalf[i,j] / (λ_ihalf[i,j]+2+μ_ihalf[i,j]) + 2*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd # σzz σzz[i,j] = 0.0 # we are on the free surface! end @@ -295,7 +295,7 @@ function update_4thord_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd # σzz - σzz[i,j] = σzz[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt* ∂vz∂z_bkd + + σzz[i,j] = σzz[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vz∂z_bkd + λ_ihalf[i,j] * dt * ∂vx∂x_fwd end end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 021dbea..101d68b 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -30,11 +30,14 @@ function check_numerics( min_ppw::Integer=10 ) # Check points per wavelengh - vel_min = get_minimum_func(wavsim)(sqrt.(wavsim.matprop.μ ./ wavsim.matprop.ρ)) # min Vs + # min Vs + vel_min = get_minimum_func(wavsim)(sqrt.(wavsim.matprop.μ ./ wavsim.matprop.ρ)) h_max = maximum(wavsim.gridspacing) - ppw = vel_min / shot.srcs.domfreq / h_max + ppw = vel_min / (shot.srcs.domfreq * h_max) # (shot.srcs.domfreq * h_max) ? @debug "Points per wavelength: $(ppw)" - @assert ppw >= min_ppw "Not enough points per wavelengh!" + @assert ppw >= min_ppw "Not enough points per wavelength!" + fmax = shot.srcs.domfreq + @debug "dh should be <= $(vel_min/(8*fmax)) " return end From 76851e909e187b9dddfee91f7f52b7f9473482bc Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Wed, 24 Jan 2024 17:48:25 +0100 Subject: [PATCH 021/111] wip: interpolate src and rec with a sinc --- src/models/elastic/ela_models.jl | 9 +- src/srcrec_interpolation.jl | 190 +++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 src/srcrec_interpolation.jl diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 101d68b..7cd1736 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -33,11 +33,12 @@ function check_numerics( # min Vs vel_min = get_minimum_func(wavsim)(sqrt.(wavsim.matprop.μ ./ wavsim.matprop.ρ)) h_max = maximum(wavsim.gridspacing) - ppw = vel_min / (shot.srcs.domfreq * h_max) # (shot.srcs.domfreq * h_max) ? + fmax = shot.srcs.domfreq * 2.0 + ppw = vel_min / (fmax * h_max) @debug "Points per wavelength: $(ppw)" - @assert ppw >= min_ppw "Not enough points per wavelength!" - fmax = shot.srcs.domfreq - @debug "dh should be <= $(vel_min/(8*fmax)) " + + dh0 = round((vel_min/(min_ppw*fmax)),digits=2) + @assert ppw >= min_ppw "Not enough points per wavelength (assuming fmax = 2*domfreq)! \n [$(round(ppw,digits=1)) instead of >= $min_ppw]\n Grid spacing should be <= $dh0" return end diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl new file mode 100644 index 0000000..b6df6c4 --- /dev/null +++ b/src/srcrec_interpolation.jl @@ -0,0 +1,190 @@ + + +using SpecialFunctions + +##################################################################### + +""" + +Kaiser windowing function. + +# Parameters + +- `x`: coordinate of points +- `x0`: coordinate of source or receiver point +- `b`: 'b' coefficient +- `r`: cut-off radius + +""" +function kaiser(x::Vector, x0::Real, b::Real, r::Real) + # Kaiser window function + # r is window half with + # Rule of thumb for finite diff.: + # b=4.14 b=6.31 + # r = 4.0*dx + w=zeros(length(x)) + for i=1:length(x) + xcur = x[i]-x0 + if -r<=xcur<=r + den = 1.0/besseli(0,b) + w[i] = den*besseli(0, b*(sqrt.(1 -(xcur/r)^2))) + else + w[i] = 0.0 + end + end + return w +end + +##################################################################### + +""" + +Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. + +# Parameters + +- `xstart`: origin coordinate of the grid +- `Δx`: grid spacing +- `kind`: :monopole or :dipole, i.e., using sinc or derivative of sinc +- `npts` (optional): half-number of grid points for the window +- `beta` (optional): 'beta' parameter for the Kaiser windowing function + +""" + +function coeffsinc1D(xstart::Real,Δx::Real,xcenter::Real, kind::Symbol ; + npts::Int64=4, beta::Union{Nothing,Real}=nothing) + ## Coefficients for sinc interpolation + ## in 1D + ## xstart is the x coordinate of first node in the regular grid + ## + ## Rule of thumb for npts==4 [Hicks 2002, Geophysics]: + ## beta=4.14 for monopoles, + ## beta=4.40 for dipoles + ### + ### Julia: sinc(x) = + ### \sin(\pi x) / (\pi x) if x \neq 0, and 1 if x = 0 + ### + @assert xcenter >= xstart + + if beta==nothing + if kind==:monopole + beta = 4.14 + elseif kind==:dipole + beta = 4.40 + end + end + + radius = npts*Δx + ## Assuming x from grid starts at xstart + xh = (xcenter-xstart)/Δx + ix = floor(Int64,xh+1) + if mod((xcenter-xstart),Δx) == 0.0 + ixsta = ix-npts + ixend = ix+npts + else + ixsta = ix-npts+1 + ixend = ix+npts + end + x = [xstart+Δx*(i-1) for i=ixsta:ixend] + indexes = ixsta:ixend + + if kind==:monopole + # interpolating sinc(x) = sin(pi*x)/(pi*x) see Julia definition + intrpsinc = sinc.((x.-xcenter)./Δx) # factor 1/Δx ?? + + elseif kind==:dipole + # derivative of sinc + # cosc(x) is the derivative of sinc(x) in Julia + intrpsinc = cosc.((x.-xcenter)./Δx) + + else + error("coeffsinc1d(): Wrong argument 'kind'.") + end + # apply Kaiser windowing + kaix = kaiser(x,xcenter,beta,radius) + itpfun = kaix.*intrpsinc + # return also indices of window (as a range) + return itpfun,indexes +end +# ## test: +# begin +# xstart = 12.0 +# x0 = 15.75 +# Δx = 0.5 +# x = [(i-1)*Δx+xstart for i=1:15] +# coe,idxs = coeffsinc1d(xstart,Δx,x0,:monopole) +# scatterlines(idxs,coe) +# @show idxs +# Any[1:length(x) x] +# end + +##################################################################### + +function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real,zcenter::Real, + nx::Integer,nz::Integer,kind::Vector{Symbol} ; + npts::Int64=4, beta::Union{Nothing,Real}=nothing) + + ## Calculate the 2D array of coefficients + xcoe,xidx = coeffsinc1D(xstart,Δx,xcenter,kind[1]) + zcoe,zidx = coeffsinc1D(zstart,Δz,zcenter,kind[2]) + + function reflectcoeffsinc(coe,idx,n) + if idx[1] < 1 + # We are before the edge + nab = count( idx.<1 ) + # get the "reflected" coefficients + reflcoe = coe[nab:-1:1] + # Create a new set of indices excluding those above the surface + idx = idx[nab+1:end] + # Hicks 2002 Geophysics + # Subtract coefficients past the edge + coe[nab+1:2*nab] .-= reflcoe + # Create a new set of coefficients excluding those above the surface + coe = coe[nab+1:end] + elseif idx[end] > n + # We are past the edge + nab = count( idx.>n ) + # get the "reflected" coefficients + reflcoe = coe[end:-1:end-nab+1] + # Create a new set of indices excluding those above the surface + idx = idx[1:end-nab] + # Hicks 2002 Geophysics + # Subtract coefficients past the edge + coe[end-2*nab+1:end-nab] .-= reflcoe + # Create a new set of coefficients excluding those above the surface + coe = coe[1:end-nab] + end + return coe,idx + end + + ## Crop coefficients if they go beyond model edges + xcoe,xidx = reflectcoeffsinc(xcoe,xidx,nx) + zcoe,zidx = reflectcoeffsinc(zcoe,zidx,nz) + + # tensor product of x and y + xzcoeff = zeros(typeof(xcenter),length(xcoe),length(zcoe)) + for j in eachindex(zcoe) + for i in eachindex(xcoe) + xzcoeff[i,j] = xcoe[i] * zcoe[j] + end + end + + return xidx,zidx,xzcoeff +end + +## test +# begin +# include("../src/srcrec_interpolation.jl") +# xstart = 12.0 +# x0 = 15.75 +# Δx = 0.5 +# zstart = 3.0 +# z0 = 6.12 +# Δz = 0.35 +# xidx,zidx,xzcoeff = coeffsinc2D(xstart,zstart,Δx,Δz,x0,z0,[:monopole,:monopole]) +# @show xidx +# @show zidx +# @show xzcoeff +# fig,ax,hm=heatmap(xzcoeff); Colorbar(fig[1,2],hm); fig +# end +##################################################################### From 4eefba18fd70029ed6809ec83ff61eba76f73e01 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Wed, 24 Jan 2024 17:57:57 +0100 Subject: [PATCH 022/111] wip: interp src and recs with sinc --- src/srcrec_interpolation.jl | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl index b6df6c4..823b5c1 100644 --- a/src/srcrec_interpolation.jl +++ b/src/srcrec_interpolation.jl @@ -50,7 +50,6 @@ Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or r - `beta` (optional): 'beta' parameter for the Kaiser windowing function """ - function coeffsinc1D(xstart::Real,Δx::Real,xcenter::Real, kind::Symbol ; npts::Int64=4, beta::Union{Nothing,Real}=nothing) ## Coefficients for sinc interpolation @@ -120,15 +119,31 @@ end ##################################################################### +""" + +Compute 2-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. + +# Parameters + +- `xstart`, `zstart`: origin coordinates of the grid +- `Δx`,`Δz` : grid spacing +- `xcenter`, `zcenter`: coordinates of source or receiver point +- `nx`,`nz`: grid size in x and y +- `kind`: vector of symbols :monopole or :dipole, i.e., using sinc or derivative of sinc +- `npts` (optional): half-number of grid points for the window +- `beta` (optional): 'beta' parameter for the Kaiser windowing function + +""" function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real,zcenter::Real, nx::Integer,nz::Integer,kind::Vector{Symbol} ; npts::Int64=4, beta::Union{Nothing,Real}=nothing) ## Calculate the 2D array of coefficients - xcoe,xidx = coeffsinc1D(xstart,Δx,xcenter,kind[1]) - zcoe,zidx = coeffsinc1D(zstart,Δz,zcenter,kind[2]) + xcoe,xidx = coeffsinc1D(xstart,Δx,xcenter,kind[1],npts=npts,beta=beta) + zcoe,zidx = coeffsinc1D(zstart,Δz,zcenter,kind[2],npts=npts,beta=beta) function reflectcoeffsinc(coe,idx,n) + if idx[1] < 1 # We are before the edge nab = count( idx.<1 ) @@ -141,6 +156,7 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real coe[nab+1:2*nab] .-= reflcoe # Create a new set of coefficients excluding those above the surface coe = coe[nab+1:end] + elseif idx[end] > n # We are past the edge nab = count( idx.>n ) @@ -154,6 +170,7 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real # Create a new set of coefficients excluding those above the surface coe = coe[1:end-nab] end + return coe,idx end @@ -161,7 +178,7 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real xcoe,xidx = reflectcoeffsinc(xcoe,xidx,nx) zcoe,zidx = reflectcoeffsinc(zcoe,zidx,nz) - # tensor product of x and y + # tensor product of coeff. in x and z xzcoeff = zeros(typeof(xcenter),length(xcoe),length(zcoe)) for j in eachindex(zcoe) for i in eachindex(xcoe) @@ -181,7 +198,7 @@ end # zstart = 3.0 # z0 = 6.12 # Δz = 0.35 -# xidx,zidx,xzcoeff = coeffsinc2D(xstart,zstart,Δx,Δz,x0,z0,[:monopole,:monopole]) +# xidx,zidx,xzcoeff = coeffsinc2D(xstart,zstart,Δx,Δz,x0,z0,nx,nz,[:monopole,:monopole]) # @show xidx # @show zidx # @show xzcoeff From c774286a916943b2b3bae1cb375e1fbaf504d143 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Thu, 25 Jan 2024 16:51:15 +0100 Subject: [PATCH 023/111] first src and rec interpolation with sinc --- Project.toml | 1 + src/SeismicWaves.jl | 5 + .../backends/Elastic2D_Iso_CPML_Serial.jl | 86 ++++++++---- src/models/elastic/ela_forward.jl | 127 ++++++++++++++---- src/solve.jl | 10 -- src/srcrec_interpolation.jl | 30 +++-- 6 files changed, 184 insertions(+), 75 deletions(-) diff --git a/Project.toml b/Project.toml index 0e70294..4c5c9bd 100644 --- a/Project.toml +++ b/Project.toml @@ -11,6 +11,7 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" ParallelStencil = "94395366-693c-11ea-3b26-d9b7aac5d958" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" [compat] julia = "1.8" diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 51aba98..fbfdf41 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -4,11 +4,13 @@ Module for generalized wave propagation solvers. module SeismicWaves using LinearAlgebra +using SpecialFunctions using Printf using ParallelStencil using Logging using DocStringExtensions + # main struct for wave simulation export WaveSimul export build_wavesim @@ -42,9 +44,12 @@ include("receivers.jl") include("shot.jl") include("checks.jl") include("boundarycond.jl") +include("srcrec_interpolation.jl") include("models/cpmlcoeffs.jl") + + # Acoustic include("models/acoustic/acou_abstract_types.jl") include("models/acoustic/acou_material_properties.jl") diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 108c980..ecd8013 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -428,15 +428,27 @@ end function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, - possrcs_bk::Array{<:Integer,2}, + srccoeij_bk::Array{<:Integer}, + srccoeval_bk::Array{<:Real}, + reccoeij_bk::Array{<:Integer}, + reccoeval_bk::Array{<:Real}, srctf_bk::Matrix{<:Real}, - posrecs_bk::Array{<:Integer,2}, traces_bk::Array{<:Real}, it::Integer, - Mxx::Vector{<:Real}, - Mzz::Vector{<:Real}, - Mxz::Vector{<:Real}; + Mxx_bk::Vector{<:Real}, + Mzz_bk::Vector{<:Real}, + Mxz_bk::Vector{<:Real}; save_trace::Bool=true) where {N} + # function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, + # possrcs_bk::Array{<:Integer,2}, + # srctf_bk::Matrix{<:Real}, + # posrecs_bk::Array{<:Integer,2}, + # traces_bk::Array{<:Real}, + # it::Integer, + # Mxx_bk::Vector{<:Real}, + # Mzz_bk::Vector{<:Real}, + # Mxz_bk::Vector{<:Real}; + # save_trace::Bool=true) where {N} @assert N==2 freetop = wavsim.freetop @@ -498,46 +510,72 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) # inject sources (moment tensor type of internal force) - inject_momten_sources!(σxx,σzz,σxz,Mxx,Mzz,Mxz, srctf_bk, dt, possrcs_bk, it) + inject_momten_sources2D!(σxx,σzz,σxz,Mxx_bk,Mzz_bk,Mxz_bk,srctf_bk,dt, + srccoeij_bk,srccoeval_bk,it) + #possrcs_bk,it) # record receivers if save_trace - record_receivers2D!(vx,vz,traces_bk, posrecs_bk, it) + record_receivers2D!(vx,vz,traces_bk,reccoeij_bk,reccoeval_bk,it) end return end - -function inject_momten_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) +function inject_momten_sources2D!(σxx,σzz,σxz,Mxx,Mzz,Mxz,srctf_bk,dt,srccoeij_bk,srccoeval_bk,it) +#function inject_momten_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) ## Inject the source as stress from moment tensor ## See Igel 2017 Computational Seismology (book) page 31, 2.6.1 lensrctf = length(srctf_bk) if it<=lensrctf - - for s in axes(possrcs_bk, 1) - isrc = possrcs_bk[s, 1] - jsrc = possrcs_bk[s, 2] - - σxx[isrc,jsrc] += Mxx[s] * srctf_bk[it] * dt - σzz[isrc,jsrc] += Mzz[s] * srctf_bk[it] * dt - σxz[isrc,jsrc] += Mxz[s] * srctf_bk[it] * dt + # total number of interpolation points + nsrcpts = size(srccoeij_bk,1) + # p runs on all interpolation points defined by the windowed sinc function + # s runs on all actual source locations as specified by user input + for p=1:nsrcpts + # [src_id, i, j] + s,isrc,jsrc = srccoeij_bk[p,:] + # update stresses on points computed from sinc interpolation + # scaled with the coefficients' values + σxx[isrc,jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σzz[isrc,jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σxz[isrc,jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] * dt end + + # for s in axes(possrcs_bk, 1) + # isrc = possrcs_bk[s, 1] + # jsrc = possrcs_bk[s, 2] + # σxx[isrc,jsrc] += Mxx[s] * srctf_bk[it] * dt + # σzz[isrc,jsrc] += Mzz[s] * srctf_bk[it] * dt + # σxz[isrc,jsrc] += Mxz[s] * srctf_bk[it] * dt + # end end return end -function record_receivers2D!(vx,vz,traces_bk, posrecs, it) +function record_receivers2D!(vx,vz,traces_bk,reccoeij_bk,reccoeval_bk,it) - for ir in axes(posrecs, 1) - irec = posrecs[ir, 1] - jrec = posrecs[ir, 2] - # interpolate velocities on the same grid? - traces_bk[it,1,ir] = vx[irec, jrec] - traces_bk[it,2,ir] = vz[irec, jrec] + # total number of interpolation points + nrecpts = size(reccoeij_bk,1) + # p runs on all interpolation points defined by the windowed sinc function + # s runs on all actual source locations as specified by user input + for p=1:nrecpts + # [src_id, i, j] + r,irec,jrec = reccoeij_bk[p,:] + # update traces by summing up values from all sinc interpolation points + traces_bk[it,1,r] += vx[irec,jrec] + traces_bk[it,2,r] += vz[irec,jrec] end + + # for ir in axes(posrecs, 1) + # irec = posrecs[ir, 1] + # jrec = posrecs[ir, 2] + # # interpolate velocities on the same grid? + # traces_bk[it,1,ir] = vx[irec, jrec] + # traces_bk[it,2,ir] = vz[irec, jrec] + # end return end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 4bf5ada..68d7eec 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -14,55 +14,84 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # scale source time function, etc. # find nearest grid points indexes for both sources and receivers - possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) - posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + # possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) + # posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + if N==2 + # interpolation coefficients for sources + srccoeij,srccoeval = spreadsrcrecinterp2D(wavsim.gridspacing,wavsim.gridsize, + shot.srcs.positions, + nptssinc=4,xstart=0.0,zstart=0.0) + # interpolation coefficients for receivers + reccoeij,reccoeval = spreadsrcrecinterp2D(wavsim.gridspacing,wavsim.gridsize, + shot.recs.positions, + nptssinc=4,xstart=0.0,zstart=0.0) + elseif N==3 + error("swforward_1shot!(): Elastic 3D not yet implemented!") + end + + # source time function srctf = shot.srcs.tf + # moment tensors momtens = shot.srcs.momtens # Numerics nt = wavsim.nt + # Wrap sources and receivers arrays - possrcs_bk = wavsim.backend.Data.Array(possrcs) - posrecs_bk = wavsim.backend.Data.Array(posrecs) + + # possrcs_bk = wavsim.backend.Data.Array(possrcs) + # posrecs_bk = wavsim.backend.Data.Array(posrecs) + + srccoeij_bk = wavsim.backend.Data.Array(srccoeij) + srccoeval_bk = wavsim.backend.Data.Array(srccoeval) + reccoeij_bk = wavsim.backend.Data.Array(reccoeij) + reccoeval_bk = wavsim.backend.Data.Array(reccoeval) + srctf_bk = wavsim.backend.Data.Array(srctf) traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) if N==2 ## ONLY 2D for now!!! - Mxx = wavsim.backend.Data.Array(momtens.Mxx) - Mzz = wavsim.backend.Data.Array(momtens.Mzz) - Mxz = wavsim.backend.Data.Array(momtens.Mxz) + Mxx_bk = wavsim.backend.Data.Array(momtens.Mxx) + Mzz_bk = wavsim.backend.Data.Array(momtens.Mzz) + Mxz_bk = wavsim.backend.Data.Array(momtens.Mxz) elseif N==3 error("swforward_1shot!(): Elastic 3D not yet implemented!") end # Reset wavesim reset!(wavsim) + # Zeros traces (there is a summation in record_receivers2D!() + traces_bk .= 0.0 # Time loop for it in 1:nt - # Compute one forward step - wavsim.backend.forward_onestep_CPML!(wavsim, - possrcs_bk, - srctf_bk, - posrecs_bk, - traces_bk, - it, - Mxx,Mzz,Mxz, - save_trace=true) - - # wavsim.velpartic..., wavsim.stress..., - # wavsim.λ_ihalf - # wavsim.ρ, wavsim.ρ_ihalf_jhalf, - # wavsim.μ, wavsim.μ_ihalf, wavsim.μ_jhalf, - # wavsim.dt, wavsim.gridspacing..., - # wavsim.ψ..., - # wavsim.a_coeffs..., - # wavsim.b_coeffs..., - # Mxx,Mzz,Mxz, - # possrcs_a, srctf_a, posrecs_a, traces_a, it, - # freetop, save_trace) + + if N==2 + # Compute one forward step + wavsim.backend.forward_onestep_CPML!(wavsim, + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + traces_bk, + it, + Mxx_bk,Mzz_bk,Mxz_bk, + save_trace=true) + # # Compute one forward step + # wavsim.backend.forward_onestep_CPML!(wavsim, + # possrcs_bk, + # srctf_bk, + # posrecs_bk, + # traces_bk, + # it, + # Mxx_bk,Mzz_bk,Mxz_bk, + # save_trace=true) + else + error("swforward_1shot!(): Elastic 3D not yet implemented!") + end # Print timestep info if it % wavsim.infoevery == 0 @@ -93,3 +122,45 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC copyto!(shot.recs.seismograms, traces_bk) return end + + + +function spreadsrcrecinterp2D(gridspacing::NTuple{N,Real},gridsize::NTuple{N,Integer}, + positions::Matrix{<:Real}; + nptssinc::Int=4,xstart::Real=0.0,zstart::Real=0.0) where N + + nloc = size(positions,1) + Ndim = size(positions,2) + @assert Ndim==2 + @assert N==Ndim + + Δx = gridspacing[1] + Δz = gridspacing[2] + nx,nz = gridsize[1:2] + + maxnumcoeff = nloc * (2*nptssinc+1)^Ndim + coeij_tmp = zeros(Int,maxnumcoeff,Ndim+1) + coeval_tmp = zeros(maxnumcoeff) + l=0 + for p=1:nloc + # extract x and z position for source or receiver p + xpos,zpos = positions[p,:] + # compute grid indices and values of sinc coefficients + xidx,zidx,xzcoeff = coeffsinc2D(xstart,zstart,Δx,Δz,xpos,zpos, + nx,nz,[:monopole,:monopole],npts=nptssinc) + for j=1:length(zidx) + for i=1:length(xidx) + l+=1 + # id, i, j indices + coeij_tmp[l,:] .= (p,xidx[i],zidx[j]) + # coefficients value + coeval_tmp[l] = xzcoeff[i,j] + end + end + end + # keep only the valid part of the arrays + coeij = coeij_tmp[1:l,:] + coeval = coeval_tmp[1:l] + + return coeij,coeval +end diff --git a/src/solve.jl b/src/solve.jl index 6a6938e..c025389 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -35,8 +35,6 @@ end # Shots loop for singleshot in shots - srcs = singleshot.srcs - recs = singleshot.recs # Initialize shot @info "Initializing shot" #possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) @@ -95,8 +93,6 @@ end # loop on the subset of shots per each WaveSimul for s in grpshots[w] singleshot = shots[s] - srcs = singleshot.srcs - recs = singleshot.recs # Initialize shot @info "Initializing shot" #possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) @@ -135,8 +131,6 @@ end # Compute total misfit for all shots totmisfitval = 0 for singleshot in shots - srcs = singleshot.srcs - recs = singleshot.recs @info "Checking invcov matrix" if typeof(wavsim)<:Vector{<:WaveSimul} check_invcov_matrix(wavsim[1], recs.invcov) @@ -176,8 +170,6 @@ end # Shots loop for (s,singleshot) in enumerate(shots) @info "Shot #$s" - srcs = singleshot.srcs - recs = singleshot.recs # Initialize shot @info "Initializing shot" #possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) @@ -249,8 +241,6 @@ end for s in grpshots[w] singleshot = shots[s] @info "Shot #$s" - srcs = singleshot.srcs - recs = singleshot.recs # Initialize shot @info "Initializing shot" #possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl index 823b5c1..f1a0cde 100644 --- a/src/srcrec_interpolation.jl +++ b/src/srcrec_interpolation.jl @@ -1,8 +1,6 @@ -using SpecialFunctions - -##################################################################### +#################################################################### """ @@ -50,7 +48,7 @@ Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or r - `beta` (optional): 'beta' parameter for the Kaiser windowing function """ -function coeffsinc1D(xstart::Real,Δx::Real,xcenter::Real, kind::Symbol ; +function coeffsinc1D(xstart::Real,Δx::Real,xcenter::Real, kind::Symbol, nx::Integer ; npts::Int64=4, beta::Union{Nothing,Real}=nothing) ## Coefficients for sinc interpolation ## in 1D @@ -63,7 +61,8 @@ function coeffsinc1D(xstart::Real,Δx::Real,xcenter::Real, kind::Symbol ; ### Julia: sinc(x) = ### \sin(\pi x) / (\pi x) if x \neq 0, and 1 if x = 0 ### - @assert xcenter >= xstart + @assert xcenter >= xstart + @assert xcenter <= (nx-1)*Δx+xstart if beta==nothing if kind==:monopole @@ -139,11 +138,14 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real npts::Int64=4, beta::Union{Nothing,Real}=nothing) ## Calculate the 2D array of coefficients - xcoe,xidx = coeffsinc1D(xstart,Δx,xcenter,kind[1],npts=npts,beta=beta) - zcoe,zidx = coeffsinc1D(zstart,Δz,zcenter,kind[2],npts=npts,beta=beta) - - function reflectcoeffsinc(coe,idx,n) - + xcoe,xidx = coeffsinc1D(xstart,Δx,xcenter,kind[1],nx,npts=npts,beta=beta) + zcoe,zidx = coeffsinc1D(zstart,Δz,zcenter,kind[2],nz,npts=npts,beta=beta) + + function reflectcoeffsinc(coe,idx,nmax) + # + # "Reflect" coefficients past the edge, i.e., mirror and subtract them + # from the internal ones + # if idx[1] < 1 # We are before the edge nab = count( idx.<1 ) @@ -157,9 +159,9 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real # Create a new set of coefficients excluding those above the surface coe = coe[nab+1:end] - elseif idx[end] > n + elseif idx[end] > nmax # We are past the edge - nab = count( idx.>n ) + nab = count( idx.>nmax ) # get the "reflected" coefficients reflcoe = coe[end:-1:end-nab+1] # Create a new set of indices excluding those above the surface @@ -174,7 +176,7 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real return coe,idx end - ## Crop coefficients if they go beyond model edges + ## Crop and reflect coefficients if they go beyond model edges [Hicks 2002, Geophysics] xcoe,xidx = reflectcoeffsinc(xcoe,xidx,nx) zcoe,zidx = reflectcoeffsinc(zcoe,zidx,nz) @@ -205,3 +207,5 @@ end # fig,ax,hm=heatmap(xzcoeff); Colorbar(fig[1,2],hm); fig # end ##################################################################### + +##################################################################### From bd5851def42428d8a11747c56a6dde3ffa31a576 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Fri, 26 Jan 2024 14:57:09 +0100 Subject: [PATCH 024/111] fix bug in PMLs --- src/models/cpmlcoeffs.jl | 91 ++++++++++++++++++- .../backends/Elastic2D_Iso_CPML_Serial.jl | 6 ++ 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index b5a8362..2580c9b 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -38,8 +38,15 @@ function compute_CPML_coefficientsAxis!( alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) npower = 2.0 # CPML power coefficient d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile - a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") - a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") + a_l, a_r, b_l, b_r = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :startongrd) + a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :starthalfgrd) + + # @show size(cpmlcoeffs.a),size(a_l),size(a_r) + # @show size(cpmlcoeffs.a_h),size(a_hl),size(a_hr) + # @show a_l + # @show a_hl + # @show a_r + # @show a_hr copyto!(cpmlcoeffs.a, vcat(a_l,a_r)) copyto!(cpmlcoeffs.a_h, vcat(a_hl,a_hr)) @@ -90,6 +97,79 @@ end # Default type constructor # CPMLCoefficients(halo) = CPMLCoefficients{Float64}(halo) + +function calc_Kab_CPML_staggeredgrid( + halo::Integer, + dt::Float64, + npower::Float64, + d0::Float64, + alpha_max_pml::Float64, + onwhere::Symbol; + K_max_pml::Union{Float64, Nothing}=nothing +)::Tuple{Array{<:Real}, Array{<:Real}, Array{<:Real}, Array{<:Real}} + @assert halo >= 0.0 + + Kab_size = halo + # shift for half grid coefficients + if onwhere == :starthalfgrd + shift_left = 0.0 + shift_right = 0.5 + elseif onwhere == :startongrd + shift_left = 0.5 + shift_right = 0.0 + else + error("Wrong onwhere parameter!") + end + + # distance from edge node + dist_left = collect(LinRange(shift_left, Kab_size+shift_left-1, Kab_size)) + dist_right = collect(LinRange(shift_right, Kab_size+shift_right-1, Kab_size)) + + if halo != 0 + normdist_left = reverse(dist_left) ./ (halo-0.5) + normdist_right = dist_right ./ (halo-0.5) + else + normdist_left = reverse(dist_left) + normdist_right = dist_right + end + + if K_max_pml === nothing + K_left = 1.0 + else + K_left = 1.0 .+ (K_max_pml - 1.0) .* (normdist_left .^ npower) + end + d_left = d0 .* (normdist_left .^ npower) + alpha_left = alpha_max_pml .* (1.0 .- normdist_left) + b_left = exp.(.-(d_left ./ K_left .+ alpha_left) .* dt) + a_left = d_left .* (b_left .- 1.0) ./ (K_left .* (d_left .+ K_left .* alpha_left)) + + if K_max_pml === nothing + K_right = 1.0 + else + K_right = 1.0 .+ (K_max_pml - 1.0) .* (normdist_right .^ npower) + end + d_right = d0 .* (normdist_right .^ npower) + alpha_right = alpha_max_pml .* (1.0 .- normdist_right) + b_right = exp.(.-(d_right ./ K_right .+ alpha_right) .* dt) + a_right = d_right .* (b_right .- 1.0) ./ (K_right .* (d_right .+ K_right .* alpha_right)) + + # println() + # @show onwhere + # @show dist_left + # @show dist_right + # @show normdist_left + # @show normdist_right + # @show a_left + # @show a_right + + if K_max_pml === nothing + return a_left, a_right, b_left, b_right + else + return a_left, a_right, b_left, b_right, K_left, K_right + end +end + + ##################################### function compute_CPML_coefficients!( @@ -105,7 +185,9 @@ function compute_CPML_coefficients!( alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) npower = 2.0 # CPML power coefficient d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile - if halo == 0 d0 = 0.0 end # fix for thickness == 0 generating NaNs + if halo == 0 # fix for thickness == 0 generating NaNs + d0 = 0.0 + end a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") @@ -119,6 +201,7 @@ function compute_CPML_coefficients!( copyto!(cpmlcoeffs.b_hr, b_hr) end +##################################### function calc_Kab_CPML( halo::Integer, @@ -181,3 +264,5 @@ function calc_Kab_CPML( return a_left, a_right, b_left, b_right, K_left, K_right end end + +##################################### diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index ecd8013..0bec042 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -485,6 +485,12 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, μ_ihalf = matprop.μ_ihalf μ_jhalf = matprop.μ_jhalf + # @show size(vx),size(vz) + # @show size(σxx),size(σzz),size(σxz) + # @show size(a_x),size(a_x_half) + # @show size(b_x),size(b_x_half) + # error("\nExiting...") + ## pre-scale coefficients factx = 1.0/(24.0*dx) factz = 1.0/(24.0*dz) From b0aafb6f2736d3c8565da2f008798b8187326e76 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Thu, 1 Feb 2024 15:33:34 +0100 Subject: [PATCH 025/111] add simple_example_elastic.jl --- examples/simple_example_elastic.jl | 358 +++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 examples/simple_example_elastic.jl diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl new file mode 100644 index 0000000..7d58c38 --- /dev/null +++ b/examples/simple_example_elastic.jl @@ -0,0 +1,358 @@ + +using Revise +using SeismicWaves +using LinearAlgebra +using GLMakie + +################################################################### +using Logging + +function exelaprob() + + ##======================================== + # time stuff + nt = 1500 #1500 + dt = 0.0008 + t = collect(Float64, range(0.0; step=dt, length=nt)) # seconds + #@show dt,(nt-1)*dt + + ##======================================== + # create a velocity model + nx = 380 # 211 + nz = 270 # 120 + dh = 4.5 # meters + @show nx,nz,nx*nz,dh + #@show (nx-1)*dh, (nz-1)*dh + + vp = zeros(nx, nz) + #vp .= 2700.0 + vp[nx÷2+10:end,:] .= 3100.0 + for i in 1:nx + for j in 1:nz + vp[i, j] = 2000.0 + dh * (j - 1) + end + end + @show extrema(vp) + vs = vp ./ sqrt(3) + + @show extrema(vp),extrema(vs) + + ρ = 2100.0 * ones(nx,nz) + μ = vs.^2 .* ρ # μ = Vs^2⋅ρ + λ = (vp.^2 .* ρ) .- (2 .* μ) # λ = vp^2 · ρ - 2μ + + + @show extrema(vp.^2) + @show extrema(vp.^2 .* ρ) + + + @show extrema(λ) + @show extrema(μ) + @show extrema(ρ) + matprop = ElasticIsoMaterialProperties(λ=λ,μ=μ,ρ=ρ) + + ##======================================== + # shots definition + nshots = 1 + shots = Vector{Shot}() #Pair{Sources, Receivers}}() + + for i in 1:nshots + # sources definition + nsrc = 1 + # sources x-position (in grid points) (different for every shot) + if nsrc==1 + ixsrc = [nx/2] + else + ixsrc = round.(Int, LinRange(30, nx - 31, nsrc)) + end + possrcs = zeros(nsrc, 2) # 1 source, 2 dimensions + for s=1:nsrc + possrcs[s, 1] = (ixsrc[i] - 1) * dh .+ 0.124 # x-positions in meters + possrcs[s, 2] = (nz/2)*dh .+ 0.124 #(nz/2) * dh # y-positions in meters + end + + # source time functions + f0 = 12.0 + t0 = 1.20 / f0 + srcstf = zeros(nt, nsrc) + Mxx = zeros(nsrc) + Mzz = zeros(nsrc) + Mxz = zeros(nsrc) + for s in 1:nsrc + srcstf[:, s] .= rickerstf.(t, t0, f0) + Mxx[s] = 5e10 #1.5e10 #1.5e6 #e20 + Mzz[s] = 3e10 #2.4e10 #1.5e6 #e20 + Mxz[s] = 2e10 #0.89e10 #0.0e6 #e20 + end + + srcs = MomentTensorSources(possrcs, srcstf, + MomentTensor2D(Mxx=Mxx,Mzz=Mzz,Mxz=Mxz), + f0) + #srcs = ScalarSources(possrcs, srcstf, f0) + + #@show srcs.positions + + # receivers definition + nrecs = 10 + # receivers x-positions (in grid points) (same for every shot) + ixrec = round.(Int, LinRange(40, nx-40, nrecs)) + posrecs = zeros(nrecs, 2) # 20 receivers, 2 dimensions + posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 # x-positions in meters + posrecs[:, 2] .= (nz/4)*dh .- 0.312 # (nz/2) * dh # y-positions in meters + + ndim = 2 + recs = VectorReceivers(posrecs, nt, ndim) + + #@show recs.positions + + # add pair as shot + push!(shots, Shot(; srcs=srcs, recs=recs)) # srcs => recs) + end + + @show shots[1].srcs.positions + @show shots[1].recs.positions + + ##============================================ + ## Input parameters for elastic simulation + snapevery = 5 + infoevery = 100 + freetop = true + halo = 20 + rcoef = 0.0001 + @show halo + @show rcoef + boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=freetop) + params = InputParametersElastic(nt, dt, [nx, nz], [dh, dh], boundcond) + + + ##=============================================== + ## compute the seismograms + snapshots = swforward!(params, + matprop, + shots; + parall=:serial, + infoevery=infoevery, + snapevery=snapevery) + + # ##=============================================== + # ## compute the gradient + # shots_grad = Vector{Shot}() + # for i in 1:nshots + # seis = shots[i].recs.seismograms + # nt = size(seis,1) + # recs_grad = ScalarReceivers(shots[i].recs.positions, nt; observed=seis, + # invcov=Diagonal(ones(nt))) + # push!(shots_grad, Shot(; srcs=shots[i].srcs, recs=recs_grad)) + # end + + # newvelmod = matprop.vp .- 0.2 + # newvelmod[30:40,33:44] *= 0.9 + # matprop_grad = ElasticIsoMaterialProperties(newvelmod) + + # grad = swgradient!(params, + # matprop_grad, + # shots_grad; + # parall=:threads ) + + + return params, matprop, shots, snapshots#, grad +end + +################################################################## + + + +function plotstuff(par,matprop,shots) + + rect = [0.0, 0.0, par.gridspacing[1]*(par.gridsize[1]-1), par.gridspacing[2]*(par.gridsize[2]-1)] + + xgrd = [par.gridspacing[1]*(i-1) for i=1:par.gridsize[1]] + ygrd = [par.gridspacing[2]*(i-1) for i=1:par.gridsize[2]] + + xrec = shots[1].recs.positions[:,1] + yrec = shots[1].recs.positions[:,2] + xsrc = shots[1].srcs.positions[:,1] + ysrc = shots[1].srcs.positions[:,2] + + vp = sqrt.( (matprop.λ + 2 .* matprop.μ) ./ matprop.ρ ) + + lsrec = 6:10 + + + fig = Figure(size=(1000,1200)) + + ax1 = Axis(fig[1,1],title="Vx") + ax2 = Axis(fig[2,1],title="Vz") + ax3 = Axis(fig[3,1],title="Source time function") + ax4 = Axis(fig[4,1],xlabel="x [m]",ylabel="z [m]") + + for r=lsrec + lines!(ax1,shots[1].recs.seismograms[:,1,r],label="Vx #$r") + end + axislegend(ax1) + + for r=lsrec + lines!(ax2,shots[1].recs.seismograms[:,2,r],label="Vz #$r") + end + axislegend(ax2) + + lines!(ax3,shots[1].srcs.tf[:,1]) + + #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) + hm = heatmap!(ax4,xgrd,ygrd,vp,colormap=:Reds) #,alpha=0.7) + Colorbar(fig[4,2],hm,label="Vp") + + scatter!(ax4,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) + scatter!(ax4,xsrc,ysrc,label="Sources",markersize=15) + axislegend(ax4) + for r=lsrec + text!(ax4,xrec[r],yrec[r],text="#$r") + end + ax4.yreversed = true + + save("vx_vz_vp_example.png",fig) + return fig +end + + +function snapanimate(par,matprop,shots,snapsh; scalamp=0.01, snapevery=5) + + xgrd = [par.gridspacing[1]*(i-1) for i=1:par.gridsize[1]] + ygrd = [par.gridspacing[2]*(i-1) for i=1:par.gridsize[2]] + xrec = shots[1].recs.positions[:,1] + yrec = shots[1].recs.positions[:,2] + xsrc = shots[1].srcs.positions[:,1] + ysrc = shots[1].srcs.positions[:,2] + + vxsnap = snapsh[1][1] + vzsnap = snapsh[1][2] + @show size(vxsnap),size(vzsnap) + + curvx = Observable(vxsnap[:,:,1]) + curvz = Observable(vzsnap[:,:,1]) + @show typeof(curvx),size(curvx[]) + + vp = sqrt.( (matprop.λ + 2 .* matprop.μ) ./ matprop.ρ ) + + + dx = par.gridspacing[1] + dz = par.gridspacing[2] + nx = par.gridsize[1] + nz = par.gridsize[2] + halo = par.boundcond.halo + rcoef = par.boundcond.rcoef + freetop = par.boundcond.freeboundtop + + if freetop + rectpml = [dx*(halo-1), 0.0, + dx*(nx-2*halo-1), dz*(nz-halo-1)] + else + rectpml = [dx*(halo-1), dz*(halo-1), + dx*(nx-2*halo-1), dz*(nz-2*halo-1)] + end + + ##===================================== + fig = Figure(size=(900,1800)) + + cmapwavefield = :balance #:cyclic_grey_15_85_c0_n256_s25 #:balance + + ax1 = Axis(fig[1,1],aspect=DataAspect(), + xlabel="x [m]",ylabel="z [m]") + #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) + vmax = max(abs.(extrema(vxsnap))...) + vminmax = scalamp .* (-vmax,vmax) + hm = heatmap!(ax1,xgrd,ygrd,curvx,colormap=cmapwavefield, + colorrange=vminmax) #,alpha=0.7) + Colorbar(fig[1,2],hm,label="x partic. vel.") + + lines!(ax1,Rect(rectpml...),color=:green) + scatter!(ax1,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) + scatter!(ax1,xsrc,ysrc,label="Sources",markersize=15) + axislegend(ax1) + ax1.yreversed = true + + + ax2 = Axis(fig[2,1],aspect=DataAspect(), + xlabel="x [m]",ylabel="z [m]") + #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) + vmax = max(abs.(extrema(vzsnap))...) + vminmax = scalamp .* (-vmax,vmax) + hm = heatmap!(ax2,xgrd,ygrd,curvz,colormap=cmapwavefield, + colorrange=vminmax) #,alpha=0.7) + Colorbar(fig[2,2],hm,label="z partic. vel.") + + lines!(ax2,Rect(rectpml...),color=:green) + scatter!(ax2,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) + scatter!(ax2,xsrc,ysrc,label="Sources",markersize=15) + axislegend(ax2) + ax2.yreversed = true + + + ax3 = Axis(fig[3,1],aspect=DataAspect(), + xlabel="x [m]",ylabel="z [m]") + hm = heatmap!(ax3,xgrd,ygrd,vp,colormap=:Reds) #,alpha=0.7) + Colorbar(fig[3,2],hm,label="Vp") + + scatter!(ax3,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) + scatter!(ax3,xsrc,ysrc,label="Sources",markersize=15) + axislegend(ax3) + ax3.yreversed = true + + ## + display(fig) + ##===================================== + + nframes = size(vxsnap,3) + + function updatefunction(curax1,curax2,vxsnap,vzsnap,it) + cvx = vxsnap[:,:,it] + cvz = vzsnap[:,:,it] + curax1.title = "Vx, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" + curax2.title = "Vz, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" + return cvx,cvz + end + + fps = 15 + + # live plot + # for j in 1:1 + # for it=1:nframes + # curvx[],curvz[] = updatefunction(ax1,ax2,vxsnap,vzsnap,it) + # sleep(1/fps) + # end + # end + + ## + record(fig, "snapshots_halo_$(halo)_rcoef_$(rcoef).mp4", 1:nframes, framerate=fps) do it + curvx[],curvz[] = updatefunction(ax1,ax2,vxsnap,vzsnap,it) + # yield() -> not required with record + end + + +end + +################################################################## +# debug_logger = ConsoleLogger(stderr, Logging.Debug) +# global_logger(debug_logger) +# error_logger = ConsoleLogger(stderr, Logging.Error) +# global_logger(error_logger) +info_logger = ConsoleLogger(stderr, Logging.Info) +global_logger(info_logger) + +par, matprop, shots, snapsh = exelaprob() + +snapanimate(par,matprop,shots,snapsh) + +fig = plotstuff(par,matprop,shots) + + + +# with_logger(error_logger) do +# p, v, s, snaps = exacouprob() +# end + +# using Plots +# heatmap(snaps[6][:,:,20]'; aspect_ratio=:equal, cmap=:RdBu) +# yaxis!(flip=true) + +################################################################## From 71592f1b8425e67251d58116e00aa6ac34994849 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 11 Mar 2024 14:25:57 +0100 Subject: [PATCH 026/111] Pinned compatibility on Julia v1.7 to v1.9 for now --- Project.toml | 2 +- test/Project.toml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f81588b..68d06aa 100644 --- a/Project.toml +++ b/Project.toml @@ -13,7 +13,7 @@ ParallelStencil = "94395366-693c-11ea-3b26-d9b7aac5d958" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [compat] -julia = "1.7" +julia = "1.7 - 1.9" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/Project.toml b/test/Project.toml index b8c136d..ed1a8ea 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -8,3 +8,6 @@ NumericalIntegration = "e7bfaba1-d571-5449-8927-abc22e82249b" ReferenceTests = "324d217c-45ce-50fc-942e-d289b448e8cf" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestSetExtensions = "98d24dd4-01ad-11ea-1b02-c9a08f80db04" + +[compat] +TestSetExtensions = "= 2.0" From 52c96b778cd63652a387c4b30a301383af9f5c4b Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 12 Mar 2024 10:53:23 +0100 Subject: [PATCH 027/111] Fix changes and tests (for CPU backends) TODO: test for GPU backends --- .../constant_density/gradient_check_fd.jl | 2 +- .../variable_density/gradient_check_fd.jl | 4 ++-- examples/simple_example_wavesim.jl | 4 ++-- src/models/acoustic/acou_forward.jl | 12 +++++------ src/models/acoustic/acou_gradient.jl | 20 +++++++++---------- src/models/acoustic/acou_models.jl | 4 ++-- src/solve.jl | 14 ++++++------- test/test_forward_constant_density.jl | 8 ++++---- ...test_gradient_acoustic_constant_density.jl | 14 ++++++++++++- ...test_gradient_acoustic_variable_density.jl | 6 ++++++ test/utils/setup_models.jl | 4 ++-- 11 files changed, 55 insertions(+), 37 deletions(-) diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index 614a186..4cf9375 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -60,7 +60,7 @@ function setup(nt, c0, c0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], boundcond) # Wave simulation builder - wavesim = build_wavesim(params; gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt))) + wavesim = build_wavesim(params, matprop_const; gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt))) return wavesim, shots, matprop_const, matprop_gauss end diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index 0ae18c1..ec5884f 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -72,10 +72,10 @@ function setup(nt, c0, c0max, rho0, rho0max, r, dx, dy, dt, halo, rcoef, nx, ny, ##============================================ ## Input parameters for acoustic simulation boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false) - params = InputParametersAcousticVariableDensity(nt, dt, [nx, ny], [dx, dy], boundcond) + params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], boundcond) # Wave simulation builder - wavesim = build_wavesim(params; gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt)), smooth_radius=0) + wavesim = build_wavesim(params, matprop_const; gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt)), smooth_radius=0) return wavesim, shots, matprop_const, matprop_gauss end diff --git a/examples/simple_example_wavesim.jl b/examples/simple_example_wavesim.jl index b597680..5e47071 100644 --- a/examples/simple_example_wavesim.jl +++ b/examples/simple_example_wavesim.jl @@ -113,7 +113,7 @@ function exacouprob_wavsim(parall=:serial) end println("\nswforward! - wavesim") - wavesim_fwd = build_wavesim(params; parall=parall, + wavesim_fwd = build_wavesim(params, matprop; parall=parall, gradient=false) for i=1:3 @@ -157,7 +157,7 @@ function exacouprob_wavsim(parall=:serial) println("\nswgradient! - wavesim") - wavesim_grad = build_wavesim(params; parall=parall, + wavesim_grad = build_wavesim(params, matprop; parall=parall, gradient=true, check_freq=check_freq) diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 9315d86..dcf5dd1 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -45,7 +45,7 @@ end possrcs_bk = wavsim.backend.Data.Array(possrcs) posrecs_bk = wavsim.backend.Data.Array(posrecs) srctf_bk = wavsim.backend.Data.Array(scal_srctf) - traces_bk = wavsim.backend.Data.Array(recs.seismograms) + traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(wavsim) @@ -76,7 +76,7 @@ end end # Save traces - copyto!(recs.seismograms, traces_bk) + copyto!(shot.recs.seismograms, traces_bk) end @@ -94,7 +94,7 @@ end scal_srctf = shot.srcs.tf ./ prod(wavsim.gridspacing) .* (wavsim.dt) # scale with velocity squared times density at each source position (its like dividing by m0) for s in axes(scal_srctf, 2) - scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 * wavsim.matprop.rho[positions[s, :]...] + scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 .* wavsim.matprop.rho[possrcs[s, :]...] end return possrcs,posrecs,scal_srctf @@ -112,7 +112,7 @@ end ) where {N} # scale source time function, etc. - possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsime,shot) + possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsim,shot) # Pressure and velocity arrays pcur = wavsim.pcur @@ -123,7 +123,7 @@ end possrcs_bk = wavsim.backend.Data.Array(possrcs) posrecs_bk = wavsim.backend.Data.Array(posrecs) srctf_bk = wavsim.backend.Data.Array(scal_srctf) - traces_bk = wavsim.backend.Data.Array(recs.seismograms) + traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(wavsim) @@ -154,5 +154,5 @@ end end # Save traces - copyto!(recs.seismograms, traces_bk) + copyto!(shot.recs.seismograms, traces_bk) end diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 0eaff5f..7c047ee 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -13,7 +13,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = )::Array{<:Real} where {N} # scale source time function, etc. - possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsim,shot) + possrcs,posrecs,scal_srctf = possrcrec_scaletf(model,shot) # Numerics nt = model.nt @@ -29,7 +29,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = possrcs_bk = model.backend.Data.Array(possrcs) posrecs_bk = model.backend.Data.Array(posrecs) srctf_bk = model.backend.Data.Array(scal_srctf) - traces_bk = model.backend.Data.Array(recs.seismograms) + traces_bk = model.backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(model) @@ -67,10 +67,10 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = end @info "Saving seismograms" - copyto!(recs.seismograms, traces_bk) + copyto!(shot.recs.seismograms, traces_bk) @debug "Computing residuals" - residuals_bk = model.backend.Data.Array(dχ_du(misfit, recs)) + residuals_bk = model.backend.Data.Array(dχ_du(misfit, shot.recs)) # Prescale residuals (fact = vel^2 * dt^2) model.backend.prescale_residuals!(residuals_bk, posrecs_bk, model.fact) @@ -84,7 +84,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = adjold, adjcur, adjnew = model.backend.forward_onestep_CPML!( adjold, adjcur, adjnew, model.fact, model.gridspacing..., model.halo, - model.ψ_bkdj..., model.ξ_bkdj..., model.a_coeffs..., model.b_coeffs..., + model.ψ_adj..., model.ξ_adj..., model.a_coeffs..., model.b_coeffs..., posrecs_bk, residuals_bk, nothing, nothing, it; # adjoint sources positions are receivers save_trace=false ) @@ -162,7 +162,7 @@ end )::Array{<:Real} where {N} # scale source time function, etc. - possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsime,shot) + possrcs,posrecs,scal_srctf = possrcrec_scaletf(model,shot) # Numerics nt = model.nt @@ -176,7 +176,7 @@ end possrcs_bk = model.backend.Data.Array(possrcs) posrecs_bk = model.backend.Data.Array(posrecs) srctf_bk = model.backend.Data.Array(scal_srctf) - traces_bk = model.backend.Data.Array(recs.seismograms) + traces_bk = model.backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(model) @@ -216,10 +216,10 @@ end end @info "Saving seismograms" - copyto!(recs.seismograms, traces_bk) + copyto!(shot.recs.seismograms, traces_bk) @debug "Computing residuals" - residuals_bk = model.backend.Data.Array(dχ_du(misfit, recs)) + residuals_bk = model.backend.Data.Array(dχ_du(misfit, shot.recs)) # Prescale residuals (fact = vel^2 * rho * dt) model.backend.prescale_residuals!(residuals_bk, posrecs_bk, model.fact_m0) @@ -233,7 +233,7 @@ end model.backend.backward_onestep_CPML!( adjpcur, adjvcur..., model.fact_m0, model.fact_m1_stag..., model.gridspacing..., model.halo, - model.ψ_bkdj..., model.ξ_bkdj..., model.a_coeffs..., model.b_coeffs..., + model.ψ_adj..., model.ξ_adj..., model.a_coeffs..., model.b_coeffs..., posrecs_bk, residuals_bk, it; # adjoint sources positions are receivers ) # Print timestep info diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 612642f..336d70c 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -163,7 +163,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) end # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, sizehalfgrdplusone=true) for _ in 1:N]...) + cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, true) for _ in 1:N]...) # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) a_coeffs = [] b_coeffs = [] @@ -482,7 +482,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) end # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients(halo, backend) for _ in 1:N]...) + cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, true) for _ in 1:N]...) # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) a_coeffs = [] b_coeffs = [] diff --git a/src/solve.jl b/src/solve.jl index c025389..4772e21 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -133,12 +133,12 @@ end for singleshot in shots @info "Checking invcov matrix" if typeof(wavsim)<:Vector{<:WaveSimul} - check_invcov_matrix(wavsim[1], recs.invcov) + check_invcov_matrix(wavsim[1], singleshot.recs.invcov) else - check_invcov_matrix(wavsim, recs.invcov) + check_invcov_matrix(wavsim, singleshot.recs.invcov) end @info "Computing misfit" - totmisfitval += misfit(recs, matprop) + totmisfitval += misfit(singleshot.recs, matprop) end return totmisfitval @@ -175,7 +175,7 @@ end #possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) init_shot!(wavsim, singleshot) @info "Checking invcov matrix" - check_invcov_matrix(wavsim, recs.invcov) + check_invcov_matrix(wavsim, singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" # curgrad = swgradient_1shot!( @@ -191,7 +191,7 @@ end # Compute misfit if needed if compute_misfit @info "Computing misfit" - totmisfitval += misfit(recs, matprop) + totmisfitval += misfit(singleshot.recs, matprop) end end @@ -246,7 +246,7 @@ end #possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) init_shot!(wavsim[w], singleshot) @info "Checking invcov matrix" - check_invcov_matrix(wavsim[w], recs.invcov) + check_invcov_matrix(wavsim[w], singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" # curgrad = swgradient_1shot!( @@ -262,7 +262,7 @@ end # Compute misfit if needed if compute_misfit @info "Computing misfit" - allmisfitval[s] = misfit(recs, matprop) + allmisfitval[s] = misfit(singleshot.recs, matprop) end end end diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index fc443ab..df73109 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -35,7 +35,7 @@ with_logger(error_logger) do # wave simulation params = InputParametersAcoustic(nt, dt, [nx], [dx], CPMLBoundaryConditionParameters(halo, rcoef, false)) - wavesim = build_wavesim(params; parall=parall) + wavesim = build_wavesim(params, matprop; parall=parall) # single source at 10 grid points from CPML boundary times = collect(range(0.0; step=dt, length=nt)) @@ -88,7 +88,7 @@ with_logger(error_logger) do # wave simulation params = InputParametersAcoustic(nt, dt, [nx], [dx], CPMLBoundaryConditionParameters(halo, rcoef, false)) - wavesim = build_wavesim(params; parall=parall) + wavesim = build_wavesim(params, matprop; parall=parall) # multiple sources at differece distances times = collect(range(0.0; step=dt, length=nt)) @@ -145,7 +145,7 @@ with_logger(error_logger) do # wave simulation params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], CPMLBoundaryConditionParameters(halo, rcoef, false)) - wavesim = build_wavesim(params; parall=parall) + wavesim = build_wavesim(params, matprop; parall=parall) # single source at 10 grid points from top CPML boundary times = collect(range(0.0; step=dt, length=nt)) @@ -201,7 +201,7 @@ with_logger(error_logger) do # wave simulation params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], CPMLBoundaryConditionParameters(halo, rcoef, false)) - wavesim = build_wavesim(params; parall=parall) + wavesim = build_wavesim(params, matprop; parall=parall) # multiple sources at differece distances times = collect(range(0.0; step=dt, length=nt)) diff --git a/test/test_gradient_acoustic_constant_density.jl b/test/test_gradient_acoustic_constant_density.jl index a8b5b87..5d45914 100644 --- a/test/test_gradient_acoustic_constant_density.jl +++ b/test/test_gradient_acoustic_constant_density.jl @@ -1,4 +1,4 @@ -using Test +using Test, LinearAlgebra using SeismicWaves using CUDA: CUDA @@ -41,6 +41,9 @@ with_logger(error_logger) do # Check that gradient is non zero @test !all(g -> g == 0.0, grad) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) # Check that misfits are equivalent @test misfit ≈ misfit_check end @@ -73,6 +76,9 @@ with_logger(error_logger) do # Check that gradient is non zero @test !all(g -> g == 0.0, grad) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) # Check that misfits are equivalent @test misfit ≈ misfit_check end @@ -104,6 +110,9 @@ with_logger(error_logger) do # Check that gradient is non zero @test !all(g -> g == 0.0, grad) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) # Check that misfits are equivalent @test misfit ≈ misfit_check end @@ -135,6 +144,9 @@ with_logger(error_logger) do # Check that gradient is non zero @test !all(g -> g == 0.0, grad) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) # Check that misfits are equivalent @test misfit ≈ misfit_check end diff --git a/test/test_gradient_acoustic_variable_density.jl b/test/test_gradient_acoustic_variable_density.jl index a304e5f..189a1d4 100644 --- a/test/test_gradient_acoustic_variable_density.jl +++ b/test/test_gradient_acoustic_variable_density.jl @@ -43,6 +43,9 @@ with_logger(error_logger) do # Check that gradient is non zero @test !all(g -> g == 0.0, grad) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) # Check that misfits are equivalent @test misfit ≈ misfit_check end @@ -76,6 +79,9 @@ with_logger(error_logger) do # Check that gradient is non zero @test !all(g -> g == 0.0, grad) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) # Check that misfits are equivalent @test misfit ≈ misfit_check end diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index 8d7a678..01a6ce6 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -49,7 +49,7 @@ function setup_constant_vel_rho_1D_CPML(nt, dt, nx, dx, c0, ρ0, t0, f0, halo, r lx = (nx - 1) * dx matprop = VpRhoAcousticVDMaterialProperties(c0 .* ones(nx), ρ0 .* ones(nx)) # input parameters - params = InputParametersAcousticVariableDensity(nt, dt, [nx], [dx], + params = InputParametersAcoustic(nt, dt, [nx], [dx], CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources times = collect(range(0.0; step=dt, length=nt)) @@ -97,7 +97,7 @@ function setup_constant_vel_rho_2D_CPML(nt, dt, nx, ny, dx, dy, c0, ρ0, t0, f0, ly = (ny - 1) * dy matprop = VpRhoAcousticVDMaterialProperties(c0 .* ones(nx, ny), ρ0 .* ones(nx, ny)) # input parameters - params = InputParametersAcousticVariableDensity(nt, dt, [nx, ny], [dx, dy], + params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources times = collect(range(0.0; step=dt, length=nt)) From 8fd63236224c1bf36bc68972364b36e97f5a5f0b Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 12 Mar 2024 13:05:05 +0100 Subject: [PATCH 028/111] First formatting pass --- .JuliaFormatter.toml | 2 +- docs/make.jl | 29 +- .../variable_density/gradient_check_fd.jl | 2 +- .../variable_density/plot_gradient.jl | 26 +- examples/simple_example_acoustic.jl | 20 +- examples/simple_example_elastic.jl | 223 +++++----- examples/simple_example_wavesim.jl | 66 ++- src/HMCseiswaves.jl | 39 +- src/SeismicWaves.jl | 12 - src/boundarycond.jl | 1 - src/checks.jl | 13 +- src/models/acoustic/acou_forward.jl | 26 +- src/models/acoustic/acou_gradient.jl | 36 +- .../acoustic/acou_material_properties.jl | 2 - src/models/acoustic/acou_models.jl | 4 +- src/models/acoustic/acou_params.jl | 2 - .../backends/Acoustic1D_CD_CPML_Serial.jl | 4 +- .../backends/shared/acoustic1D_VD_xPU.jl | 17 +- .../backends/shared/acoustic2D_VD_xPU.jl | 94 ++-- .../fourth_order_FiniteDifferences1D.jl | 2 +- .../fourth_order_FiniteDifferences2D.jl | 4 +- .../backends/shared/smooth_gradient_1D.jl | 4 +- .../backends/shared/smooth_gradient_2D.jl | 6 +- .../backends/shared/smooth_gradient_3D.jl | 8 +- src/models/backend_selection.jl | 2 - src/models/cpmlcoeffs.jl | 78 ++-- .../backends/Elastic2D_Iso_CPML_Serial.jl | 407 ++++++++---------- src/models/elastic/ela_abstract_types.jl | 1 - src/models/elastic/ela_forward.jl | 107 +++-- src/models/elastic/ela_init_bc.jl | 6 +- src/models/elastic/ela_material_properties.jl | 43 +- src/models/elastic/ela_models.jl | 132 +++--- src/models/elastic/ela_params.jl | 1 - src/receivers.jl | 24 +- src/solve.jl | 50 +-- src/sources.jl | 43 +- src/srcrec_interpolation.jl | 135 +++--- src/utils.jl | 19 +- src/wrappers.jl | 58 ++- ..._vs_numerical_acoustic_variable_density.jl | 10 +- ...test_gradient_acoustic_variable_density.jl | 8 +- test/utils/setup_models.jl | 4 +- 42 files changed, 822 insertions(+), 948 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 785421b..b00e9c3 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -1,4 +1,4 @@ -margin = 130 +margin = 180 always_for_in = true whitespace_ops_in_indices = false remove_extra_newlines = true diff --git a/docs/make.jl b/docs/make.jl index c7ba898..ddc2fe2 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,21 +1,20 @@ using Documenter, SeismicWaves +makedocs(; repo=Remotes.GitLab("JuliaGeoph", "SeismicWaves.jl"), # "https://gitlab.com/JuliaGeoph/SeismicWaves.jl/blob/{commit}{path}#{line}", + sitename="SeismicWaves.jl", + modules=[SeismicWaves], + authors="Andrea Zunino, Giacomo Aloisi", + format=Documenter.HTML(; prettyurls=get(ENV, "CI", nothing) == "true"), + pages=[ + "Home" => "index.md" + ], + warnonly=[:missing_docs, :cross_references] +) -makedocs(repo=Remotes.GitLab("JuliaGeoph","SeismicWaves.jl"), # "https://gitlab.com/JuliaGeoph/SeismicWaves.jl/blob/{commit}{path}#{line}", - sitename="SeismicWaves.jl", - modules = [SeismicWaves], - authors = "Andrea Zunino, Giacomo Aloisi", - format = Documenter.HTML(prettyurls=get(ENV,"CI",nothing)=="true"), - pages = [ - "Home" => "index.md", - ], - warnonly = [:missing_docs, :cross_references] - ) - -deploydocs( +deploydocs(; repo="gitlab.com/JuliaGeoph/SeismicWaves.jl.git", - devbranch = "main", - deploy_config = Documenter.GitLab(), - branch = "gl-pages" + devbranch="main", + deploy_config=Documenter.GitLab(), + branch="gl-pages" ) diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index ec5884f..5a9b4c4 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -175,7 +175,7 @@ rho0 = 1500 rho0max = 3000 r = 35 dh = dx = dy = 5.0 -dt = dh / sqrt(2) / c0max * 6/7 +dt = dh / sqrt(2) / c0max * 6 / 7 halo = 20 rcoef = 0.0001 nx = 201 diff --git a/examples/gradient_check_fd/variable_density/plot_gradient.jl b/examples/gradient_check_fd/variable_density/plot_gradient.jl index 4027cbe..815ef06 100644 --- a/examples/gradient_check_fd/variable_density/plot_gradient.jl +++ b/examples/gradient_check_fd/variable_density/plot_gradient.jl @@ -22,23 +22,24 @@ l = @layout([A B C]) # Get gradient gradients = deserialize("grad.dat") -adjgrad_vp = gradients[:,:,1] -adjgrad_rho = gradients[:,:,2] +adjgrad_vp = gradients[:, :, 1] +adjgrad_rho = gradients[:, :, 2] fd_gradients = deserialize("fdgrad.dat") -fdgrad_vp = fd_gradients[:,:,1] -fdgrad_rho = fd_gradients[:,:,2] - -@show adjgrad_vp[100,100] -@show adjgrad_rho[100,100] -@show abs(adjgrad_vp[100,100] - fdgrad_vp[100,100]) -@show abs(adjgrad_rho[100,100] - fdgrad_rho[100,100]) -@show abs((adjgrad_vp[100,100] - fdgrad_vp[100,100]) / adjgrad_vp[100,100]) -@show abs((adjgrad_rho[100,100] - fdgrad_rho[100,100]) / adjgrad_rho[100,100]) +fdgrad_vp = fd_gradients[:, :, 1] +fdgrad_rho = fd_gradients[:, :, 2] +@show adjgrad_vp[100, 100] +@show adjgrad_rho[100, 100] +@show abs(adjgrad_vp[100, 100] - fdgrad_vp[100, 100]) +@show abs(adjgrad_rho[100, 100] - fdgrad_rho[100, 100]) +@show abs((adjgrad_vp[100, 100] - fdgrad_vp[100, 100]) / adjgrad_vp[100, 100]) +@show abs((adjgrad_rho[100, 100] - fdgrad_rho[100, 100]) / adjgrad_rho[100, 100]) for i in 1:201 for j in 1:201 - if isnan(adjgrad_vp[i,j]) @show i, j end + if isnan(adjgrad_vp[i, j]) + @show i, j + end end end @@ -166,7 +167,6 @@ p = plot( ) savefig("fdgrad_rho.png") - grad_diff_vp = fdgrad_vp - adjgrad_vp # Plot relative difference between adjoint and FD grad and zoom in rel_diff = log10.(abs.(grad_diff_vp ./ fdgrad_vp) * 100) diff --git a/examples/simple_example_acoustic.jl b/examples/simple_example_acoustic.jl index 73a06b1..98266aa 100644 --- a/examples/simple_example_acoustic.jl +++ b/examples/simple_example_acoustic.jl @@ -93,11 +93,11 @@ function exacouprob(parall=:serial) logger = ConsoleLogger(Error) ## compute the seismograms @time snapshots = swforward!(params, - matprop, - shots; - parall=parall, - infoevery=infoevery, - logger=logger ) + matprop, + shots; + parall=parall, + infoevery=infoevery, + logger=logger) #snapevery=snapevery) ##=============================================== @@ -116,11 +116,11 @@ function exacouprob(parall=:serial) matprop_grad = VpAcousticCDMaterialProperties(newvelmod) @time grad = swgradient!(params, - matprop_grad, - shots_grad; - parall=parall, - logger=logger ) - + matprop_grad, + shots_grad; + parall=parall, + logger=logger) + return params, velmod, shots#, snapshots, grad end diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index 7d58c38..b24cfdf 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -21,12 +21,12 @@ function exelaprob() nx = 380 # 211 nz = 270 # 120 dh = 4.5 # meters - @show nx,nz,nx*nz,dh + @show nx, nz, nx * nz, dh #@show (nx-1)*dh, (nz-1)*dh vp = zeros(nx, nz) #vp .= 2700.0 - vp[nx÷2+10:end,:] .= 3100.0 + vp[nx÷2+10:end, :] .= 3100.0 for i in 1:nx for j in 1:nz vp[i, j] = 2000.0 + dh * (j - 1) @@ -35,21 +35,19 @@ function exelaprob() @show extrema(vp) vs = vp ./ sqrt(3) - @show extrema(vp),extrema(vs) + @show extrema(vp), extrema(vs) - ρ = 2100.0 * ones(nx,nz) - μ = vs.^2 .* ρ # μ = Vs^2⋅ρ - λ = (vp.^2 .* ρ) .- (2 .* μ) # λ = vp^2 · ρ - 2μ - - - @show extrema(vp.^2) - @show extrema(vp.^2 .* ρ) + ρ = 2100.0 * ones(nx, nz) + μ = vs .^ 2 .* ρ # μ = Vs^2⋅ρ + λ = (vp .^ 2 .* ρ) .- (2 .* μ) # λ = vp^2 · ρ - 2μ + @show extrema(vp .^ 2) + @show extrema(vp .^ 2 .* ρ) @show extrema(λ) @show extrema(μ) @show extrema(ρ) - matprop = ElasticIsoMaterialProperties(λ=λ,μ=μ,ρ=ρ) + matprop = ElasticIsoMaterialProperties(; λ=λ, μ=μ, ρ=ρ) ##======================================== # shots definition @@ -60,15 +58,15 @@ function exelaprob() # sources definition nsrc = 1 # sources x-position (in grid points) (different for every shot) - if nsrc==1 - ixsrc = [nx/2] + if nsrc == 1 + ixsrc = [nx / 2] else ixsrc = round.(Int, LinRange(30, nx - 31, nsrc)) end possrcs = zeros(nsrc, 2) # 1 source, 2 dimensions - for s=1:nsrc + for s in 1:nsrc possrcs[s, 1] = (ixsrc[i] - 1) * dh .+ 0.124 # x-positions in meters - possrcs[s, 2] = (nz/2)*dh .+ 0.124 #(nz/2) * dh # y-positions in meters + possrcs[s, 2] = (nz / 2) * dh .+ 0.124 #(nz/2) * dh # y-positions in meters end # source time functions @@ -86,8 +84,8 @@ function exelaprob() end srcs = MomentTensorSources(possrcs, srcstf, - MomentTensor2D(Mxx=Mxx,Mzz=Mzz,Mxz=Mxz), - f0) + MomentTensor2D(; Mxx=Mxx, Mzz=Mzz, Mxz=Mxz), + f0) #srcs = ScalarSources(possrcs, srcstf, f0) #@show srcs.positions @@ -95,10 +93,10 @@ function exelaprob() # receivers definition nrecs = 10 # receivers x-positions (in grid points) (same for every shot) - ixrec = round.(Int, LinRange(40, nx-40, nrecs)) + ixrec = round.(Int, LinRange(40, nx - 40, nrecs)) posrecs = zeros(nrecs, 2) # 20 receivers, 2 dimensions posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 # x-positions in meters - posrecs[:, 2] .= (nz/4)*dh .- 0.312 # (nz/2) * dh # y-positions in meters + posrecs[:, 2] .= (nz / 4) * dh .- 0.312 # (nz/2) * dh # y-positions in meters ndim = 2 recs = VectorReceivers(posrecs, nt, ndim) @@ -111,7 +109,7 @@ function exelaprob() @show shots[1].srcs.positions @show shots[1].recs.positions - + ##============================================ ## Input parameters for elastic simulation snapevery = 5 @@ -124,15 +122,14 @@ function exelaprob() boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=freetop) params = InputParametersElastic(nt, dt, [nx, nz], [dh, dh], boundcond) - ##=============================================== ## compute the seismograms snapshots = swforward!(params, - matprop, - shots; - parall=:serial, - infoevery=infoevery, - snapevery=snapevery) + matprop, + shots; + parall=:serial, + infoevery=infoevery, + snapevery=snapevery) # ##=============================================== # ## compute the gradient @@ -154,87 +151,79 @@ function exelaprob() # shots_grad; # parall=:threads ) - return params, matprop, shots, snapshots#, grad end ################################################################## +function plotstuff(par, matprop, shots) + rect = [0.0, 0.0, par.gridspacing[1] * (par.gridsize[1] - 1), par.gridspacing[2] * (par.gridsize[2] - 1)] + xgrd = [par.gridspacing[1] * (i - 1) for i in 1:par.gridsize[1]] + ygrd = [par.gridspacing[2] * (i - 1) for i in 1:par.gridsize[2]] -function plotstuff(par,matprop,shots) - - rect = [0.0, 0.0, par.gridspacing[1]*(par.gridsize[1]-1), par.gridspacing[2]*(par.gridsize[2]-1)] + xrec = shots[1].recs.positions[:, 1] + yrec = shots[1].recs.positions[:, 2] + xsrc = shots[1].srcs.positions[:, 1] + ysrc = shots[1].srcs.positions[:, 2] - xgrd = [par.gridspacing[1]*(i-1) for i=1:par.gridsize[1]] - ygrd = [par.gridspacing[2]*(i-1) for i=1:par.gridsize[2]] - - xrec = shots[1].recs.positions[:,1] - yrec = shots[1].recs.positions[:,2] - xsrc = shots[1].srcs.positions[:,1] - ysrc = shots[1].srcs.positions[:,2] - - vp = sqrt.( (matprop.λ + 2 .* matprop.μ) ./ matprop.ρ ) + vp = sqrt.((matprop.λ + 2 .* matprop.μ) ./ matprop.ρ) lsrec = 6:10 - - fig = Figure(size=(1000,1200)) + fig = Figure(; size=(1000, 1200)) - ax1 = Axis(fig[1,1],title="Vx") - ax2 = Axis(fig[2,1],title="Vz") - ax3 = Axis(fig[3,1],title="Source time function") - ax4 = Axis(fig[4,1],xlabel="x [m]",ylabel="z [m]") - - for r=lsrec - lines!(ax1,shots[1].recs.seismograms[:,1,r],label="Vx #$r") + ax1 = Axis(fig[1, 1]; title="Vx") + ax2 = Axis(fig[2, 1]; title="Vz") + ax3 = Axis(fig[3, 1]; title="Source time function") + ax4 = Axis(fig[4, 1]; xlabel="x [m]", ylabel="z [m]") + + for r in lsrec + lines!(ax1, shots[1].recs.seismograms[:, 1, r]; label="Vx #$r") end axislegend(ax1) - for r=lsrec - lines!(ax2,shots[1].recs.seismograms[:,2,r],label="Vz #$r") + for r in lsrec + lines!(ax2, shots[1].recs.seismograms[:, 2, r]; label="Vz #$r") end axislegend(ax2) - lines!(ax3,shots[1].srcs.tf[:,1]) + lines!(ax3, shots[1].srcs.tf[:, 1]) #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) - hm = heatmap!(ax4,xgrd,ygrd,vp,colormap=:Reds) #,alpha=0.7) - Colorbar(fig[4,2],hm,label="Vp") + hm = heatmap!(ax4, xgrd, ygrd, vp; colormap=:Reds) #,alpha=0.7) + Colorbar(fig[4, 2], hm; label="Vp") - scatter!(ax4,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) - scatter!(ax4,xsrc,ysrc,label="Sources",markersize=15) + scatter!(ax4, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + scatter!(ax4, xsrc, ysrc; label="Sources", markersize=15) axislegend(ax4) - for r=lsrec - text!(ax4,xrec[r],yrec[r],text="#$r") + for r in lsrec + text!(ax4, xrec[r], yrec[r]; text="#$r") end ax4.yreversed = true - save("vx_vz_vp_example.png",fig) + save("vx_vz_vp_example.png", fig) return fig end - -function snapanimate(par,matprop,shots,snapsh; scalamp=0.01, snapevery=5) - - xgrd = [par.gridspacing[1]*(i-1) for i=1:par.gridsize[1]] - ygrd = [par.gridspacing[2]*(i-1) for i=1:par.gridsize[2]] - xrec = shots[1].recs.positions[:,1] - yrec = shots[1].recs.positions[:,2] - xsrc = shots[1].srcs.positions[:,1] - ysrc = shots[1].srcs.positions[:,2] +function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) + xgrd = [par.gridspacing[1] * (i - 1) for i in 1:par.gridsize[1]] + ygrd = [par.gridspacing[2] * (i - 1) for i in 1:par.gridsize[2]] + xrec = shots[1].recs.positions[:, 1] + yrec = shots[1].recs.positions[:, 2] + xsrc = shots[1].srcs.positions[:, 1] + ysrc = shots[1].srcs.positions[:, 2] vxsnap = snapsh[1][1] vzsnap = snapsh[1][2] - @show size(vxsnap),size(vzsnap) + @show size(vxsnap), size(vzsnap) - curvx = Observable(vxsnap[:,:,1]) - curvz = Observable(vzsnap[:,:,1]) - @show typeof(curvx),size(curvx[]) + curvx = Observable(vxsnap[:, :, 1]) + curvz = Observable(vzsnap[:, :, 1]) + @show typeof(curvx), size(curvx[]) - vp = sqrt.( (matprop.λ + 2 .* matprop.μ) ./ matprop.ρ ) + vp = sqrt.((matprop.λ + 2 .* matprop.μ) ./ matprop.ρ) - dx = par.gridspacing[1] dz = par.gridspacing[2] nx = par.gridsize[1] @@ -244,57 +233,55 @@ function snapanimate(par,matprop,shots,snapsh; scalamp=0.01, snapevery=5) freetop = par.boundcond.freeboundtop if freetop - rectpml = [dx*(halo-1), 0.0, - dx*(nx-2*halo-1), dz*(nz-halo-1)] + rectpml = [dx * (halo - 1), 0.0, + dx * (nx - 2 * halo - 1), dz * (nz - halo - 1)] else - rectpml = [dx*(halo-1), dz*(halo-1), - dx*(nx-2*halo-1), dz*(nz-2*halo-1)] + rectpml = [dx * (halo - 1), dz * (halo - 1), + dx * (nx - 2 * halo - 1), dz * (nz - 2 * halo - 1)] end ##===================================== - fig = Figure(size=(900,1800)) + fig = Figure(; size=(900, 1800)) cmapwavefield = :balance #:cyclic_grey_15_85_c0_n256_s25 #:balance - ax1 = Axis(fig[1,1],aspect=DataAspect(), - xlabel="x [m]",ylabel="z [m]") + ax1 = Axis(fig[1, 1]; aspect=DataAspect(), + xlabel="x [m]", ylabel="z [m]") #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) vmax = max(abs.(extrema(vxsnap))...) - vminmax = scalamp .* (-vmax,vmax) - hm = heatmap!(ax1,xgrd,ygrd,curvx,colormap=cmapwavefield, - colorrange=vminmax) #,alpha=0.7) - Colorbar(fig[1,2],hm,label="x partic. vel.") - - lines!(ax1,Rect(rectpml...),color=:green) - scatter!(ax1,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) - scatter!(ax1,xsrc,ysrc,label="Sources",markersize=15) + vminmax = scalamp .* (-vmax, vmax) + hm = heatmap!(ax1, xgrd, ygrd, curvx; colormap=cmapwavefield, + colorrange=vminmax) #,alpha=0.7) + Colorbar(fig[1, 2], hm; label="x partic. vel.") + + lines!(ax1, Rect(rectpml...); color=:green) + scatter!(ax1, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + scatter!(ax1, xsrc, ysrc; label="Sources", markersize=15) axislegend(ax1) ax1.yreversed = true - - ax2 = Axis(fig[2,1],aspect=DataAspect(), - xlabel="x [m]",ylabel="z [m]") + ax2 = Axis(fig[2, 1]; aspect=DataAspect(), + xlabel="x [m]", ylabel="z [m]") #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) vmax = max(abs.(extrema(vzsnap))...) - vminmax = scalamp .* (-vmax,vmax) - hm = heatmap!(ax2,xgrd,ygrd,curvz,colormap=cmapwavefield, - colorrange=vminmax) #,alpha=0.7) - Colorbar(fig[2,2],hm,label="z partic. vel.") - - lines!(ax2,Rect(rectpml...),color=:green) - scatter!(ax2,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) - scatter!(ax2,xsrc,ysrc,label="Sources",markersize=15) + vminmax = scalamp .* (-vmax, vmax) + hm = heatmap!(ax2, xgrd, ygrd, curvz; colormap=cmapwavefield, + colorrange=vminmax) #,alpha=0.7) + Colorbar(fig[2, 2], hm; label="z partic. vel.") + + lines!(ax2, Rect(rectpml...); color=:green) + scatter!(ax2, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + scatter!(ax2, xsrc, ysrc; label="Sources", markersize=15) axislegend(ax2) ax2.yreversed = true + ax3 = Axis(fig[3, 1]; aspect=DataAspect(), + xlabel="x [m]", ylabel="z [m]") + hm = heatmap!(ax3, xgrd, ygrd, vp; colormap=:Reds) #,alpha=0.7) + Colorbar(fig[3, 2], hm; label="Vp") - ax3 = Axis(fig[3,1],aspect=DataAspect(), - xlabel="x [m]",ylabel="z [m]") - hm = heatmap!(ax3,xgrd,ygrd,vp,colormap=:Reds) #,alpha=0.7) - Colorbar(fig[3,2],hm,label="Vp") - - scatter!(ax3,xrec,yrec,marker=:dtriangle,label="Receivers",markersize=15) - scatter!(ax3,xsrc,ysrc,label="Sources",markersize=15) + scatter!(ax3, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + scatter!(ax3, xsrc, ysrc; label="Sources", markersize=15) axislegend(ax3) ax3.yreversed = true @@ -302,14 +289,14 @@ function snapanimate(par,matprop,shots,snapsh; scalamp=0.01, snapevery=5) display(fig) ##===================================== - nframes = size(vxsnap,3) - - function updatefunction(curax1,curax2,vxsnap,vzsnap,it) - cvx = vxsnap[:,:,it] - cvz = vzsnap[:,:,it] + nframes = size(vxsnap, 3) + + function updatefunction(curax1, curax2, vxsnap, vzsnap, it) + cvx = vxsnap[:, :, it] + cvz = vzsnap[:, :, it] curax1.title = "Vx, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" curax2.title = "Vz, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" - return cvx,cvz + return cvx, cvz end fps = 15 @@ -323,12 +310,10 @@ function snapanimate(par,matprop,shots,snapsh; scalamp=0.01, snapevery=5) # end ## - record(fig, "snapshots_halo_$(halo)_rcoef_$(rcoef).mp4", 1:nframes, framerate=fps) do it - curvx[],curvz[] = updatefunction(ax1,ax2,vxsnap,vzsnap,it) + record(fig, "snapshots_halo_$(halo)_rcoef_$(rcoef).mp4", 1:nframes; framerate=fps) do it + curvx[], curvz[] = updatefunction(ax1, ax2, vxsnap, vzsnap, it) # yield() -> not required with record end - - end ################################################################## @@ -341,11 +326,9 @@ global_logger(info_logger) par, matprop, shots, snapsh = exelaprob() -snapanimate(par,matprop,shots,snapsh) - -fig = plotstuff(par,matprop,shots) - +snapanimate(par, matprop, shots, snapsh) +fig = plotstuff(par, matprop, shots) # with_logger(error_logger) do # p, v, s, snaps = exacouprob() diff --git a/examples/simple_example_wavesim.jl b/examples/simple_example_wavesim.jl index 5e47071..2c35f95 100644 --- a/examples/simple_example_wavesim.jl +++ b/examples/simple_example_wavesim.jl @@ -21,7 +21,7 @@ function exacouprob_wavsim(parall=:serial) nx = 301 #300 #211 nz = 288 #300 #120 dh = 10.0 # meters - @show nx,nz + @show nx, nz #@show (nx-1)*dh, (nz-1)*dh @@ -97,32 +97,31 @@ function exacouprob_wavsim(parall=:serial) ## compute the seismograms println("####>>>> parall = $parall <<<<####") - if parall==:threads || parall==:threadpersrc + if parall == :threads || parall == :threadpersrc @show Threads.nthreads() end - println("\nswforward! - NO wavesim") - for i=1:3 + for i in 1:3 @time snapshots = swforward!(params, - matprop, - shots; - parall=parall, - infoevery=infoevery, - logger=logger ) + matprop, + shots; + parall=parall, + infoevery=infoevery, + logger=logger) end - println("\nswforward! - wavesim") + println("\nswforward! - wavesim") wavesim_fwd = build_wavesim(params, matprop; parall=parall, - gradient=false) - - for i=1:3 + gradient=false) + + for i in 1:3 @time snapshots = swforward!(wavesim_fwd, - matprop, - shots; - logger=logger ) - end - + matprop, + shots; + logger=logger) + end + #snapevery=snapevery) ##=============================================== @@ -146,33 +145,30 @@ function exacouprob_wavsim(parall=:serial) grad = nothing println("\nswgradient! - NO wavesim") - for i=1:3 + for i in 1:3 @time grad = swgradient!(params, - matprop_grad, - shots_grad; - check_freq=check_freq, - parall=parall, - logger=logger ) + matprop_grad, + shots_grad; + check_freq=check_freq, + parall=parall, + logger=logger) end - println("\nswgradient! - wavesim") wavesim_grad = build_wavesim(params, matprop; parall=parall, - gradient=true, - check_freq=check_freq) - - for i=1:3 + gradient=true, + check_freq=check_freq) + + for i in 1:3 @time grad = swgradient!(wavesim_grad, - matprop_grad, - shots_grad; - logger=logger ) + matprop_grad, + shots_grad; + logger=logger) end - - jldsave("fwd_grad_$(parall).jld",shots=shots,grad=grad) + jldsave("fwd_grad_$(parall).jld"; shots=shots, grad=grad) return params, velmod, shots, grad end ################################################################## - diff --git a/src/HMCseiswaves.jl b/src/HMCseiswaves.jl index 8127084..bd5383e 100644 --- a/src/HMCseiswaves.jl +++ b/src/HMCseiswaves.jl @@ -18,10 +18,8 @@ using Logging export AcouWavCDProb - #wavesim = nothing - ################################################################# ## create the problem type for traveltime tomography @@ -31,16 +29,16 @@ struct AcouWavCDProb shots::Vector{<:Shot} #invCovds::Vector{<:AbstractMatrix{Float64}} parall::Symbol #firsttime::Base.RefValue{Bool} - - function AcouWavCDProb(inpars::InputParametersAcoustic, - shots::Vector{<:Shot}, - parall::Symbol ) - # nt = inpars.ntimesteps - # check_freq = ceil(Int, sqrt(nt)) - # wavesim = build_wavesim(inpars; gradient=true,check_freq=check_freq, - # snapevery=nothing,infoevery=nothing) - return new(inpars,shots,parall) #,Ref(true)) + function AcouWavCDProb(inpars::InputParametersAcoustic, + shots::Vector{<:Shot}, + parall::Symbol) + + # nt = inpars.ntimesteps + # check_freq = ceil(Int, sqrt(nt)) + # wavesim = build_wavesim(inpars; gradient=true,check_freq=check_freq, + # snapevery=nothing,infoevery=nothing) + return new(inpars, shots, parall) #,Ref(true)) end end @@ -49,7 +47,6 @@ end ############################################################ ## make the type callable function (acouprob::AcouWavCDProb)(vecvel::Vector{Float64}, kind::Symbol) - logger = Logging.ConsoleLogger(Error) #logger = Logging.NullLogger() @@ -82,7 +79,7 @@ function (acouprob::AcouWavCDProb)(vecvel::Vector{Float64}, kind::Symbol) ## compute the logdensity value for vecvel ## ############################################# misval = swmisfit!(acouprob.inpars, matprop, acouprob.shots; - parall=acouprob.parall,logger=logger) + parall=acouprob.parall, logger=logger) # misval = swmisfit!(wavesim, matprop, acouprob.shots, # logger=logger) return misval @@ -92,17 +89,17 @@ function (acouprob::AcouWavCDProb)(vecvel::Vector{Float64}, kind::Symbol) ## compute the gradient of the misfit function ## ################################################# grad = swgradient!(acouprob.inpars, - matprop, - acouprob.shots; - parall=acouprob.parall, - ## if next line is commented: no checkpointing - check_freq=ceil(Int, sqrt(acouprob.inpars.ntimesteps)), - logger=logger) + matprop, + acouprob.shots; + parall=acouprob.parall, + ## if next line is commented: no checkpointing + check_freq=ceil(Int, sqrt(acouprob.inpars.ntimesteps)), + logger=logger) # @time grad = swgradient!(wavesim, # matprop, # acouprob.shots, # logger=logger) - + # return flattened gradient return vec(grad) @@ -111,7 +108,7 @@ function (acouprob::AcouWavCDProb)(vecvel::Vector{Float64}, kind::Symbol) ## compute calculated data (solve forward problem) ## #################################################### dcalc = swforward!(acouprob.inpars, matprop, acouprob.shots; - parall=acouprob.parall,logger=logger) + parall=acouprob.parall, logger=logger) # dcalc = swforward!(wavesim, matprop, acouprob.shots, # logger=logger) return dcalc diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index fbfdf41..8bee61d 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -10,7 +10,6 @@ using ParallelStencil using Logging using DocStringExtensions - # main struct for wave simulation export WaveSimul export build_wavesim @@ -31,7 +30,6 @@ export swforward!, swmisfit!, swgradient! # source time functions export gaussstf, gaussderivstf, rickerstf - include("abstract_types.jl") include("traits/boundarycondition.jl") @@ -48,8 +46,6 @@ include("srcrec_interpolation.jl") include("models/cpmlcoeffs.jl") - - # Acoustic include("models/acoustic/acou_abstract_types.jl") include("models/acoustic/acou_material_properties.jl") @@ -68,7 +64,6 @@ include("models/elastic/ela_forward.jl") #include("models/elastic/ela_gradient.jl") include("models/elastic/ela_init_bc.jl") - # Backend selection include("models/backend_selection.jl") # Misfit @@ -78,7 +73,6 @@ include("solve.jl") # Main functions include("wrappers.jl") - # Acoustic serial backend include("models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl") include("models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl") @@ -87,7 +81,6 @@ include("models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl") # Elastic serial backend include("models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl") - # Acoustic parallel backends ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl") @@ -111,19 +104,14 @@ include("models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl") ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") - # Elastic parallel backends - - # Utils include("utils.jl") - ## HMC stuff include("HMCseiswaves.jl") using .HMCseiswaves export AcouWavCDProb - end # module diff --git a/src/boundarycond.jl b/src/boundarycond.jl index ad207c3..4d19128 100644 --- a/src/boundarycond.jl +++ b/src/boundarycond.jl @@ -1,5 +1,4 @@ - @doc """ $(TYPEDEF) diff --git a/src/checks.jl b/src/checks.jl index a8cedbe..503b0a5 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -26,12 +26,11 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s tyreceiver <: ScalarReceivers return - elseif tysim==ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< - tymatprop==ElasticIsoMaterialProperties{2} && - tysource <: MomentTensorSources && - tyreceiver <: VectorReceivers + elseif tysim == ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< + tymatprop == ElasticIsoMaterialProperties{2} && + tysource <: MomentTensorSources && + tyreceiver <: VectorReceivers return - end return error("Types of WaveSimul, MaterialProperties and Sources/Receivers are incosistent \ @@ -89,6 +88,4 @@ function check_positions( return end -function check_invcov_matrix(model::WaveSimul, invcov) - @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" -end +check_invcov_matrix(model::WaveSimul, invcov) = @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index dcf5dd1..af00fdd 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -2,10 +2,9 @@ # Generic function swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) - # Scaling for AcousticCDWaveSimul @views function possrcrec_scaletf(wavsim::AcousticCDCPMLWaveSimul{N}, - shot::Shot) where {N} + shot::Shot) where {N} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) @@ -18,10 +17,9 @@ swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(Boundary scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 end - return possrcs,posrecs,scal_srctf + return possrcs, posrecs, scal_srctf end - @views function swforward_1shot!( ::CPMLBoundaryCondition, wavsim::AcousticCDCPMLWaveSimul{N}, @@ -30,11 +28,11 @@ end # posrecs, # srctf, # recs - ) where {N} +) where {N} # scale source time function, etc. - possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsim,shot) - + possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) + # Pressure arrays pold = wavsim.pold pcur = wavsim.pcur @@ -44,7 +42,7 @@ end # Wrap sources and receivers arrays possrcs_bk = wavsim.backend.Data.Array(possrcs) posrecs_bk = wavsim.backend.Data.Array(posrecs) - srctf_bk = wavsim.backend.Data.Array(scal_srctf) + srctf_bk = wavsim.backend.Data.Array(scal_srctf) traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(wavsim) @@ -79,28 +77,26 @@ end copyto!(shot.recs.seismograms, traces_bk) end - ##################################################### # Scaling for AcousticVDStaggeredCPMLWaveSimul @views function possrcrec_scaletf(wavsim::AcousticVDStaggeredCPMLWaveSimul{N}, - shot::Shot) where {N} + shot::Shot) where {N} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) # source time function # scale with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(wavsim.gridspacing) .* (wavsim.dt) + scal_srctf = shot.srcs.tf ./ prod(wavsim.gridspacing) .* (wavsim.dt) # scale with velocity squared times density at each source position (its like dividing by m0) for s in axes(scal_srctf, 2) scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 .* wavsim.matprop.rho[possrcs[s, :]...] end - return possrcs,posrecs,scal_srctf + return possrcs, posrecs, scal_srctf end - @views function swforward_1shot!( ::CPMLBoundaryCondition, wavsim::AcousticVDStaggeredCPMLWaveSimul{N}, @@ -109,10 +105,10 @@ end # posrecs, # srctf, # recs - ) where {N} +) where {N} # scale source time function, etc. - possrcs,posrecs,scal_srctf = possrcrec_scaletf(wavsim,shot) + possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) # Pressure and velocity arrays pcur = wavsim.pcur diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 7c047ee..040f040 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -10,10 +10,10 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # srctf, # recs, misfit - )::Array{<:Real} where {N} +)::Array{<:Real} where {N} # scale source time function, etc. - possrcs,posrecs,scal_srctf = possrcrec_scaletf(model,shot) + possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) # Numerics nt = model.nt @@ -159,10 +159,10 @@ end # srctf, # recs, misfit - )::Array{<:Real} where {N} +)::Array{<:Real} where {N} # scale source time function, etc. - possrcs,posrecs,scal_srctf = possrcrec_scaletf(model,shot) + possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) # Numerics nt = model.nt @@ -211,7 +211,7 @@ end end # Start populating save buffer at last checkpoint if it >= model.last_checkpoint - copyto!(model.save_buffer[fill(Colon(), N)..., it - model.last_checkpoint + 1], pcur) + copyto!(model.save_buffer[fill(Colon(), N)..., it-model.last_checkpoint+1], pcur) end end @@ -271,15 +271,20 @@ end save_trace=false ) if recit % model.infoevery == 0 - @debug @sprintf("Recover forward iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", recit, model.dt * recit, maximum(abs.(Array(pcur)))) + @debug @sprintf( + "Recover forward iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", + recit, + model.dt * recit, + maximum(abs.(Array(pcur))) + ) end # Save recovered pressure in save buffer - copyto!(model.save_buffer[fill(Colon(), N)..., recit - (curr_checkpoint+1) + 2], pcur) + copyto!(model.save_buffer[fill(Colon(), N)..., recit-(curr_checkpoint+1)+2], pcur) end end # Get pressure fields from saved buffer - pcur_corr = model.save_buffer[fill(Colon(), N)..., (it - curr_checkpoint)+1] - pcur_old = model.save_buffer[fill(Colon(), N)..., (it - curr_checkpoint)] + pcur_corr = model.save_buffer[fill(Colon(), N)..., (it-curr_checkpoint)+1] + pcur_old = model.save_buffer[fill(Colon(), N)..., (it-curr_checkpoint)] # Correlate for gradient computation model.backend.correlate_gradient_m0!(model.curgrad_m0, adjpcur, pcur_corr, pcur_old, model.dt) model.backend.correlate_gradient_m1!(model.curgrad_m1_stag, adjvcur, pcur_corr, model.gridspacing) @@ -299,10 +304,11 @@ end # compute regularization if needed dχ_dvp, dχ_drho = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) # Rescale gradients with respect to material properties (chain rule) - return reshape(hcat( - .-2.0 .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp - .-gradient_m0 ./ (model.matprop.vp .^ 2 .* model.matprop.rho .^ 2) .- gradient_m1 ./ model.matprop.rho .+ dχ_drho # grad wrt rho - ), - model.totgrad_size... - ) + return reshape( + hcat( + .-2.0 .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp + .-gradient_m0 ./ (model.matprop.vp .^ 2 .* model.matprop.rho .^ 2) .- gradient_m1 ./ model.matprop.rho .+ dχ_drho # grad wrt rho + ), + model.totgrad_size... + ) end diff --git a/src/models/acoustic/acou_material_properties.jl b/src/models/acoustic/acou_material_properties.jl index a414683..51a0272 100644 --- a/src/models/acoustic/acou_material_properties.jl +++ b/src/models/acoustic/acou_material_properties.jl @@ -12,7 +12,6 @@ struct VpAcousticCDMaterialProperties{N} <: MaterialProperties{N} vp::Array{<:Float64, N} end - @doc """ $(TYPEDEF) @@ -46,7 +45,6 @@ mutable struct VpRhoAcousticVDMaterialProperties{N} <: MaterialProperties{N} end end - @doc """ $(SIGNATURES) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 336d70c..6d8e692 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -111,7 +111,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} # Backend backend::Module parall::Symbol - + function AcousticCDCPMLWaveSimul{N}( ns::NTuple{N, <:Integer}, gridspacing::NTuple{N, <:Real}, @@ -324,7 +324,7 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() @views function check_courant_condition(model::AcousticVDStaggeredWaveSimul{N}, vp::Array{<:Real, N}) where {N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) - courant = vel_max * model.dt * tmp * 7/6 # 7/6 comes from the higher order stencil + courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil @debug "Courant number: $(courant)" if courant > 1 @warn "Courant condition not satisfied! [$(courant)]" diff --git a/src/models/acoustic/acou_params.jl b/src/models/acoustic/acou_params.jl index b83a3ee..5941772 100644 --- a/src/models/acoustic/acou_params.jl +++ b/src/models/acoustic/acou_params.jl @@ -70,5 +70,3 @@ end # return InputParametersAcousticVariableDensity{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) # end - - diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index a0e4140..7032d6e 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -33,15 +33,13 @@ end pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * (d2p_dx2) end -@views function update_ψ!(ψ_l, ψ_r, pcur, halo, nx, _dx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - for i in 1:(halo+1) +@views update_ψ!(ψ_l, ψ_r, pcur, halo, nx, _dx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) = for i in 1:(halo+1) ii = i + nx - halo - 2 # shift for right boundary pressure indices # left boundary ψ_l[i] = b_x_hl[i] * ψ_l[i] + a_x_hl[i] * (pcur[i+1] - pcur[i]) * _dx # right boundary ψ_r[i] = b_x_hr[i] * ψ_r[i] + a_x_hr[i] * (pcur[ii+1] - pcur[ii]) * _dx end -end @views function update_p_CPML!( pold, pcur, pnew, halo, fact, nx, _dx, _dx2, diff --git a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl index 7b9b4e9..0e235af 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl @@ -13,7 +13,7 @@ end end @parallel_indices (i) function update_p_CPML!(pcur, vx_cur, halo, fact_m0, nx, _dx, - ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) + ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) # Compute velocity derivatives dv_dx = @d_dx_4th(vx_cur, i) * _dx # Update CPML memory arrays if on the boundary @@ -34,9 +34,9 @@ end end @parallel_indices (i) function update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) # Compute pressure derivative in x direction - dp_dx = @d_dx_4th(pcur, i+1) * _dx + dp_dx = @d_dx_4th(pcur, i + 1) * _dx # Update CPML memory arrays if on the boundary if i <= halo + 1 # left boundary @@ -79,14 +79,13 @@ end _dx = 1 / (dx * 24) @parallel (3:(nx-2)) update_p_CPML!(pcur, vx_cur, halo, fact_m0, nx, _dx, - ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) + ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) @parallel (2:(nx-2)) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) if save_trace @parallel (1:size(posrecs, 1)) record_receivers!(pcur, traces, posrecs, it) end - end @views function backward_onestep_CPML!( @@ -100,9 +99,9 @@ end _dx = 1 / (dx * 24) @parallel (2:(nx-2)) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) @parallel (3:(nx-2)) update_p_CPML!(pcur, vx_cur, halo, fact_m0, nx, _dx, - ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) + ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) end @@ -113,7 +112,7 @@ end end @parallel_indices (i) function correlate_gradient_m1_kernel_x!(curgrad_m1_stag_x, adjvcur_x, pold, _dx) - curgrad_m1_stag_x[i] = curgrad_m1_stag_x[i] + adjvcur_x[i] * @d_dx_4th(pold, i+1) * _dx + curgrad_m1_stag_x[i] = curgrad_m1_stag_x[i] + adjvcur_x[i] * @d_dx_4th(pold, i + 1) * _dx return nothing end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl index 50028c0..abb8719 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl @@ -14,77 +14,77 @@ end return nothing end -@parallel_indices (i,j) function update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, - ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, - ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) +@parallel_indices (i, j) function update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, + ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, + ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) # Compute velocity derivatives dv_dx = @d_dx_4th(vx_cur, i, j) * _dx dv_dy = @d_dy_4th(vy_cur, i, j) * _dy # Update CPML memory arrays if on the boundary if i <= halo + 1 # left boundary - ξ_x_l[i-1,j] = b_x_l[i-1] * ξ_x_l[i-1,j] + a_x_l[i-1] * dv_dx - dv_dx += ξ_x_l[i-1,j] + ξ_x_l[i-1, j] = b_x_l[i-1] * ξ_x_l[i-1, j] + a_x_l[i-1] * dv_dx + dv_dx += ξ_x_l[i-1, j] elseif i >= nx - halo # right boundary ii = i - (nx - halo) + 1 - ξ_x_r[ii,j] = b_x_r[ii] * ξ_x_r[ii,j] + a_x_r[ii] * dv_dx - dv_dx += ξ_x_r[ii,j] + ξ_x_r[ii, j] = b_x_r[ii] * ξ_x_r[ii, j] + a_x_r[ii] * dv_dx + dv_dx += ξ_x_r[ii, j] end if j <= halo + 1 # top boundary - ξ_y_l[i,j-1] = b_y_l[j-1] * ξ_y_l[i,j-1] + a_y_l[j-1] * dv_dy - dv_dy += ξ_y_l[i,j-1] + ξ_y_l[i, j-1] = b_y_l[j-1] * ξ_y_l[i, j-1] + a_y_l[j-1] * dv_dy + dv_dy += ξ_y_l[i, j-1] elseif j >= ny - halo # bottom boundary jj = j - (ny - halo) + 1 - ξ_y_r[i,jj] = b_y_r[jj] * ξ_y_r[i,jj] + a_y_r[jj] * dv_dy - dv_dy += ξ_y_r[i,jj] + ξ_y_r[i, jj] = b_y_r[jj] * ξ_y_r[i, jj] + a_y_r[jj] * dv_dy + dv_dy += ξ_y_r[i, jj] end # Update pressure - pcur[i,j] -= fact_m0[i,j] * (dv_dx + dv_dy) + pcur[i, j] -= fact_m0[i, j] * (dv_dx + dv_dy) return nothing end -@parallel_indices (i,j) function update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) +@parallel_indices (i, j) function update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, + ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) # Compute pressure derivative in x direction - dp_dx = @d_dx_4th(pcur, i+1, j) * _dx + dp_dx = @d_dx_4th(pcur, i + 1, j) * _dx # Update CPML memory arrays if on the boundary if i <= halo + 1 # left boundary - ψ_x_l[i,j] = b_x_hl[i] * ψ_x_l[i,j] + a_x_hl[i] * dp_dx - dp_dx += ψ_x_l[i,j] + ψ_x_l[i, j] = b_x_hl[i] * ψ_x_l[i, j] + a_x_hl[i] * dp_dx + dp_dx += ψ_x_l[i, j] elseif i >= nx - halo - 1 # right boundary ii = i - (nx - halo - 1) + 1 - ψ_x_r[ii,j] = b_x_hr[ii] * ψ_x_r[ii,j] + a_x_hr[ii] * dp_dx - dp_dx += ψ_x_r[ii,j] + ψ_x_r[ii, j] = b_x_hr[ii] * ψ_x_r[ii, j] + a_x_hr[ii] * dp_dx + dp_dx += ψ_x_r[ii, j] end # Update velocity - vx_cur[i,j] -= fact_m1_x[i,j] * dp_dx + vx_cur[i, j] -= fact_m1_x[i, j] * dp_dx return nothing end -@parallel_indices (i,j) function update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, - ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) +@parallel_indices (i, j) function update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, + ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) # Compute pressure derivative in y direction - dp_dy = @d_dy_4th(pcur, i, j+1) * _dy + dp_dy = @d_dy_4th(pcur, i, j + 1) * _dy # Update CPML memory arrays if on the boundary if j <= halo + 1 # top boundary - ψ_y_l[i,j] = b_y_hl[j] * ψ_y_l[i,j] + a_y_hl[j] * dp_dy - dp_dy += ψ_y_l[i,j] + ψ_y_l[i, j] = b_y_hl[j] * ψ_y_l[i, j] + a_y_hl[j] * dp_dy + dp_dy += ψ_y_l[i, j] elseif j >= ny - halo - 1 # bottom boundary jj = j - (ny - halo - 1) + 1 - ψ_y_r[i,jj] = b_y_hr[jj] * ψ_y_r[i,jj] + a_y_hr[jj] * dp_dy - dp_dy += ψ_y_r[i,jj] + ψ_y_r[i, jj] = b_y_hr[jj] * ψ_y_r[i, jj] + a_y_hr[jj] * dp_dy + dp_dy += ψ_y_r[i, jj] end # Update velocity - vy_cur[i,j] -= fact_m1_y[i,j] * dp_dy + vy_cur[i, j] -= fact_m1_y[i, j] * dp_dy return nothing end @@ -118,21 +118,20 @@ end _dx = 1 / (dx * 24) _dy = 1 / (dy * 24) - @parallel (3:(nx-2),3:(ny-2)) update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, - ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, - ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) + @parallel (3:(nx-2), 3:(ny-2)) update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, + ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, + ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) - @parallel_async (2:(nx-2),1:ny) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - @parallel_async (1:nx,2:(ny-2)) update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, - ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) + @parallel_async (2:(nx-2), 1:ny) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, + ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + @parallel_async (1:nx, 2:(ny-2)) update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, + ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) @synchronize if save_trace @parallel (1:size(posrecs, 1)) record_receivers!(pcur, traces, posrecs, it) end - end @views function backward_onestep_CPML!( @@ -149,17 +148,16 @@ end _dx = 1 / (dx * 24) _dy = 1 / (dy * 24) - @parallel_async (2:(nx-2),1:ny) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - @parallel_async (1:nx,2:(ny-2)) update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, - ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) + @parallel_async (2:(nx-2), 1:ny) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, + ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + @parallel_async (1:nx, 2:(ny-2)) update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, + ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) @synchronize - @parallel (3:(nx-2),3:(ny-2)) update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, - ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, - ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) + @parallel (3:(nx-2), 3:(ny-2)) update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, + ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, + ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) - end @views function correlate_gradient_m1!(curgrad_m1_stag, adjvcur, pold, gridspacing) @@ -169,14 +167,14 @@ end @parallel (1:nx, 2:nx-2) correlate_gradient_m1_kernel_y!(curgrad_m1_stag[2], adjvcur[2], pold, _gridspacing[2]) end -@parallel_indices (i,j) function correlate_gradient_m1_kernel_x!(curgrad_m1_stag_x, adjvcur_x, pold, _dx) - curgrad_m1_stag_x[i,j] = curgrad_m1_stag_x[i,j] + adjvcur_x[i,j] * @d_dx_4th(pold, i+1, j) * _dx +@parallel_indices (i, j) function correlate_gradient_m1_kernel_x!(curgrad_m1_stag_x, adjvcur_x, pold, _dx) + curgrad_m1_stag_x[i, j] = curgrad_m1_stag_x[i, j] + adjvcur_x[i, j] * @d_dx_4th(pold, i + 1, j) * _dx return nothing end -@parallel_indices (i,j) function correlate_gradient_m1_kernel_y!(curgrad_m1_stag_y, adjvcur_y, pold, _dy) - curgrad_m1_stag_y[i,j] = curgrad_m1_stag_y[i,j] + adjvcur_y[i,j] * @d_dy_4th(pold, i, j+1) * _dy +@parallel_indices (i, j) function correlate_gradient_m1_kernel_y!(curgrad_m1_stag_y, adjvcur_y, pold, _dy) + curgrad_m1_stag_y[i, j] = curgrad_m1_stag_y[i, j] + adjvcur_y[i, j] * @d_dy_4th(pold, i, j + 1) * _dy return nothing end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl index 3328853..3ad648a 100644 --- a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl +++ b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl @@ -1,3 +1,3 @@ macro d_dx_4th(a, i) - return esc( :( ( -$a[$i+1] + 27.0 * $a[$i] - 27.0 * $a[$i-1] + $a[$i-2] ) ) ) + return esc(:((-$a[$i+1] + 27.0 * $a[$i] - 27.0 * $a[$i-1] + $a[$i-2]))) end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl index 732aba9..2dce407 100644 --- a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl +++ b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl @@ -1,7 +1,7 @@ macro d_dx_4th(a, i, j) - return esc( :( ( -$a[$i+1, $j] + 27.0 * $a[$i, $j] - 27.0 * $a[$i-1, $j] + $a[$i-2, $j] ) ) ) + return esc(:((-$a[$i+1, $j] + 27.0 * $a[$i, $j] - 27.0 * $a[$i-1, $j] + $a[$i-2, $j]))) end macro d_dy_4th(a, i, j) - return esc( :( ( -$a[$i, $j+1] + 27.0 * $a[$i, $j] - 27.0 * $a[$i, $j-1] + $a[$i, $j-2] ) ) ) + return esc(:((-$a[$i, $j+1] + 27.0 * $a[$i, $j] - 27.0 * $a[$i, $j-1] + $a[$i, $j-2]))) end diff --git a/src/models/acoustic/backends/shared/smooth_gradient_1D.jl b/src/models/acoustic/backends/shared/smooth_gradient_1D.jl index 94e9797..fcc9b89 100644 --- a/src/models/acoustic/backends/shared/smooth_gradient_1D.jl +++ b/src/models/acoustic/backends/shared/smooth_gradient_1D.jl @@ -1,8 +1,8 @@ function smooth_gradient!(grad, possrcs, radius) nx = length(grad) - nsources = size(possrcs,1) + nsources = size(possrcs, 1) for s in 1:nsources - isrc = possrcs[s,1] + isrc = possrcs[s, 1] imin = isrc - radius imax = isrc + radius for i in imin:imax diff --git a/src/models/acoustic/backends/shared/smooth_gradient_2D.jl b/src/models/acoustic/backends/shared/smooth_gradient_2D.jl index 2a15893..b739dba 100644 --- a/src/models/acoustic/backends/shared/smooth_gradient_2D.jl +++ b/src/models/acoustic/backends/shared/smooth_gradient_2D.jl @@ -1,9 +1,9 @@ function smooth_gradient!(grad, possrcs, radius) nx, ny = size(grad) - nsources = size(possrcs,1) + nsources = size(possrcs, 1) for s in 1:nsources - isrc = possrcs[s,1] - jsrc = possrcs[s,2] + isrc = possrcs[s, 1] + jsrc = possrcs[s, 2] imin = isrc - radius imax = isrc + radius jmin = jsrc - radius diff --git a/src/models/acoustic/backends/shared/smooth_gradient_3D.jl b/src/models/acoustic/backends/shared/smooth_gradient_3D.jl index 1962857..46331cc 100644 --- a/src/models/acoustic/backends/shared/smooth_gradient_3D.jl +++ b/src/models/acoustic/backends/shared/smooth_gradient_3D.jl @@ -1,10 +1,10 @@ function smooth_gradient!(grad, possrcs, radius) nx, ny, nz = size(grad) - nsources = size(possrcs,1) + nsources = size(possrcs, 1) for s in 1:nsources - isrc = possrcs[s,1] - jsrc = possrcs[s,2] - ksrc = possrcs[s,3] + isrc = possrcs[s, 1] + jsrc = possrcs[s, 2] + ksrc = possrcs[s, 3] imin = isrc - radius imax = isrc + radius jmin = jsrc - radius diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index 8fac6d1..17e2bb6 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -1,5 +1,4 @@ - select_backend(wavesim_type::Type{<:WaveSimul}, parall::Symbol) = select_backend(BoundaryConditionTrait(wavesim_type), GridTrait(wavesim_type), wavesim_type, Val{parall}) @@ -59,7 +58,6 @@ select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggere select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU - # Backend selections for ElasticIsoWaveSimul select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimul{2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 2580c9b..6c6f492 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -6,20 +6,20 @@ struct CPMLCoefficientsAxis b_h::Any function CPMLCoefficientsAxis(halo::Integer, backend::Module, - sizehalfgrdplusone::Bool=false) + sizehalfgrdplusone::Bool=false) if sizehalfgrdplusone return new( - backend.zeros(2 * halo), - backend.zeros(2 * (halo+1) +1 ), - backend.zeros(2 * halo), - backend.zeros(2 * (halo+1) +1), + backend.zeros(2 * halo), + backend.zeros(2 * (halo + 1) + 1), + backend.zeros(2 * halo), + backend.zeros(2 * (halo + 1) + 1) ) else return new( - backend.zeros(2 * halo), - backend.zeros(2 * (halo+1)), - backend.zeros(2 * halo), - backend.zeros(2 * (halo+1)) + backend.zeros(2 * halo), + backend.zeros(2 * (halo + 1)), + backend.zeros(2 * halo), + backend.zeros(2 * (halo + 1)) ) end end @@ -38,7 +38,7 @@ function compute_CPML_coefficientsAxis!( alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) npower = 2.0 # CPML power coefficient d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile - a_l, a_r, b_l, b_r = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :startongrd) + a_l, a_r, b_l, b_r = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :startongrd) a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :starthalfgrd) # @show size(cpmlcoeffs.a),size(a_l),size(a_r) @@ -48,10 +48,10 @@ function compute_CPML_coefficientsAxis!( # @show a_r # @show a_hr - copyto!(cpmlcoeffs.a, vcat(a_l,a_r)) - copyto!(cpmlcoeffs.a_h, vcat(a_hl,a_hr)) - copyto!(cpmlcoeffs.b, vcat(b_l,b_r)) - copyto!(cpmlcoeffs.b_h, vcat(b_hl,b_hr)) + copyto!(cpmlcoeffs.a, vcat(a_l, a_r)) + copyto!(cpmlcoeffs.a_h, vcat(a_hl, a_hr)) + copyto!(cpmlcoeffs.b, vcat(b_l, b_r)) + copyto!(cpmlcoeffs.b_h, vcat(b_hl, b_hr)) end ################################################################# @@ -67,28 +67,28 @@ struct CPMLCoefficients b_hr::Any function CPMLCoefficients(halo::Integer, backend::Module, - sizehalfgrdplusone::Bool=false) + sizehalfgrdplusone::Bool=false) if sizehalfgrdplusone return new( - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo + 1), - backend.zeros(halo + 1), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo + 1), - backend.zeros(halo + 1) + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo + 1), + backend.zeros(halo + 1), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo + 1), + backend.zeros(halo + 1) ) else return new( - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo) + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo), + backend.zeros(halo) ) end end @@ -97,7 +97,6 @@ end # Default type constructor # CPMLCoefficients(halo) = CPMLCoefficients{Float64}(halo) - function calc_Kab_CPML_staggeredgrid( halo::Integer, dt::Float64, @@ -122,17 +121,17 @@ function calc_Kab_CPML_staggeredgrid( end # distance from edge node - dist_left = collect(LinRange(shift_left, Kab_size+shift_left-1, Kab_size)) - dist_right = collect(LinRange(shift_right, Kab_size+shift_right-1, Kab_size)) + dist_left = collect(LinRange(shift_left, Kab_size + shift_left - 1, Kab_size)) + dist_right = collect(LinRange(shift_right, Kab_size + shift_right - 1, Kab_size)) if halo != 0 - normdist_left = reverse(dist_left) ./ (halo-0.5) - normdist_right = dist_right ./ (halo-0.5) + normdist_left = reverse(dist_left) ./ (halo - 0.5) + normdist_right = dist_right ./ (halo - 0.5) else normdist_left = reverse(dist_left) normdist_right = dist_right end - + if K_max_pml === nothing K_left = 1.0 else @@ -161,7 +160,7 @@ function calc_Kab_CPML_staggeredgrid( # @show normdist_right # @show a_left # @show a_right - + if K_max_pml === nothing return a_left, a_right, b_left, b_right else @@ -169,7 +168,6 @@ function calc_Kab_CPML_staggeredgrid( end end - ##################################### function compute_CPML_coefficients!( @@ -187,7 +185,7 @@ function compute_CPML_coefficients!( d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile if halo == 0 # fix for thickness == 0 generating NaNs d0 = 0.0 - end + end a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 0bec042..3707571 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -1,9 +1,8 @@ module Elastic2D_Iso_CPML_Serial - # To get those structs into this module -using SeismicWaves: ElasticIsoCPMLWaveSimul,ElasticIsoMaterialProperties +using SeismicWaves: ElasticIsoCPMLWaveSimul, ElasticIsoMaterialProperties # Dummy data module module Data @@ -14,8 +13,6 @@ end ones = Base.ones zeros = Base.zeros - - # Staggered grid with equal spacing in x and z. # Second order in time, fourth order in space. # Convolutionary Perfectly Matched Layer (C-PML) boundary conditions @@ -71,7 +68,6 @@ zeros = Base.zeros # | vz(i,j) | vz(i+1/2,j+1/2) | # ------------------------------------------------ - ############################## # Derivative operators ############################## @@ -91,46 +87,43 @@ zeros = Base.zeros # Weigths for taking derivarives for incresing indices # Dweights = 1.0/inpar.dh * [1/24.0, -27.0/24.0, 27.0/24.0, -1/24.0] - - -function update_4thord_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx∂x,ψ_∂σxz∂z,b_x,b_z,a_x,a_z, - freetop) +function update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x, b_z, a_x, a_z, + freetop) if freetop - for j = 1:2 - for i = 3:nx-1 - + for j in 1:2 + for i in 3:nx-1 + # Vx # σxx derivative only in x so no problem - ∂σxx∂x_bkw = factx * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) + ∂σxx∂x_bkw = factx * (σxx[i-2, j] - 27.0 * σxx[i-1, j] + 27.0 * σxx[i, j] - σxx[i+1, j]) # image, mirroring σxz[i,j-2] = -σxz[i,j+1], etc. #∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) - if j==1 + if j == 1 # j bwd-> -2 -1|0 1 (mirror -2 and -1) - ∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) - elseif j==2 + ∂σxz∂z_bkw = factz * (-σxz[i, j+1] + 27.0 * σxz[i, j] + 27.0 * σxz[i, j] - σxz[i, j+1]) + elseif j == 2 # j bwd-> -2|-1 0 1 (mirror only -2) - ∂σxz∂z_bkw = factz * ( -σxz[i,j] -27.0*σxz[i,j-1] +27.0*σxz[i,j] -σxz[i,j+1] ) + ∂σxz∂z_bkw = factz * (-σxz[i, j] - 27.0 * σxz[i, j-1] + 27.0 * σxz[i, j] - σxz[i, j+1]) end # update velocity - vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) - + vx[i, j] = vx[i, j] + (dt / ρ[i, j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) end end end - + # vx - for j = 3:nz-1 - for i = 3:nx-1 - + for j in 3:nz-1 + for i in 3:nx-1 + # Vx - ∂σxx∂x_bkw = factx * ( σxx[i-2,j] -27.0*σxx[i-1,j] +27.0*σxx[i,j] -σxx[i+1,j] ) - ∂σxz∂z_bkw = factz * ( σxz[i,j-2] -27.0*σxz[i,j-1] +27.0*σxz[i,j] -σxz[i,j+1] ) + ∂σxx∂x_bkw = factx * (σxx[i-2, j] - 27.0 * σxx[i-1, j] + 27.0 * σxx[i, j] - σxx[i+1, j]) + ∂σxz∂z_bkw = factz * (σxz[i, j-2] - 27.0 * σxz[i, j-1] + 27.0 * σxz[i, j] - σxz[i, j+1]) ##======================= # C-PML stuff ##======================= # x boundaries - + # con1 = (i <= halo) # con2 = (i >= nx - halo + 1) # if con1 || con2 @@ -145,27 +138,27 @@ function update_4thord_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx if i <= halo # # left boundary - ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw - ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i,j] - elseif i >= nx - halo + 1 + ψ_∂σxx∂x[i, j] = b_x[i] * ψ_∂σxx∂x[i, j] + a_x[i] * ∂σxx∂x_bkw + ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i, j] + elseif i >= nx - halo + 1 # right boundary - ii = i - (nx - 2*halo) - ψ_∂σxx∂x[ii,j] = b_x[ii] * ψ_∂σxx∂x[ii,j] + a_x[ii] * ∂σxx∂x_bkw - ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii,j] + ii = i - (nx - 2 * halo) + ψ_∂σxx∂x[ii, j] = b_x[ii] * ψ_∂σxx∂x[ii, j] + a_x[ii] * ∂σxx∂x_bkw + ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii, j] end # y boundaries - if j <= halo && freetop==false + if j <= halo && freetop == false # top boundary - ψ_∂σxz∂z[i,j] = b_z[j] * ψ_∂σxz∂z[i,j] + a_z[j] * ∂σxz∂z_bkw - ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] - elseif j >= nz - halo + 1 + ψ_∂σxz∂z[i, j] = b_z[j] * ψ_∂σxz∂z[i, j] + a_z[j] * ∂σxz∂z_bkw + ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i, j] + elseif j >= nz - halo + 1 # bottom boundary - jj = j - (nz - 2*halo) - ψ_∂σxz∂z[i,jj] = b_z[jj] * ψ_∂σxz∂z[i,jj] + a_z[jj] * ∂σxz∂z_bkw - ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,jj] + jj = j - (nz - 2 * halo) + ψ_∂σxz∂z[i, jj] = b_z[jj] * ψ_∂σxz∂z[i, jj] + a_z[jj] * ∂σxz∂z_bkw + ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i, jj] end ##======================= - + # # C-PML stuff # # DO NOT delete this part! # ψ_∂σxx∂x[i,j] = b_x[i] * ψ_∂σxx∂x[i,j] + a_x[i] * ∂σxx∂x_bkw @@ -175,74 +168,68 @@ function update_4thord_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,ψ_∂σxx # ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i,j] # update velocity - vx[i,j] = vx[i,j] + (dt/ρ[i,j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) - + vx[i, j] = vx[i, j] + (dt / ρ[i, j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) end - end + end return end - - -function update_4thord_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,ψ_∂σxz∂x,ψ_∂σzz∂z, - b_x_half,b_z_half,a_x_half,a_z_half,freetop) - +function update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, + b_x_half, b_z_half, a_x_half, a_z_half, freetop) if freetop - for j = 1:2 - for i = 2:nx-2 + for j in 1:2 + for i in 2:nx-2 # Vz # σxz derivative only in x so no problem - ∂σxz∂x_fwd = factx * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) + ∂σxz∂x_fwd = factx * (σxz[i-1, j] - 27.0 * σxz[i, j] + 27.0 * σxz[i+1, j] - σxz[i+2, j]) # image, mirroring σzz[i,j-1] = -σxz[i,j+2], etc. #∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) - if j==1 + if j == 1 # j fwd-> -1 0| 1 2 (mirror -2 and -1) - ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) - elseif j==2 + ∂σzz∂z_fwd = factz * (-σzz[i, j+2] + 27.0 * σzz[i, j+1] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) + elseif j == 2 # j fwd-> -1|0 1 2 (mirror only -1) - ∂σzz∂z_fwd = factz * ( -σzz[i,j+2] -27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + ∂σzz∂z_fwd = factz * (-σzz[i, j+2] - 27.0 * σzz[i, j] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) end # update velocity (ρ has been interpolated in advance) - vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) - + vz[i, j] = vz[i, j] + (dt / ρ_ihalf_jhalf[i, j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) end end end # vz - for j = 2:nz-2 - for i = 2:nx-2 - - # Vz - ∂σxz∂x_fwd = factx * ( σxz[i-1,j] -27.0*σxz[i,j] +27.0*σxz[i+1,j] -σxz[i+2,j] ) - ∂σzz∂z_fwd = factz * ( σzz[i,j-1] -27.0*σzz[i,j] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + for j in 2:nz-2 + for i in 2:nx-2 + # Vz + ∂σxz∂x_fwd = factx * (σxz[i-1, j] - 27.0 * σxz[i, j] + 27.0 * σxz[i+1, j] - σxz[i+2, j]) + ∂σzz∂z_fwd = factz * (σzz[i, j-1] - 27.0 * σzz[i, j] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) ##======================= # C-PML stuff ##======================= # x boundaries - if i <= halo + if i <= halo # left boundary - ψ_∂σxz∂x[i,j] = b_x_half[i] * ψ_∂σxz∂x[i,j] + a_x_half[i]*∂σxz∂x_fwd - ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i,j] + ψ_∂σxz∂x[i, j] = b_x_half[i] * ψ_∂σxz∂x[i, j] + a_x_half[i] * ∂σxz∂x_fwd + ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i, j] elseif i >= nx - halo + 1 # right boundary - ii = i - (nx - 2*halo) - ψ_∂σxz∂x[ii,j] = b_x_half[ii] * ψ_∂σxz∂x[ii,j] + a_x_half[ii]*∂σxz∂x_fwd - ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[ii,j] + ii = i - (nx - 2 * halo) + ψ_∂σxz∂x[ii, j] = b_x_half[ii] * ψ_∂σxz∂x[ii, j] + a_x_half[ii] * ∂σxz∂x_fwd + ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[ii, j] end # y boundaries - if j <= halo && freetop==false # + 1 + if j <= halo && freetop == false # + 1 # top boundary - ψ_∂σzz∂z[i,j] = b_z_half[j] * ψ_∂σzz∂z[i,j] + a_z_half[j]*∂σzz∂z_fwd - ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] + ψ_∂σzz∂z[i, j] = b_z_half[j] * ψ_∂σzz∂z[i, j] + a_z_half[j] * ∂σzz∂z_fwd + ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i, j] elseif j >= nz - halo + 1 # bottom boundary - jj = j - (nz - 2*halo) - ψ_∂σzz∂z[i,jj] = b_z_half[jj] * ψ_∂σzz∂z[i,jj] + a_z_half[jj]*∂σzz∂z_fwd - ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,jj] + jj = j - (nz - 2 * halo) + ψ_∂σzz∂z[i, jj] = b_z_half[jj] * ψ_∂σzz∂z[i, jj] + a_z_half[jj] * ∂σzz∂z_fwd + ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i, jj] end ##======================= @@ -254,191 +241,182 @@ function update_4thord_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf # ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i,j] # update velocity (ρ has been interpolated in advance) - vz[i,j] = vz[i,j] + (dt/ρ_ihalf_jhalf[i,j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) - + vz[i, j] = vz[i, j] + (dt / ρ_ihalf_jhalf[i, j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) end end return end - -function update_4thord_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, - vx,vz,dt,λ_ihalf,μ_ihalf,ψ_∂vx∂x,ψ_∂vz∂z, - b_x_half,b_z,a_x_half,a_z,freetop) - - if freetop==true +function update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, ψ_∂vx∂x, ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + if freetop == true # σxx, σzz # j=1: we are on the free surface! - j = 1 - for i = 2:nx-2 + j = 1 + for i in 2:nx-2 # σxx # vx derivative only in x so no problem - ∂vx∂x_fwd = factx * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd - ∂vz∂z_bkd = -(1.0-2.0*μ_ihalf[i,j]/λ_ihalf[i,j])*∂vx∂x_fwd + ∂vz∂z_bkd = -(1.0 - 2.0 * μ_ihalf[i, j] / λ_ihalf[i, j]) * ∂vx∂x_fwd # σxx # σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd - σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j] - λ_ihalf[i,j] / (λ_ihalf[i,j]+2+μ_ihalf[i,j]) + 2*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] - λ_ihalf[i, j] / (λ_ihalf[i, j] + 2 + μ_ihalf[i, j]) + 2 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd # σzz - σzz[i,j] = 0.0 # we are on the free surface! + σzz[i, j] = 0.0 # we are on the free surface! end # j=2: we are just below the surface (1/2) j = 2 - for i = 2:nx-2 + for i in 2:nx-2 # σxx # vx derivative only in x so no problem - ∂vx∂x_fwd = factx * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) + ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) # zero velocity above the free surface - ∂vz∂z_bkd = factz * ( 0.0 -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) + ∂vz∂z_bkd = factz * (0.0 - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) # σxx - σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + - λ_ihalf[i,j] * dt * ∂vz∂z_bkd + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i, j] * dt * ∂vz∂z_bkd # σzz - σzz[i,j] = σzz[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vz∂z_bkd + - λ_ihalf[i,j] * dt * ∂vx∂x_fwd + σzz[i, j] = σzz[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vz∂z_bkd + + λ_ihalf[i, j] * dt * ∂vx∂x_fwd end end # σxx, σzz - for j = 3:nz-1 - for i = 2:nx-2 - + for j in 3:nz-1 + for i in 2:nx-2 + # σxx,σzz - ∂vx∂x_fwd = factx * ( vx[i-1,j] -27.0*vx[i,j] +27.0*vx[i+1,j] -vx[i+2,j] ) - ∂vz∂z_bkd = factz * ( vz[i,j-2] -27.0*vz[i,j-1] +27.0*vz[i,j] -vz[i,j+1] ) + ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) + ∂vz∂z_bkd = factz * (vz[i, j-2] - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) ##======================= # C-PML stuff ##======================= # x boundaries - if i <= halo + if i <= halo # left boundary - ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd - ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] + ψ_∂vx∂x[i, j] = b_x_half[i] * ψ_∂vx∂x[i, j] + a_x_half[i] * ∂vx∂x_fwd + ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i, j] elseif i >= nx - halo + 1 # right boundary - ii = i - (nx - 2*halo) - ψ_∂vx∂x[ii,j] = b_x_half[ii] * ψ_∂vx∂x[ii,j] + a_x_half[ii]*∂vx∂x_fwd - ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[ii,j] + ii = i - (nx - 2 * halo) + ψ_∂vx∂x[ii, j] = b_x_half[ii] * ψ_∂vx∂x[ii, j] + a_x_half[ii] * ∂vx∂x_fwd + ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[ii, j] end # y boundaries - if j <= halo && freetop==false + if j <= halo && freetop == false # top boundary - ψ_∂vz∂z[i,j] = b_z[j] * ψ_∂vz∂z[i,j] + a_z[j]*∂vz∂z_bkd - ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] + ψ_∂vz∂z[i, j] = b_z[j] * ψ_∂vz∂z[i, j] + a_z[j] * ∂vz∂z_bkd + ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i, j] elseif j >= nz - halo + 1 # bottom boundary - jj = j - (nz - 2*halo) - ψ_∂vz∂z[i,jj] = b_z[jj] * ψ_∂vz∂z[i,jj] + a_z[jj]*∂vz∂z_bkd - ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,jj] + jj = j - (nz - 2 * halo) + ψ_∂vz∂z[i, jj] = b_z[jj] * ψ_∂vz∂z[i, jj] + a_z[jj] * ∂vz∂z_bkd + ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i, jj] end ##======================= - + # # C-PML stuff # # DO NOT delete this part! # ψ_∂vx∂x[i,j] = b_x_half[i] * ψ_∂vx∂x[i,j] + a_x_half[i]*∂vx∂x_fwd # ψ_∂vz∂z[i,j] = b_z[j] * ψ_∂vz∂z[i,j] + a_z[j]*∂vz∂z_bkd # ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i,j] # ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i,j] - + # σxx - σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + - λ_ihalf[i,j] * dt * ∂vz∂z_bkd + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i, j] * dt * ∂vz∂z_bkd ## derivatives are the same than for σxx # σzz - σzz[i,j] = σzz[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vz∂z_bkd + - λ_ihalf[i,j] * dt * ∂vx∂x_fwd - + σzz[i, j] = σzz[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vz∂z_bkd + + λ_ihalf[i, j] * dt * ∂vx∂x_fwd end end return end - -function update_4thord_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, - μ_jhalf,b_x,b_z_half, - ψ_∂vx∂z,ψ_∂vz∂x,a_x,a_z_half, - freetop) - +function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, + freetop) if freetop # σxz j = 1 - for i=3:nx-1 + for i in 3:nx-1 # zero velocity above the free surface - ∂vx∂z_fwd = factz * ( 0.0 -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) + ∂vx∂z_fwd = factz * (0.0 - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) # vz derivative only in x so no problem - ∂vz∂x_bkd = factx * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) # σxz - σxz[i,j] = σxz[i,j] + μ_jhalf[i,j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) + σxz[i, j] = σxz[i, j] + μ_jhalf[i, j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) end end # σxz - for j = 2:nz-2 - for i = 3:nx-1 + for j in 2:nz-2 + for i in 3:nx-1 # σxz - ∂vx∂z_fwd = factz * ( vx[i,j-1] -27.0*vx[i,j] +27.0*vx[i,j+1] -vx[i,j+2] ) - ∂vz∂x_bkd = factx * ( vz[i-2,j] -27.0*vz[i-1,j] +27.0*vz[i,j] -vz[i+1,j] ) - + ∂vx∂z_fwd = factz * (vx[i, j-1] - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) + ##======================= # C-PML stuff ##======================= # x boundaries - if i <= halo + if i <= halo # left boundary - ψ_∂vz∂x[i,j] = b_x[i] * ψ_∂vz∂x[i,j] + a_x[i]*∂vz∂x_bkd - ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] + ψ_∂vz∂x[i, j] = b_x[i] * ψ_∂vz∂x[i, j] + a_x[i] * ∂vz∂x_bkd + ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i, j] elseif i >= nx - halo + 1 # right boundary - ii = i - (nx - 2*halo) - ψ_∂vz∂x[ii,j] = b_x[ii] * ψ_∂vz∂x[ii,j] + a_x[ii]*∂vz∂x_bkd - ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[ii,j] + ii = i - (nx - 2 * halo) + ψ_∂vz∂x[ii, j] = b_x[ii] * ψ_∂vz∂x[ii, j] + a_x[ii] * ∂vz∂x_bkd + ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[ii, j] end # y boundaries - if j <= halo && freetop==false + if j <= halo && freetop == false # top boundary - ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd - ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] + ψ_∂vx∂z[i, j] = b_z_half[j] * ψ_∂vx∂z[i, j] + a_z_half[j] * ∂vx∂z_fwd + ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i, j] elseif j >= nz - halo + 1 # bottom boundary - jj = j - (nz - 2*halo) - ψ_∂vx∂z[i,jj] = b_z_half[jj] * ψ_∂vx∂z[i,jj] + a_z_half[jj]*∂vx∂z_fwd - ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,jj] + jj = j - (nz - 2 * halo) + ψ_∂vx∂z[i, jj] = b_z_half[jj] * ψ_∂vx∂z[i, jj] + a_z_half[jj] * ∂vx∂z_fwd + ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i, jj] end ##======================= - + # # C-PML stuff # # DO NOT delete this part! # ψ_∂vz∂x[i,j] = b_x[i] * ψ_∂vz∂x[i,j] + a_x[i]*∂vz∂x_bkd # ψ_∂vx∂z[i,j] = b_z_half[j] * ψ_∂vx∂z[i,j] + a_z_half[j]*∂vx∂z_fwd # ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i,j] # ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i,j] - - # σxz - σxz[i,j] = σxz[i,j] + μ_jhalf[i,j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) + # σxz + σxz[i, j] = σxz[i, j] + μ_jhalf[i, j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) end end return end - - function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, - srccoeij_bk::Array{<:Integer}, - srccoeval_bk::Array{<:Real}, - reccoeij_bk::Array{<:Integer}, - reccoeval_bk::Array{<:Real}, - srctf_bk::Matrix{<:Real}, - traces_bk::Array{<:Real}, - it::Integer, - Mxx_bk::Vector{<:Real}, - Mzz_bk::Vector{<:Real}, - Mxz_bk::Vector{<:Real}; - save_trace::Bool=true) where {N} + srccoeij_bk::Array{<:Integer}, + srccoeval_bk::Array{<:Real}, + reccoeij_bk::Array{<:Integer}, + reccoeval_bk::Array{<:Real}, + srctf_bk::Matrix{<:Real}, + traces_bk::Array{<:Real}, + it::Integer, + Mxx_bk::Vector{<:Real}, + Mzz_bk::Vector{<:Real}, + Mxz_bk::Vector{<:Real}; + save_trace::Bool=true) where {N} # function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, # possrcs_bk::Array{<:Integer,2}, # srctf_bk::Matrix{<:Real}, @@ -450,14 +428,14 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, # Mxz_bk::Vector{<:Real}; # save_trace::Bool=true) where {N} - @assert N==2 + @assert N == 2 freetop = wavsim.freetop cpmlcoeffs = wavsim.cpmlcoeffs matprop = wavsim.matprop dx = wavsim.gridspacing[1] dz = wavsim.gridspacing[2] dt = wavsim.dt - nx,nz = wavsim.gridsize[1:2] + nx, nz = wavsim.gridsize[1:2] halo = wavsim.halo vx = wavsim.velpartic.vx @@ -465,7 +443,7 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, σxx = wavsim.stress.σxx σzz = wavsim.stress.σzz σxz = wavsim.stress.σxz - + psi = wavsim.ψ a_x = cpmlcoeffs[1].a @@ -492,63 +470,63 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, # error("\nExiting...") ## pre-scale coefficients - factx = 1.0/(24.0*dx) - factz = 1.0/(24.0*dz) - + factx = 1.0 / (24.0 * dx) + factz = 1.0 / (24.0 * dz) + # update velocity vx - update_4thord_vx!(nx,nz,halo,vx,factx,factz,σxx,σxz,dt,ρ,psi.ψ_∂σxx∂x,psi.ψ_∂σxz∂z, - b_x,b_z,a_x,a_z,freetop) + update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, psi.ψ_∂σxx∂x, psi.ψ_∂σxz∂z, + b_x, b_z, a_x, a_z, freetop) # update velocity vz - update_4thord_vz!(nx,nz,halo,vz,factx,factz,σxz,σzz,dt,ρ_ihalf_jhalf,psi.ψ_∂σxz∂x, - psi.ψ_∂σzz∂z,b_x_half,b_z_half,a_x_half,a_z_half,freetop) + update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, psi.ψ_∂σxz∂x, + psi.ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # inject sources (external body force) #inject_bodyforce_sources!(vx,vz,fx,fz,srctf_bk, dt, possrcs_bk,it) # update stresses σxx and σzz - update_4thord_σxxσzz!(nx,nz,halo,σxx,σzz,factx,factz, - vx,vz,dt,λ_ihalf,μ_ihalf, - psi.ψ_∂vx∂x,psi.ψ_∂vz∂z, - b_x_half,b_z,a_x_half,a_z,freetop) + update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, + psi.ψ_∂vx∂x, psi.ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) # update stress σxz - update_4thord_σxz!(nx,nz,halo,σxz,factx,factz,vx,vz,dt, - μ_jhalf,b_x,b_z_half, - psi.ψ_∂vx∂z,psi.ψ_∂vz∂x,a_x,a_z_half,freetop) + update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + psi.ψ_∂vx∂z, psi.ψ_∂vz∂x, a_x, a_z_half, freetop) # inject sources (moment tensor type of internal force) - inject_momten_sources2D!(σxx,σzz,σxz,Mxx_bk,Mzz_bk,Mxz_bk,srctf_bk,dt, - srccoeij_bk,srccoeval_bk,it) - #possrcs_bk,it) - + inject_momten_sources2D!(σxx, σzz, σxz, Mxx_bk, Mzz_bk, Mxz_bk, srctf_bk, dt, + srccoeij_bk, srccoeval_bk, it) + #possrcs_bk,it) + # record receivers if save_trace - record_receivers2D!(vx,vz,traces_bk,reccoeij_bk,reccoeval_bk,it) + record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) end - + return end -function inject_momten_sources2D!(σxx,σzz,σxz,Mxx,Mzz,Mxz,srctf_bk,dt,srccoeij_bk,srccoeval_bk,it) -#function inject_momten_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) +function inject_momten_sources2D!(σxx, σzz, σxz, Mxx, Mzz, Mxz, srctf_bk, dt, srccoeij_bk, srccoeval_bk, it) + #function inject_momten_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) ## Inject the source as stress from moment tensor ## See Igel 2017 Computational Seismology (book) page 31, 2.6.1 lensrctf = length(srctf_bk) - if it<=lensrctf + if it <= lensrctf # total number of interpolation points - nsrcpts = size(srccoeij_bk,1) + nsrcpts = size(srccoeij_bk, 1) # p runs on all interpolation points defined by the windowed sinc function # s runs on all actual source locations as specified by user input - for p=1:nsrcpts + for p in 1:nsrcpts # [src_id, i, j] - s,isrc,jsrc = srccoeij_bk[p,:] + s, isrc, jsrc = srccoeij_bk[p, :] # update stresses on points computed from sinc interpolation # scaled with the coefficients' values - σxx[isrc,jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] * dt - σzz[isrc,jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] * dt - σxz[isrc,jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] * dt end - + # for s in axes(possrcs_bk, 1) # isrc = possrcs_bk[s, 1] # jsrc = possrcs_bk[s, 2] @@ -556,25 +534,24 @@ function inject_momten_sources2D!(σxx,σzz,σxz,Mxx,Mzz,Mxz,srctf_bk,dt,srccoei # σzz[isrc,jsrc] += Mzz[s] * srctf_bk[it] * dt # σxz[isrc,jsrc] += Mxz[s] * srctf_bk[it] * dt # end - end + end return end - -function record_receivers2D!(vx,vz,traces_bk,reccoeij_bk,reccoeval_bk,it) +function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) # total number of interpolation points - nrecpts = size(reccoeij_bk,1) + nrecpts = size(reccoeij_bk, 1) # p runs on all interpolation points defined by the windowed sinc function # s runs on all actual source locations as specified by user input - for p=1:nrecpts + for p in 1:nrecpts # [src_id, i, j] - r,irec,jrec = reccoeij_bk[p,:] + r, irec, jrec = reccoeij_bk[p, :] # update traces by summing up values from all sinc interpolation points - traces_bk[it,1,r] += vx[irec,jrec] - traces_bk[it,2,r] += vz[irec,jrec] + traces_bk[it, 1, r] += vx[irec, jrec] + traces_bk[it, 2, r] += vz[irec, jrec] end - + # for ir in axes(posrecs, 1) # irec = posrecs[ir, 1] # jrec = posrecs[ir, 2] @@ -585,19 +562,17 @@ function record_receivers2D!(vx,vz,traces_bk,reccoeij_bk,reccoeval_bk,it) return end - #function correlate_gradient!( ) - # _dt2 = 1 / dt^2 - # nx, nz = size(curgrad) - # for j in 1:nz - # for i in 1:nx - # curgrad[i, j] = curgrad[i, j] + (adjcur[i, j] * (pcur[i, j] - 2.0 * pold[i, j] + pveryold[i, j]) * _dt2) - # end - # end - # return +# _dt2 = 1 / dt^2 +# nx, nz = size(curgrad) +# for j in 1:nz +# for i in 1:nx +# curgrad[i, j] = curgrad[i, j] + (adjcur[i, j] * (pcur[i, j] - 2.0 * pold[i, j] + pveryold[i, j]) * _dt2) +# end +# end +# return #end - ######################################### end # end module ######################################### diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index c99ab66..e615a87 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -3,7 +3,6 @@ abstract type ElasticWaveSimul{N} <: WaveSimul{N} end abstract type ElasticIsoWaveSimul{N} <: ElasticWaveSimul{N} end - abstract type ElasticMaterialProperties{N} <: MaterialProperties{N} end abstract type AbstrElasticIsoMaterialProperties{N} <: ElasticMaterialProperties{N} end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 68d7eec..e905007 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -1,7 +1,6 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) - @views function swforward_1shot!( ::CPMLBoundaryCondition, wavsim::ElasticIsoCPMLWaveSimul{N}, @@ -10,23 +9,23 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # posrecs::Matrix{<:Integer}, # srctf, # recs - ) where {N} +) where {N} # scale source time function, etc. # find nearest grid points indexes for both sources and receivers # possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) # posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) - if N==2 + if N == 2 # interpolation coefficients for sources - srccoeij,srccoeval = spreadsrcrecinterp2D(wavsim.gridspacing,wavsim.gridsize, - shot.srcs.positions, - nptssinc=4,xstart=0.0,zstart=0.0) + srccoeij, srccoeval = spreadsrcrecinterp2D(wavsim.gridspacing, wavsim.gridsize, + shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) # interpolation coefficients for receivers - reccoeij,reccoeval = spreadsrcrecinterp2D(wavsim.gridspacing,wavsim.gridsize, - shot.recs.positions, - nptssinc=4,xstart=0.0,zstart=0.0) - elseif N==3 + reccoeij, reccoeval = spreadsrcrecinterp2D(wavsim.gridspacing, wavsim.gridsize, + shot.recs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + elseif N == 3 error("swforward_1shot!(): Elastic 3D not yet implemented!") end @@ -37,26 +36,26 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Numerics nt = wavsim.nt - + # Wrap sources and receivers arrays - + # possrcs_bk = wavsim.backend.Data.Array(possrcs) # posrecs_bk = wavsim.backend.Data.Array(posrecs) - + srccoeij_bk = wavsim.backend.Data.Array(srccoeij) srccoeval_bk = wavsim.backend.Data.Array(srccoeval) reccoeij_bk = wavsim.backend.Data.Array(reccoeij) reccoeval_bk = wavsim.backend.Data.Array(reccoeval) - srctf_bk = wavsim.backend.Data.Array(srctf) + srctf_bk = wavsim.backend.Data.Array(srctf) traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) - if N==2 + if N == 2 ## ONLY 2D for now!!! Mxx_bk = wavsim.backend.Data.Array(momtens.Mxx) Mzz_bk = wavsim.backend.Data.Array(momtens.Mzz) Mxz_bk = wavsim.backend.Data.Array(momtens.Mxz) - elseif N==3 + elseif N == 3 error("swforward_1shot!(): Elastic 3D not yet implemented!") end @@ -67,19 +66,18 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Time loop for it in 1:nt - - if N==2 + if N == 2 # Compute one forward step wavsim.backend.forward_onestep_CPML!(wavsim, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, - srctf_bk, - traces_bk, - it, - Mxx_bk,Mzz_bk,Mxz_bk, - save_trace=true) + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + traces_bk, + it, + Mxx_bk, Mzz_bk, Mxz_bk; + save_trace=true) # # Compute one forward step # wavsim.backend.forward_onestep_CPML!(wavsim, # possrcs_bk, @@ -90,9 +88,9 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Mxx_bk,Mzz_bk,Mxz_bk, # save_trace=true) else - error("swforward_1shot!(): Elastic 3D not yet implemented!") + error("swforward_1shot!(): Elastic 3D not yet implemented!") end - + # Print timestep info if it % wavsim.infoevery == 0 # Move the cursor to the beginning to overwrite last line @@ -101,7 +99,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # REPL.Terminals.cmove_line_up(ter) @info @sprintf( "Iteration: %d/%d, simulation time: %g s", - it,nt, + it, nt, wavsim.dt * (it - 1) ) end @@ -123,44 +121,41 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC return end - - -function spreadsrcrecinterp2D(gridspacing::NTuple{N,Real},gridsize::NTuple{N,Integer}, - positions::Matrix{<:Real}; - nptssinc::Int=4,xstart::Real=0.0,zstart::Real=0.0) where N - - nloc = size(positions,1) - Ndim = size(positions,2) - @assert Ndim==2 - @assert N==Ndim +function spreadsrcrecinterp2D(gridspacing::NTuple{N, Real}, gridsize::NTuple{N, Integer}, + positions::Matrix{<:Real}; + nptssinc::Int=4, xstart::Real=0.0, zstart::Real=0.0) where {N} + nloc = size(positions, 1) + Ndim = size(positions, 2) + @assert Ndim == 2 + @assert N == Ndim Δx = gridspacing[1] Δz = gridspacing[2] - nx,nz = gridsize[1:2] + nx, nz = gridsize[1:2] - maxnumcoeff = nloc * (2*nptssinc+1)^Ndim - coeij_tmp = zeros(Int,maxnumcoeff,Ndim+1) + maxnumcoeff = nloc * (2 * nptssinc + 1)^Ndim + coeij_tmp = zeros(Int, maxnumcoeff, Ndim + 1) coeval_tmp = zeros(maxnumcoeff) - l=0 - for p=1:nloc + l = 0 + for p in 1:nloc # extract x and z position for source or receiver p - xpos,zpos = positions[p,:] + xpos, zpos = positions[p, :] # compute grid indices and values of sinc coefficients - xidx,zidx,xzcoeff = coeffsinc2D(xstart,zstart,Δx,Δz,xpos,zpos, - nx,nz,[:monopole,:monopole],npts=nptssinc) - for j=1:length(zidx) - for i=1:length(xidx) - l+=1 + xidx, zidx, xzcoeff = coeffsinc2D(xstart, zstart, Δx, Δz, xpos, zpos, + nx, nz, [:monopole, :monopole]; npts=nptssinc) + for j in 1:length(zidx) + for i in 1:length(xidx) + l += 1 # id, i, j indices - coeij_tmp[l,:] .= (p,xidx[i],zidx[j]) + coeij_tmp[l, :] .= (p, xidx[i], zidx[j]) # coefficients value - coeval_tmp[l] = xzcoeff[i,j] + coeval_tmp[l] = xzcoeff[i, j] end - end + end end # keep only the valid part of the arrays - coeij = coeij_tmp[1:l,:] + coeij = coeij_tmp[1:l, :] coeval = coeval_tmp[1:l] - return coeij,coeval + return coeij, coeval end diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl index a35dfc1..936a32d 100644 --- a/src/models/elastic/ela_init_bc.jl +++ b/src/models/elastic/ela_init_bc.jl @@ -14,7 +14,7 @@ init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimul, srcs::Sources) #@show n,typeof(model.cpmlcoeffs[n]) compute_CPML_coefficientsAxis!( model.cpmlcoeffs[n], - get_maximum_func(model)( sqrt.((model.matprop.λ+2.0*model.matprop.μ)./model.matprop.ρ) ), + get_maximum_func(model)(sqrt.((model.matprop.λ + 2.0 * model.matprop.μ) ./ model.matprop.ρ)), model.dt, model.halo, model.rcoef, @@ -26,9 +26,9 @@ init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimul, srcs::Sources) if model.freetop && N >= 1 lastcoe = model.cpmlcoeffs[N] - lastcoe.a[1:length(lastcoe.a)÷2] .= 0.0 + lastcoe.a[1:length(lastcoe.a)÷2] .= 0.0 lastcoe.a_h[1:length(lastcoe.a_h)÷2] .= 0.0 - lastcoe.b[1:length(lastcoe.b)÷2] .= 1.0 + lastcoe.b[1:length(lastcoe.b)÷2] .= 1.0 lastcoe.b_h[1:length(lastcoe.b_h)÷2] .= 1.0 # model.cpmlcoeffs[N].a_l .= 0.0 # model.cpmlcoeffs[N].a_hl .= 0.0 diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index a5b38f3..ca5f141 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -5,17 +5,16 @@ Base.@kwdef struct ElasticIsoMaterialProperties{N} <: AbstrElasticIsoMaterialPro ρ::Array{<:AbstractFloat, N} end - # Material properties for 2D simulations Base.@kwdef struct ElasticIsoMaterialProperties2D <: AbstrElasticIsoMaterialProperties{2} - λ::Array{<:AbstractFloat,2} - μ::Array{<:AbstractFloat,2} - ρ::Array{<:AbstractFloat,2} - λ_ihalf::Array{<:AbstractFloat,2} - μ_ihalf::Array{<:AbstractFloat,2} - μ_jhalf::Array{<:AbstractFloat,2} - ρ_ihalf_jhalf::Array{<:AbstractFloat,2} - + λ::Array{<:AbstractFloat, 2} + μ::Array{<:AbstractFloat, 2} + ρ::Array{<:AbstractFloat, 2} + λ_ihalf::Array{<:AbstractFloat, 2} + μ_ihalf::Array{<:AbstractFloat, 2} + μ_jhalf::Array{<:AbstractFloat, 2} + ρ_ihalf_jhalf::Array{<:AbstractFloat, 2} + # function ElasticIsoMaterialProperties{N}(ρ::Array{<:AbstractFloat, N}, # μ::Array{<:AbstractFloat, N}, # λ::Array{<:AbstractFloat, N}) where {N} @@ -29,39 +28,37 @@ Base.@kwdef struct ElasticIsoMaterialProperties2D <: AbstrElasticIsoMaterialProp # λ_ihalf = zeros(tyrho,nx-1,ny) # precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; # harmonicaver_μ=true) - + # return new{N}(λ,μ,ρ,λ_ihalf,μ_ihalf,μ_jhalf,ρ_ihalf_jhalf) # end end - - function precomp_elaprop!(matprop::ElasticIsoMaterialProperties2D; harmonicaver_μ=true) - -# function precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; -# harmonicaver_μ=true) + + # function precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; + # harmonicaver_μ=true) #------------------------------------------------------------- # pre-interpolate properties at half distances between nodes #------------------------------------------------------------- # ρ_ihalf_jhalf (nx-1,nz-1) ?? # arithmetic mean for ρ - @. matprop.ρ_ihalf_jhalf = (matprop.ρ[2:end,2:end]+matprop.ρ[2:end,1:end-1]+ - matprop.ρ[1:end-1,2:end]+matprop.ρ[1:end-1,1:end-1])/4.0 + @. matprop.ρ_ihalf_jhalf = (matprop.ρ[2:end, 2:end] + matprop.ρ[2:end, 1:end-1] + + matprop.ρ[1:end-1, 2:end] + matprop.ρ[1:end-1, 1:end-1]) / 4.0 # μ_ihalf (nx-1,nz) ?? # μ_ihalf (nx,nz-1) ?? - if harmonicaver_μ==true + if harmonicaver_μ == true # harmonic mean for μ - @. matprop.μ_ihalf = 1.0 / ( 1.0/matprop.μ[2:end,:] + 1.0 / matprop.μ[1:end-1,:] ) - @. matprop.μ_jhalf = 1.0 / ( 1.0/matprop.μ[:,2:end] + 1.0 / matprop.μ[:,1:end-1] ) + @. matprop.μ_ihalf = 1.0 / (1.0 / matprop.μ[2:end, :] + 1.0 / matprop.μ[1:end-1, :]) + @. matprop.μ_jhalf = 1.0 / (1.0 / matprop.μ[:, 2:end] + 1.0 / matprop.μ[:, 1:end-1]) else # arithmetic mean for μ - @. matprop.μ_ihalf = (matprop.μ[2:end,:] + matprop.μ[1:end-1,:]) / 2.0 - @. matprop.μ_jhalf = (matprop.μ[:,2:end] + matprop.μ[:,1:end-1]) / 2.0 + @. matprop.μ_ihalf = (matprop.μ[2:end, :] + matprop.μ[1:end-1, :]) / 2.0 + @. matprop.μ_jhalf = (matprop.μ[:, 2:end] + matprop.μ[:, 1:end-1]) / 2.0 end # λ_ihalf (nx-1,nz) ?? # arithmetic mean for λ - @. matprop.λ_ihalf = (matprop.λ[2:end,:] + matprop.λ[1:end-1,:]) / 2.0 + @. matprop.λ_ihalf = (matprop.λ[2:end, :] + matprop.λ[1:end-1, :]) / 2.0 return end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 7cd1736..632691a 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -10,7 +10,7 @@ @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" @assert all(matprop.ρ .> 0) "Density must be positive!" - + # Check courant condition vel_max = get_maximum_func(wavsim)(vp) tmp = sqrt.(sum(1 ./ wavsim.gridspacing .^ 2)) @@ -23,7 +23,6 @@ return end - function check_numerics( wavsim::ElasticIsoWaveSimul, shot::Shot; @@ -31,18 +30,17 @@ function check_numerics( ) # Check points per wavelengh # min Vs - vel_min = get_minimum_func(wavsim)(sqrt.(wavsim.matprop.μ ./ wavsim.matprop.ρ)) + vel_min = get_minimum_func(wavsim)(sqrt.(wavsim.matprop.μ ./ wavsim.matprop.ρ)) h_max = maximum(wavsim.gridspacing) fmax = shot.srcs.domfreq * 2.0 - ppw = vel_min / (fmax * h_max) + ppw = vel_min / (fmax * h_max) @debug "Points per wavelength: $(ppw)" - dh0 = round((vel_min/(min_ppw*fmax)),digits=2) + dh0 = round((vel_min / (min_ppw * fmax)); digits=2) @assert ppw >= min_ppw "Not enough points per wavelength (assuming fmax = 2*domfreq)! \n [$(round(ppw,digits=1)) instead of >= $min_ppw]\n Grid spacing should be <= $dh0" return end - @views function update_matprop!(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperties{N}) where {N} # Update material properties @@ -56,68 +54,60 @@ end return end - ########################################################### +struct Elasticψdomain2D{T <: AbstractFloat} + ψ_∂σxx∂x::Array{T, 2} + ψ_∂σxz∂z::Array{T, 2} + ψ_∂σxz∂x::Array{T, 2} + ψ_∂σzz∂z::Array{T, 2} + ψ_∂vx∂x::Array{T, 2} + ψ_∂vz∂z::Array{T, 2} + ψ_∂vz∂x::Array{T, 2} + ψ_∂vx∂z::Array{T, 2} + + function Elasticψdomain2D(backend, gridsize, halo) + @assert length(gridsize) == 2 + ψ_gridsize = [gridsize...] -struct Elasticψdomain2D{T<:AbstractFloat} - ψ_∂σxx∂x::Array{T,2} - ψ_∂σxz∂z::Array{T,2} - ψ_∂σxz∂x::Array{T,2} - ψ_∂σzz∂z::Array{T,2} - ψ_∂vx∂x::Array{T,2} - ψ_∂vz∂z::Array{T,2} - ψ_∂vz∂x::Array{T,2} - ψ_∂vx∂z::Array{T,2} - - function Elasticψdomain2D(backend,gridsize,halo) + gs1, gs2 = copy(ψ_gridsize), copy(ψ_gridsize) + gs1[1] = 2 * halo + gs2[2] = 2 * halo - @assert length(gridsize)==2 - ψ_gridsize = [gridsize...] + ψ_∂σxx∂x = backend.zeros(gs1...) + ψ_∂σxz∂z = backend.zeros(gs2...) + ψ_∂σxz∂x = backend.zeros(gs1...) + ψ_∂σzz∂z = backend.zeros(gs2...) + ψ_∂vx∂x = backend.zeros(gs1...) + ψ_∂vz∂z = backend.zeros(gs2...) + ψ_∂vz∂x = backend.zeros(gs1...) + ψ_∂vx∂z = backend.zeros(gs2...) - gs1,gs2 = copy(ψ_gridsize),copy(ψ_gridsize) - gs1[1] = 2*halo - gs2[2] = 2*halo - - ψ_∂σxx∂x = backend.zeros( gs1...) - ψ_∂σxz∂z = backend.zeros( gs2...) - ψ_∂σxz∂x = backend.zeros( gs1...) - ψ_∂σzz∂z = backend.zeros( gs2...) - ψ_∂vx∂x = backend.zeros( gs1...) - ψ_∂vz∂z = backend.zeros( gs2...) - ψ_∂vz∂x = backend.zeros( gs1...) - ψ_∂vx∂z = backend.zeros( gs2...) - T = eltype(ψ_∂σxx∂x) return new{T}(ψ_∂σxx∂x, - ψ_∂σxz∂z, - ψ_∂σxz∂x, - ψ_∂σzz∂z, - ψ_∂vx∂x, - ψ_∂vz∂z, - ψ_∂vz∂x, - ψ_∂vx∂z) + ψ_∂σxz∂z, + ψ_∂σxz∂x, + ψ_∂σzz∂z, + ψ_∂vx∂x, + ψ_∂vz∂z, + ψ_∂vz∂x, + ψ_∂vx∂z) end end - -struct Velpartic2D{T<:AbstractFloat} - vx::Array{T,2} - vz::Array{T,2} +struct Velpartic2D{T <: AbstractFloat} + vx::Array{T, 2} + vz::Array{T, 2} end - -struct Stress2D{T<:AbstractFloat} - σxx::Array{T,2} - σzz::Array{T,2} - σxz::Array{T,2} +struct Stress2D{T <: AbstractFloat} + σxx::Array{T, 2} + σzz::Array{T, 2} + σxz::Array{T, 2} end - - ############################################################## - struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Physics domainextent::NTuple{N, <:Real} @@ -158,7 +148,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Backend backend::Module parall::Symbol - + function ElasticIsoCPMLWaveSimul{N}( gridsize::NTuple{N, <:Integer}, gridspacing::NTuple{N, <:Real}, @@ -186,38 +176,38 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} # Compute wavsim sizes domainextent = gridspacing .* (gridsize .- 1) - + # Select backend backend = select_backend(ElasticIsoCPMLWaveSimul{N}, parall) # Initialize material properties - if N==2 - matprop = ElasticIsoMaterialProperties2D(λ=backend.zeros(gridsize...), - μ=backend.zeros(gridsize...), - ρ=backend.zeros(gridsize...), - λ_ihalf=backend.zeros((gridsize.-[1,0])...), - μ_ihalf=backend.zeros((gridsize.-[1,0])...), - μ_jhalf=backend.zeros((gridsize.-[0,1])...), - ρ_ihalf_jhalf=backend.zeros((gridsize.-1)...) - ) + if N == 2 + matprop = ElasticIsoMaterialProperties2D(; λ=backend.zeros(gridsize...), + μ=backend.zeros(gridsize...), + ρ=backend.zeros(gridsize...), + λ_ihalf=backend.zeros((gridsize .- [1, 0])...), + μ_ihalf=backend.zeros((gridsize .- [1, 0])...), + μ_jhalf=backend.zeros((gridsize .- [0, 1])...), + ρ_ihalf_jhalf=backend.zeros((gridsize .- 1)...) + ) else error("Only elastic 2D is currently implemented.") end # Initialize computational arrays - if N==2 + if N == 2 velpartic = Velpartic2D([backend.zeros(gridsize...) for _ in 1:N]...) # vx, vy[, vz] stress = Stress2D([backend.zeros(gridsize...) for _ in 1:(N-1)*3]...) # vx, vy[, vz] end - + ## - if N==2 # 2D - ψ = Elasticψdomain2D(backend,gridsize,halo) - else + if N == 2 # 2D + ψ = Elasticψdomain2D(backend, gridsize, halo) + else error("Only elastic 2D is currently implemented.") end - + # Initialize CPML coefficients cpmlcoeffs = [CPMLCoefficientsAxis(halo, backend) for _ in 1:N] @@ -326,10 +316,10 @@ end # Reset computational arrays for p in propertynames(wavsim.velpartic) - getfield(wavsim.velpartic,p) .= 0.0 + getfield(wavsim.velpartic, p) .= 0.0 end for p in propertynames(wavsim.stress) - getfield(wavsim.stress,p) .= 0.0 + getfield(wavsim.stress, p) .= 0.0 end for p in propertynames(wavsim.ψ) getfield(wavsim.ψ, p) .= 0.0 diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl index b3e9ee3..a3021c2 100644 --- a/src/models/elastic/ela_params.jl +++ b/src/models/elastic/ela_params.jl @@ -33,4 +33,3 @@ function InputParametersElastic( return InputParametersElastic{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) end - diff --git a/src/receivers.jl b/src/receivers.jl index 60be34f..412f9f0 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -33,7 +33,7 @@ struct ScalarReceivers{T <: Real} <: Receivers nt::Integer; observed::Union{Matrix{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing, - windows::Union{Vector{Pair{Int,Int}}, Nothing}=nothing + windows::Union{Vector{Pair{Int, Int}}, Nothing}=nothing ) where {T <: Real} @assert size(positions, 1) > 0 "There must be at least one receiver!" seismograms = zeros(T, nt, size(positions, 1)) @@ -58,7 +58,6 @@ struct ScalarReceivers{T <: Real} <: Receivers end end - # Default type constructor @doc """ $(SIGNATURES) @@ -69,8 +68,6 @@ Default constructor for Float64. ScalarReceivers(positions, nt; observed=nothing, invcov=nothing, windows=nothing) = ScalarReceivers{Float64}(positions, nt; observed=observed, invcov=invcov, windows=windows) - - @doc """ $(TYPEDEF) @@ -79,13 +76,13 @@ Type representing a multi-receiver configuration for a wave propagation shot. $(TYPEDFIELDS) """ # What about using the package ComputedFieldTypes.jl? @computed ... -struct VectorReceivers{N,T<:Real} <: Receivers +struct VectorReceivers{N, T <: Real} <: Receivers "Receiver positions" positions::Matrix{T} "Array holding seismograms (as columns)" - seismograms::Array{T,3} + seismograms::Array{T, 3} "Array holding observed seismograms (as columns)" - observed::Array{T,3} + observed::Array{T, 3} "Inverse of the covariance matrix" invcov::AbstractMatrix{T} @@ -94,30 +91,29 @@ struct VectorReceivers{N,T<:Real} <: Receivers Create a single shot wave propagation receivers configuration from receivers positions. """ - function VectorReceivers{N,T}( + function VectorReceivers{N, T}( positions::Matrix{T}, nt::Integer, ndim::Integer=2; observed::Union{Array{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing - ) where {N,T <: Real} + ) where {N, T <: Real} @assert size(positions, 1) > 0 "There must be at least one receiver!" seismograms = zeros(T, nt, ndim, size(positions, 1)) ## N+1 !!! <<<<<<<<--------------<<<< if observed !== nothing @assert size(seismograms) == size(observed) "Size of observed data is not (# timesteps, # receivers)!" else - observed = zeros(0,0,0) # (nt,ndim,npos) + observed = zeros(0, 0, 0) # (nt,ndim,npos) end if invcov !== nothing @assert size(invcov) == (nt, nt) "Size of invcov is not (# timesteps, # timesteps)!" else - invcov = zeros(0,0) + invcov = zeros(0, 0) end - return new{ndim,T}(positions, seismograms, observed, invcov) + return new{ndim, T}(positions, seismograms, observed, invcov) #return new(positions, seismograms, observed, invcov) end end # Default type constructor -VectorReceivers(positions, nt, ndim; observed=nothing, invcov=nothing) = VectorReceivers{ndim,Float64}(positions, nt, ndim; observed=observed, invcov=invcov) - +VectorReceivers(positions, nt, ndim; observed=nothing, invcov=nothing) = VectorReceivers{ndim, Float64}(positions, nt, ndim; observed=observed, invcov=invcov) diff --git a/src/solve.jl b/src/solve.jl index 4772e21..458ad5a 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -9,13 +9,12 @@ end ### FORWARDS ### - ## single WaveSimul object @views function run_swforward!( wavsim::WaveSimul{N}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - )::Union{Vector{Array}, Nothing} where {N} +)::Union{Vector{Array}, Nothing} where {N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -60,15 +59,14 @@ end wavsim::Vector{<:WaveSimul{N}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - )::Union{Vector{Array}, Nothing} where {N} - +)::Union{Vector{Array}, Nothing} where {N} nwsim = length(wavsim) nthr = Threads.nthreads() # make sure the number of threads has not changed! @assert nthr == nwsim takesnapshots = false - for w=1:nwsim + for w in 1:nwsim # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" check_sim_consistency(wavsim[w], matprop, shots) @@ -77,21 +75,21 @@ end @info "Setting wavesim material properties" set_wavesim_matprop!(wavsim[w], matprop) # Now onwards matprop from outside should not be used anymore!!! - + # Snapshots setup takesnapshots = snapenabled(wavsim[w]) if takesnapshots - snapshots_per_shot = [[] for j=1:nwsim] + snapshots_per_shot = [[] for j in 1:nwsim] end end # Shots loop nshots = length(shots) - grpshots = distribsrcs(nshots,nthr) # a vector of UnitRange + grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange # loop on the set of WaveSimul - Threads.@threads for w=1:nwsim + Threads.@threads for w in 1:nwsim # loop on the subset of shots per each WaveSimul - for s in grpshots[w] + for s in grpshots[w] singleshot = shots[s] # Initialize shot @info "Initializing shot" @@ -115,24 +113,23 @@ end return nothing end - ### MISFITS ### ## single or multiple WaveSimul objects @views function run_swmisfit!( - wavsim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}, + wavsim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; misfit::AbstractMisfit=L2Misfit(nothing) - )::Real where {N} - +)::Real where {N} + # Solve forward model for all shots run_swforward!(wavsim, matprop, shots) # Compute total misfit for all shots totmisfitval = 0 for singleshot in shots @info "Checking invcov matrix" - if typeof(wavsim)<:Vector{<:WaveSimul} + if typeof(wavsim) <: Vector{<:WaveSimul} check_invcov_matrix(wavsim[1], singleshot.recs.invcov) else check_invcov_matrix(wavsim, singleshot.recs.invcov) @@ -144,7 +141,6 @@ end return totmisfitval end - ### GRADIENTS ### ## single WaveSimul object @@ -154,7 +150,7 @@ end shots::Vector{<:Shot}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) - )::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} +)::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -168,7 +164,7 @@ end totgrad = zeros(wavsim.totgrad_size...) totmisfitval = 0 # Shots loop - for (s,singleshot) in enumerate(shots) + for (s, singleshot) in enumerate(shots) @info "Shot #$s" # Initialize shot @info "Initializing shot" @@ -198,7 +194,6 @@ end return compute_misfit ? (totgrad, totmisfitval) : totgrad end - ## :threadpersrc, multiple WaveSimul objects @views function run_swgradient!( wavsim::Vector{<:WaveSimul{N}}, @@ -206,14 +201,13 @@ end shots::Vector{<:Shot}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) - )::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} - +)::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} nwsim = length(wavsim) nthr = Threads.nthreads() # make sure the number of threads has not changed! @assert Threads.nthreads() == nwsim - for w=1:nwsim + for w in 1:nwsim # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" check_sim_consistency(wavsim[w], matprop, shots) @@ -225,7 +219,7 @@ end # Initialize total gradient and total misfit nshots = length(shots) - allgrad = [zeros(wavsim[1].totgrad_size...) for i=1:nshots] + allgrad = [zeros(wavsim[1].totgrad_size...) for i in 1:nshots] if compute_misfit allmisfitval = zeros(nshots) @@ -234,11 +228,11 @@ end # Shots loop nshots = length(shots) - grpshots = distribsrcs(nshots,nthr) # a vector of UnitRange + grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange # loop on the set of WaveSimul - Threads.@threads for w=1:nwsim + Threads.@threads for w in 1:nwsim # loop on the subset of shots per each WaveSimul - for s in grpshots[w] + for s in grpshots[w] singleshot = shots[s] @info "Shot #$s" # Initialize shot @@ -266,11 +260,11 @@ end end end end - + totgrad = sum(allgrad) if compute_misfit totmisfitval = sum(allmisfitval) end - + return compute_misfit ? (totgrad, totmisfitval) : totgrad end diff --git a/src/sources.jl b/src/sources.jl index d7a13e1..1ddae82 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -12,7 +12,7 @@ struct ScalarSources{T <: Real} <: Sources tf::Matrix{T} "Dominant frequency" domfreq::T - + @doc """ ScalarSources{T}(positions::Matrix{<:Real}, tf::Matrix{T}, domfreq::T) where {T <: Real} @@ -40,24 +40,23 @@ ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, do Type representing vector components of a 2D moment tensor. """ Base.@kwdef struct MomentTensor2D{T <: Real} <: MomentTensor - Mxx::Vector{T} - Mzz::Vector{T} - Mxz::Vector{T} + Mxx::Vector{T} + Mzz::Vector{T} + Mxz::Vector{T} end """ Type representing vector components of a 2D moment tensor. """ Base.@kwdef struct MomentTensor3D{T <: Real} <: MomentTensor - Mxx::Vector{T} - Myy::Vector{T} - Mzz::Vector{T} - Mxy::Vector{T} - Mxz::Vector{T} - Myz::Vector{T} + Mxx::Vector{T} + Myy::Vector{T} + Mzz::Vector{T} + Mxy::Vector{T} + Mxz::Vector{T} + Myz::Vector{T} end - """ Type representing a multi-source configuration for a wave propagation shot. """ @@ -77,28 +76,28 @@ struct MomentTensorSources{N, T <: Real} <: Sources Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function MomentTensorSources{N,T}(positions::Matrix{T}, tf::Matrix{T}, momtens::MomentTensor, domfreq::T) where {N, T <: Real} + function MomentTensorSources{N, T}(positions::Matrix{T}, tf::Matrix{T}, momtens::MomentTensor, domfreq::T) where {N, T <: Real} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" - if N==2 - @assert typeof(momtens)<:MomentTensor2D - elseif N==3 - @assert typeof(momtens)<:MomentTensor3D + if N == 2 + @assert typeof(momtens) <: MomentTensor2D + elseif N == 3 + @assert typeof(momtens) <: MomentTensor3D else error("MomentTensorSources: Moment tensor neither 2D nor 3D.") end - return new{N,T}(positions, tf, momtens, domfreq) + return new{N, T}(positions, tf, momtens, domfreq) end end # Default type constructor {Float64} MomentTensorSources(positions, tf, momtens, domfreq) = begin - if typeof(momtens)<:MomentTensor2D - ndim=2 - elseif typeof(momtens)<:MomentTensor3D - ndim=3 + if typeof(momtens) <: MomentTensor2D + ndim = 2 + elseif typeof(momtens) <: MomentTensor3D + ndim = 3 end - MomentTensorSources{ndim,Float64}(positions, tf, momtens, domfreq) + MomentTensorSources{ndim, Float64}(positions, tf, momtens, domfreq) end #################################################### diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl index f1a0cde..66b525e 100644 --- a/src/srcrec_interpolation.jl +++ b/src/srcrec_interpolation.jl @@ -1,18 +1,15 @@ - #################################################################### """ - Kaiser windowing function. # Parameters -- `x`: coordinate of points -- `x0`: coordinate of source or receiver point -- `b`: 'b' coefficient -- `r`: cut-off radius - + - `x`: coordinate of points + - `x0`: coordinate of source or receiver point + - `b`: 'b' coefficient + - `r`: cut-off radius """ function kaiser(x::Vector, x0::Real, b::Real, r::Real) # Kaiser window function @@ -20,12 +17,12 @@ function kaiser(x::Vector, x0::Real, b::Real, r::Real) # Rule of thumb for finite diff.: # b=4.14 b=6.31 # r = 4.0*dx - w=zeros(length(x)) - for i=1:length(x) - xcur = x[i]-x0 - if -r<=xcur<=r - den = 1.0/besseli(0,b) - w[i] = den*besseli(0, b*(sqrt.(1 -(xcur/r)^2))) + w = zeros(length(x)) + for i in 1:length(x) + xcur = x[i] - x0 + if -r <= xcur <= r + den = 1.0 / besseli(0, b) + w[i] = den * besseli(0, b * (sqrt.(1 - (xcur / r)^2))) else w[i] = 0.0 end @@ -36,20 +33,18 @@ end ##################################################################### """ - Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. # Parameters -- `xstart`: origin coordinate of the grid -- `Δx`: grid spacing -- `kind`: :monopole or :dipole, i.e., using sinc or derivative of sinc -- `npts` (optional): half-number of grid points for the window -- `beta` (optional): 'beta' parameter for the Kaiser windowing function - + - `xstart`: origin coordinate of the grid + - `Δx`: grid spacing + - `kind`: :monopole or :dipole, i.e., using sinc or derivative of sinc + - `npts` (optional): half-number of grid points for the window + - `beta` (optional): 'beta' parameter for the Kaiser windowing function """ -function coeffsinc1D(xstart::Real,Δx::Real,xcenter::Real, kind::Symbol, nx::Integer ; - npts::Int64=4, beta::Union{Nothing,Real}=nothing) +function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::Integer; + npts::Int64=4, beta::Union{Nothing, Real}=nothing) ## Coefficients for sinc interpolation ## in 1D ## xstart is the x coordinate of first node in the regular grid @@ -62,47 +57,47 @@ function coeffsinc1D(xstart::Real,Δx::Real,xcenter::Real, kind::Symbol, nx::Int ### \sin(\pi x) / (\pi x) if x \neq 0, and 1 if x = 0 ### @assert xcenter >= xstart - @assert xcenter <= (nx-1)*Δx+xstart - - if beta==nothing - if kind==:monopole + @assert xcenter <= (nx - 1) * Δx + xstart + + if beta == nothing + if kind == :monopole beta = 4.14 - elseif kind==:dipole + elseif kind == :dipole beta = 4.40 end end - - radius = npts*Δx + + radius = npts * Δx ## Assuming x from grid starts at xstart - xh = (xcenter-xstart)/Δx - ix = floor(Int64,xh+1) - if mod((xcenter-xstart),Δx) == 0.0 - ixsta = ix-npts - ixend = ix+npts + xh = (xcenter - xstart) / Δx + ix = floor(Int64, xh + 1) + if mod((xcenter - xstart), Δx) == 0.0 + ixsta = ix - npts + ixend = ix + npts else - ixsta = ix-npts+1 - ixend = ix+npts + ixsta = ix - npts + 1 + ixend = ix + npts end - x = [xstart+Δx*(i-1) for i=ixsta:ixend] + x = [xstart + Δx * (i - 1) for i in ixsta:ixend] indexes = ixsta:ixend - - if kind==:monopole + + if kind == :monopole # interpolating sinc(x) = sin(pi*x)/(pi*x) see Julia definition - intrpsinc = sinc.((x.-xcenter)./Δx) # factor 1/Δx ?? - - elseif kind==:dipole + intrpsinc = sinc.((x .- xcenter) ./ Δx) # factor 1/Δx ?? + + elseif kind == :dipole # derivative of sinc # cosc(x) is the derivative of sinc(x) in Julia - intrpsinc = cosc.((x.-xcenter)./Δx) + intrpsinc = cosc.((x .- xcenter) ./ Δx) else error("coeffsinc1d(): Wrong argument 'kind'.") end # apply Kaiser windowing - kaix = kaiser(x,xcenter,beta,radius) - itpfun = kaix.*intrpsinc + kaix = kaiser(x, xcenter, beta, radius) + itpfun = kaix .* intrpsinc # return also indices of window (as a range) - return itpfun,indexes + return itpfun, indexes end # ## test: # begin @@ -119,36 +114,34 @@ end ##################################################################### """ - Compute 2-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. # Parameters -- `xstart`, `zstart`: origin coordinates of the grid -- `Δx`,`Δz` : grid spacing -- `xcenter`, `zcenter`: coordinates of source or receiver point -- `nx`,`nz`: grid size in x and y -- `kind`: vector of symbols :monopole or :dipole, i.e., using sinc or derivative of sinc -- `npts` (optional): half-number of grid points for the window -- `beta` (optional): 'beta' parameter for the Kaiser windowing function - + - `xstart`, `zstart`: origin coordinates of the grid + - `Δx`,`Δz` : grid spacing + - `xcenter`, `zcenter`: coordinates of source or receiver point + - `nx`,`nz`: grid size in x and y + - `kind`: vector of symbols :monopole or :dipole, i.e., using sinc or derivative of sinc + - `npts` (optional): half-number of grid points for the window + - `beta` (optional): 'beta' parameter for the Kaiser windowing function """ -function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real,zcenter::Real, - nx::Integer,nz::Integer,kind::Vector{Symbol} ; - npts::Int64=4, beta::Union{Nothing,Real}=nothing) +function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter::Real, zcenter::Real, + nx::Integer, nz::Integer, kind::Vector{Symbol}; + npts::Int64=4, beta::Union{Nothing, Real}=nothing) ## Calculate the 2D array of coefficients - xcoe,xidx = coeffsinc1D(xstart,Δx,xcenter,kind[1],nx,npts=npts,beta=beta) - zcoe,zidx = coeffsinc1D(zstart,Δz,zcenter,kind[2],nz,npts=npts,beta=beta) + xcoe, xidx = coeffsinc1D(xstart, Δx, xcenter, kind[1], nx; npts=npts, beta=beta) + zcoe, zidx = coeffsinc1D(zstart, Δz, zcenter, kind[2], nz; npts=npts, beta=beta) - function reflectcoeffsinc(coe,idx,nmax) + function reflectcoeffsinc(coe, idx, nmax) # # "Reflect" coefficients past the edge, i.e., mirror and subtract them # from the internal ones # if idx[1] < 1 # We are before the edge - nab = count( idx.<1 ) + nab = count(idx .< 1) # get the "reflected" coefficients reflcoe = coe[nab:-1:1] # Create a new set of indices excluding those above the surface @@ -158,10 +151,10 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real coe[nab+1:2*nab] .-= reflcoe # Create a new set of coefficients excluding those above the surface coe = coe[nab+1:end] - + elseif idx[end] > nmax # We are past the edge - nab = count( idx.>nmax ) + nab = count(idx .> nmax) # get the "reflected" coefficients reflcoe = coe[end:-1:end-nab+1] # Create a new set of indices excluding those above the surface @@ -172,23 +165,23 @@ function coeffsinc2D(xstart::Real,zstart::Real,Δx::Real,Δz::Real,xcenter::Real # Create a new set of coefficients excluding those above the surface coe = coe[1:end-nab] end - - return coe,idx + + return coe, idx end ## Crop and reflect coefficients if they go beyond model edges [Hicks 2002, Geophysics] - xcoe,xidx = reflectcoeffsinc(xcoe,xidx,nx) - zcoe,zidx = reflectcoeffsinc(zcoe,zidx,nz) + xcoe, xidx = reflectcoeffsinc(xcoe, xidx, nx) + zcoe, zidx = reflectcoeffsinc(zcoe, zidx, nz) # tensor product of coeff. in x and z - xzcoeff = zeros(typeof(xcenter),length(xcoe),length(zcoe)) + xzcoeff = zeros(typeof(xcenter), length(xcoe), length(zcoe)) for j in eachindex(zcoe) for i in eachindex(xcoe) - xzcoeff[i,j] = xcoe[i] * zcoe[j] + xzcoeff[i, j] = xcoe[i] * zcoe[j] end end - return xidx,zidx,xzcoeff + return xidx, zidx, xzcoeff end ## test diff --git a/src/utils.jl b/src/utils.jl index 097d48a..a1ac5d2 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -19,40 +19,37 @@ Gaussian source time function for current time `t`, activation time `t0` and dom """ gaussstf(t::Real, t0::Real, f0::Real)::Real = -exp(-(pi * f0 * (t - t0))^2) / (2 * (pi * f0)^2) - struct ArithmeticAverageInterpolation <: InterpolationMethod width::Int end - @views function interp(method::ArithmeticAverageInterpolation, a::Array{<:Real, N}, dim) where {N} return sum( a[CartesianIndices(Tuple(i == dim ? (j:size(a, i)+j-method.width) : (1:size(a, i)) for i in 1:N))] for j in 1:method.width ) ./ method.width end - """ $(TYPEDSIGNATURES) Compute an optimal distribution of tasks (nsrc) for a given number of workers (threads). Returns a vector of UnitRange object. """ -function distribsrcs(nsrc::Integer,nw::Integer) +function distribsrcs(nsrc::Integer, nw::Integer) ## calculate how to subdivide the srcs among the workers - if nsrc>=nw - dis = div(nsrc,nw) - grpsizes = dis*ones(Int64,nw) - resto = mod(nsrc,nw) - if resto>0 + if nsrc >= nw + dis = div(nsrc, nw) + grpsizes = dis * ones(Int64, nw) + resto = mod(nsrc, nw) + if resto > 0 ## add the reminder grpsizes[1:resto] .+= 1 end else ## if more workers than sources use only necessary workers - grpsizes = ones(Int64,nsrc) + grpsizes = ones(Int64, nsrc) end ## now set the indices for groups of srcs - grpsrc = UnitRange.(cumsum(grpsizes).-grpsizes.+1,cumsum(grpsizes)) + grpsrc = UnitRange.(cumsum(grpsizes) .- grpsizes .+ 1, cumsum(grpsizes)) return grpsrc end diff --git a/src/wrappers.jl b/src/wrappers.jl index c5bb21a..10bc173 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -33,11 +33,10 @@ function swforward!( parall::Symbol=:threads, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, - logger::Union{Nothing,AbstractLogger}=nothing + logger::Union{Nothing, AbstractLogger}=nothing )::Union{Vector{AbstractArray}, Nothing} where {N} - - if logger==nothing - logger=current_logger() + if logger == nothing + logger = current_logger() end out = nothing with_logger(logger) do @@ -49,7 +48,6 @@ function swforward!( return out end - @doc """ $(TYPEDSIGNATURES) @@ -71,10 +69,10 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function swforward!(wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - logger::Union{Nothing,AbstractLogger}=nothing, kwargs...) where {N} - if logger==nothing - logger=current_logger() +function swforward!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} + if logger == nothing + logger = current_logger() end out = nothing with_logger(logger) do @@ -113,11 +111,10 @@ function swmisfit!( shots::Vector{<:Shot}; #<:Pair{<:Sources{<:Real}, <:Receivers{<:Real}}}; parall::Symbol=:threads, misfit::AbstractMisfit=L2Misfit(nothing), - logger::Union{Nothing,AbstractLogger}=nothing + logger::Union{Nothing, AbstractLogger}=nothing )::Real where {N} - - if logger==nothing - logger=current_logger() + if logger == nothing + logger = current_logger() end out = nothing with_logger(logger) do @@ -129,7 +126,6 @@ function swmisfit!( return out end - @doc """ $(TYPEDSIGNATURES) @@ -150,10 +146,10 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ -function swmisfit!(wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - logger::Union{Nothing,AbstractLogger}=nothing, kwargs...) where {N} - if logger==nothing - logger=current_logger() +function swmisfit!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} + if logger == nothing + logger = current_logger() end out = nothing with_logger(logger) do @@ -198,18 +194,17 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi function swgradient!( params::InputParameters{N}, matprop::MaterialProperties{N}, - shots::Vector{<:Shot}; + shots::Vector{<:Shot}; parall::Symbol=:threads, check_freq::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing), smooth_radius::Integer=5, - logger::Union{Nothing,AbstractLogger}=nothing + logger::Union{Nothing, AbstractLogger}=nothing )::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} - - if logger==nothing - logger=current_logger() + if logger == nothing + logger = current_logger() end out = nothing with_logger(logger) do @@ -221,7 +216,6 @@ function swgradient!( return out end - @doc """ $(TYPEDSIGNATURES) @@ -251,10 +245,10 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `smooth_radius::Integer = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ -function swgradient!(wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - logger::Union{Nothing,AbstractLogger}=nothing, kwargs...) where {N} - if logger==nothing - logger=current_logger() +function swgradient!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} + if logger == nothing + logger = current_logger() end out = nothing with_logger(logger) do @@ -262,7 +256,7 @@ function swgradient!(wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}, matpro end return out end - + ####################################################### @doc """ @@ -286,18 +280,16 @@ Builds a wave similation based on the input paramters `params` and keyword argum - `infoevery::Union{<:Integer, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ function build_wavesim(params::InputParameters, matprop::MaterialProperties; parall::Symbol, kwargs...) - if parall==:threadpersrc + if parall == :threadpersrc nthr = Threads.nthreads() #println(" build_wavesim :threadpersrc") - wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for s=1:nthr] + wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for s in 1:nthr] else wsim = build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) end return wsim end - - build_concrete_wavesim( params::InputParametersAcoustic{N}, ::VpAcousticCDMaterialProperties, diff --git a/test/test_analytical_vs_numerical_acoustic_variable_density.jl b/test/test_analytical_vs_numerical_acoustic_variable_density.jl index e4128d3..c806129 100644 --- a/test/test_analytical_vs_numerical_acoustic_variable_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_variable_density.jl @@ -24,7 +24,7 @@ with_logger(error_logger) do nt = 500 nx = 501 dx = 2.5 - dt = dx / c0 * 6/7 + dt = dx / c0 * 6 / 7 halo = 0 rcoef = 1.0 f0 = 5.0 @@ -48,7 +48,7 @@ with_logger(error_logger) do nt = 5000 nx = 501 dx = 2.5 - dt = dx / c0 * 6/7 + dt = dx / c0 * 6 / 7 halo = 20 rcoef = 0.0001 f0 = 5.0 @@ -74,7 +74,7 @@ with_logger(error_logger) do nt = 350 nx = ny = 401 dx = dy = 5.0 - dt = dx / c0 / sqrt(2) * 6/7 + dt = dx / c0 / sqrt(2) * 6 / 7 halo = 0 rcoef = 1.0 f0 = 5.0 @@ -95,10 +95,10 @@ with_logger(error_logger) do # constant velocity setup c0 = 1000.0 ρ0 = 1500.0 - nt = 350*4 + nt = 350 * 4 nx = ny = 401 dx = dy = 5.0 - dt = dx / c0 / sqrt(2) * 6/7 + dt = dx / c0 / sqrt(2) * 6 / 7 halo = 20 rcoef = 0.0001 f0 = 5.0 diff --git a/test/test_gradient_acoustic_variable_density.jl b/test/test_gradient_acoustic_variable_density.jl index 189a1d4..4ab8283 100644 --- a/test/test_gradient_acoustic_variable_density.jl +++ b/test/test_gradient_acoustic_variable_density.jl @@ -24,7 +24,7 @@ with_logger(error_logger) do nt = 1000 nx = 101 dx = 10.0 - dt = dx / c0 * 6/7 + dt = dx / c0 * 6 / 7 halo = 20 rcoef = 0.0001 params, shots, matprop = setup_constant_vel_rho_1D_CPML(nt, dt, nx, dx, c0, ρ0, t0, f0, halo, rcoef) @@ -60,7 +60,7 @@ with_logger(error_logger) do nt = 1000 nx = ny = 101 dx = dy = 10.0 - dt = dx / c0 / sqrt(2) * 6/7 + dt = dx / c0 / sqrt(2) * 6 / 7 halo = 20 rcoef = 0.0001 params, shots, matprop = setup_constant_vel_rho_2D_CPML(nt, dt, nx, ny, dx, dy, c0, ρ0, t0, f0, halo, rcoef) @@ -96,7 +96,7 @@ with_logger(error_logger) do nt = 1000 nx = 101 dx = 10.0 - dt = dx / c0 * 6/7 + dt = dx / c0 * 6 / 7 halo = 20 rcoef = 0.0001 params, shots, matprop = setup_constant_vel_rho_1D_CPML(nt, dt, nx, dx, c0, ρ0, t0, f0, halo, rcoef) @@ -134,7 +134,7 @@ with_logger(error_logger) do nt = 1000 nx = ny = 101 dx = dy = 10.0 - dt = dx / c0 / sqrt(2) * 6/7 + dt = dx / c0 / sqrt(2) * 6 / 7 halo = 20 rcoef = 0.0001 params, shots, matprop = setup_constant_vel_rho_2D_CPML(nt, dt, nx, ny, dx, dy, c0, ρ0, t0, f0, halo, rcoef) diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index 01a6ce6..d24a404 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -161,7 +161,7 @@ end function analytical_solution_constant_vel_constant_density_1D(c0, rho, dt, nt, t0, f0, srcs, recs) # analytical solution - times = collect(range(dt/2; step=dt, length=nt)) + times = collect(range(dt / 2; step=dt, length=nt)) dist = norm(srcs.positions[1, :] .- recs.positions[1, :]) src = (c0^2 * rho) .* rickerstf.(times, t0, f0) # Calculate Green's function @@ -201,7 +201,7 @@ end function analytical_solution_constant_vel_constant_density_2D(c0, rho, dt, nt, t0, f0, srcs, recs) # analytical solution - times = collect(range(dt/2; step=dt, length=nt)) + times = collect(range(dt / 2; step=dt, length=nt)) dist = norm(srcs.positions[1, :] .- recs.positions[1, :]) src = (c0^2 * rho) .* rickerstf.(times, t0, f0) # Calculate Green's function From f4b36199a8512850d186a1d627e91e3c1932d90f Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 12 Mar 2024 13:13:12 +0100 Subject: [PATCH 029/111] Fix linter problems --- .../acoustic/backends/Acoustic1D_CD_CPML_Serial.jl | 3 ++- src/models/elastic/ela_forward.jl | 4 ++-- src/srcrec_interpolation.jl | 2 +- src/wrappers.jl | 12 ++++++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index 7032d6e..bd6feef 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -33,7 +33,8 @@ end pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * (d2p_dx2) end -@views update_ψ!(ψ_l, ψ_r, pcur, halo, nx, _dx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) = for i in 1:(halo+1) +@views update_ψ!(ψ_l, ψ_r, pcur, halo, nx, _dx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) = + for i in 1:(halo+1) ii = i + nx - halo - 2 # shift for right boundary pressure indices # left boundary ψ_l[i] = b_x_hl[i] * ψ_l[i] + a_x_hl[i] * (pcur[i+1] - pcur[i]) * _dx diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index e905007..0bce1b7 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -143,8 +143,8 @@ function spreadsrcrecinterp2D(gridspacing::NTuple{N, Real}, gridsize::NTuple{N, # compute grid indices and values of sinc coefficients xidx, zidx, xzcoeff = coeffsinc2D(xstart, zstart, Δx, Δz, xpos, zpos, nx, nz, [:monopole, :monopole]; npts=nptssinc) - for j in 1:length(zidx) - for i in 1:length(xidx) + for j in eachindex(zidx) + for i in eachindex(xidx) l += 1 # id, i, j indices coeij_tmp[l, :] .= (p, xidx[i], zidx[j]) diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl index 66b525e..eb918ef 100644 --- a/src/srcrec_interpolation.jl +++ b/src/srcrec_interpolation.jl @@ -59,7 +59,7 @@ function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::I @assert xcenter >= xstart @assert xcenter <= (nx - 1) * Δx + xstart - if beta == nothing + if beta === nothing if kind == :monopole beta = 4.14 elseif kind == :dipole diff --git a/src/wrappers.jl b/src/wrappers.jl index 10bc173..6d3f261 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -35,7 +35,7 @@ function swforward!( infoevery::Union{Int, Nothing}=nothing, logger::Union{Nothing, AbstractLogger}=nothing )::Union{Vector{AbstractArray}, Nothing} where {N} - if logger == nothing + if logger === nothing logger = current_logger() end out = nothing @@ -71,7 +71,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). """ function swforward!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} - if logger == nothing + if logger === nothing logger = current_logger() end out = nothing @@ -113,7 +113,7 @@ function swmisfit!( misfit::AbstractMisfit=L2Misfit(nothing), logger::Union{Nothing, AbstractLogger}=nothing )::Real where {N} - if logger == nothing + if logger === nothing logger = current_logger() end out = nothing @@ -148,7 +148,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ function swmisfit!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} - if logger == nothing + if logger === nothing logger = current_logger() end out = nothing @@ -203,7 +203,7 @@ function swgradient!( smooth_radius::Integer=5, logger::Union{Nothing, AbstractLogger}=nothing )::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} - if logger == nothing + if logger === nothing logger = current_logger() end out = nothing @@ -247,7 +247,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi """ function swgradient!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} - if logger == nothing + if logger === nothing logger = current_logger() end out = nothing From 769fab9f9077276c5898b4d8ab288ec101e7659f Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 12 Mar 2024 13:45:14 +0100 Subject: [PATCH 030/111] Remove old comments --- src/SeismicWaves.jl | 11 ---------- src/receivers.jl | 1 - src/shot.jl | 20 ++++-------------- src/solve.jl | 42 +++++++++++++------------------------ src/srcrec_interpolation.jl | 28 +------------------------ src/wrappers.jl | 30 +++++++++----------------- 6 files changed, 29 insertions(+), 103 deletions(-) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 8bee61d..f2d6a42 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -82,26 +82,15 @@ include("models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl") include("models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl") # Acoustic parallel backends -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl") - -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl") -ParallelStencil.@reset_parallel_stencil() include("models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") # Elastic parallel backends diff --git a/src/receivers.jl b/src/receivers.jl index 412f9f0..bcee355 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -111,7 +111,6 @@ struct VectorReceivers{N, T <: Real} <: Receivers invcov = zeros(0, 0) end return new{ndim, T}(positions, seismograms, observed, invcov) - #return new(positions, seismograms, observed, invcov) end end diff --git a/src/shot.jl b/src/shot.jl index 21dca28..903816b 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -6,34 +6,22 @@ Type representing a source-receiver pair, i.e., a \"shot\". $(TYPEDFIELDS) """ -Base.@kwdef struct Shot #{T <: Real} +Base.@kwdef struct Shot "Structure containing the appropriate Sources for a given simulation." - srcs::Sources #{T} + srcs::Sources "Structure containing the appropriate Receivers for a given simulation." - recs::Receivers #{T} + recs::Receivers end ################################################## -function init_shot!(model::WaveSimul, shot::Shot; kwargs...)#::Tuple{Matrix{<:Int}, Matrix{<:Int}, Array{<:Real}} +function init_shot!(model::WaveSimul, shot::Shot; kwargs...) # Check shot configuration check_shot(model, shot; kwargs...) # Initialize boundary conditions based on current shot init_bdc!(model, shot.srcs) - # Return allocated shot's arrays - return #setup_shot(model, shot) end -# @views function setup_shot(model::WaveSimul, shot::Shot)::Tuple{Matrix{<:Int}, Matrix{<:Int}, Array{<:Real}} -# # find nearest grid points indexes for both sources and receivers -# possrcs = find_nearest_grid_points(model, shot.srcs.positions) -# posrecs = find_nearest_grid_points(model, shot.recs.positions) -# # source time function (prescale if needed) -# scaled_tf = scale_srctf(model, shot.srcs.tf, possrcs) - -# return possrcs, posrecs, scaled_tf -# end - @views function find_nearest_grid_points(model::WaveSimul, positions::Matrix{<:Real})::Matrix{<:Int} # source time functions nsrcs = size(positions, 1) # number of sources diff --git a/src/solve.jl b/src/solve.jl index 458ad5a..ba6e8de 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -36,11 +36,10 @@ end for singleshot in shots # Initialize shot @info "Initializing shot" - #possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) init_shot!(wavsim, singleshot) # Compute forward solver @info "Forward modelling for one shot" - swforward_1shot!(wavsim, singleshot) #possrcs, posrecs, srctf, recs) + swforward_1shot!(wavsim, singleshot) # Save shot's snapshots if takesnapshots @info "Saving snapshots" @@ -65,7 +64,7 @@ end # make sure the number of threads has not changed! @assert nthr == nwsim - takesnapshots = false + snapshots_per_shot = Dict{Int, Vector}() for w in 1:nwsim # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -77,9 +76,8 @@ end # Now onwards matprop from outside should not be used anymore!!! # Snapshots setup - takesnapshots = snapenabled(wavsim[w]) - if takesnapshots - snapshots_per_shot = [[] for j in 1:nwsim] + if snapenabled(wavsim[w]) + snapshots_per_shot[w] = [] end end @@ -100,7 +98,7 @@ end #swforward_1shot!(wavsim[w], possrcs, posrecs, srctf, recs) swforward_1shot!(wavsim[w], singleshot) # Save shot's snapshots - if takesnapshots + if snapenabled(wavsim[w]) @info "Saving snapshots" push!(snapshots_per_shot[w], copy(wavsim[w].snapshots)) end @@ -108,7 +106,7 @@ end end if takesnapshots - return collect(snapshots_per_shot) + return collect(values(snapshots_per_shot)) end return nothing end @@ -130,7 +128,9 @@ end for singleshot in shots @info "Checking invcov matrix" if typeof(wavsim) <: Vector{<:WaveSimul} - check_invcov_matrix(wavsim[1], singleshot.recs.invcov) + for i in eachindex(wavsim) + check_invcov_matrix(wavsim[i], singleshot.recs.invcov) + end else check_invcov_matrix(wavsim, singleshot.recs.invcov) end @@ -168,20 +168,12 @@ end @info "Shot #$s" # Initialize shot @info "Initializing shot" - #possrcs, posrecs, srctf = init_shot!(wavsim, singleshot) init_shot!(wavsim, singleshot) @info "Checking invcov matrix" check_invcov_matrix(wavsim, singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" - # curgrad = swgradient_1shot!( - # wavsim, possrcs, - # posrecs, srctf, - # recs, misfit - # ) - curgrad = swgradient_1shot!( - wavsim, singleshot, misfit - ) + curgrad = swgradient_1shot!(wavsim, singleshot, misfit) # Accumulate gradient totgrad .+= curgrad # Compute misfit if needed @@ -219,7 +211,7 @@ end # Initialize total gradient and total misfit nshots = length(shots) - allgrad = [zeros(wavsim[1].totgrad_size...) for i in 1:nshots] + allgrad = [zeros(wavsim[i].totgrad_size...) for i in nshots] if compute_misfit allmisfitval = zeros(nshots) @@ -227,7 +219,6 @@ end end # Shots loop - nshots = length(shots) grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange # loop on the set of WaveSimul Threads.@threads for w in 1:nwsim @@ -237,22 +228,16 @@ end @info "Shot #$s" # Initialize shot @info "Initializing shot" - #possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) init_shot!(wavsim[w], singleshot) @info "Checking invcov matrix" check_invcov_matrix(wavsim[w], singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" - # curgrad = swgradient_1shot!( - # wavsim[w], possrcs, - # posrecs, srctf, - # recs, misfit - # ) curgrad = swgradient_1shot!( wavsim[w], singleshot, misfit ) - # Accumulate gradient - allgrad[s] = curgrad + # Save gradient + allgrad[s] .= curgrad # Compute misfit if needed if compute_misfit @info "Computing misfit" @@ -261,6 +246,7 @@ end end end + # Accumulate gradient and misfit totgrad = sum(allgrad) if compute_misfit totmisfitval = sum(allmisfitval) diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl index eb918ef..fce6976 100644 --- a/src/srcrec_interpolation.jl +++ b/src/srcrec_interpolation.jl @@ -68,7 +68,7 @@ function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::I end radius = npts * Δx - ## Assuming x from grid starts at xstart + # Assuming x from grid starts at xstart xh = (xcenter - xstart) / Δx ix = floor(Int64, xh + 1) if mod((xcenter - xstart), Δx) == 0.0 @@ -99,17 +99,6 @@ function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::I # return also indices of window (as a range) return itpfun, indexes end -# ## test: -# begin -# xstart = 12.0 -# x0 = 15.75 -# Δx = 0.5 -# x = [(i-1)*Δx+xstart for i=1:15] -# coe,idxs = coeffsinc1d(xstart,Δx,x0,:monopole) -# scatterlines(idxs,coe) -# @show idxs -# Any[1:length(x) x] -# end ##################################################################### @@ -184,21 +173,6 @@ function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter:: return xidx, zidx, xzcoeff end -## test -# begin -# include("../src/srcrec_interpolation.jl") -# xstart = 12.0 -# x0 = 15.75 -# Δx = 0.5 -# zstart = 3.0 -# z0 = 6.12 -# Δz = 0.35 -# xidx,zidx,xzcoeff = coeffsinc2D(xstart,zstart,Δx,Δz,x0,z0,nx,nz,[:monopole,:monopole]) -# @show xidx -# @show zidx -# @show xzcoeff -# fig,ax,hm=heatmap(xzcoeff); Colorbar(fig[1,2],hm); fig -# end ##################################################################### ##################################################################### diff --git a/src/wrappers.jl b/src/wrappers.jl index 6d3f261..0d1c250 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -38,14 +38,12 @@ function swforward!( if logger === nothing logger = current_logger() end - out = nothing - with_logger(logger) do + return with_logger(logger) do # Build wavesim wavesim = build_wavesim(params, matprop; parall=parall, snapevery=snapevery, infoevery=infoevery, gradient=false) # Solve simulation - out = run_swforward!(wavesim, matprop, shots) + run_swforward!(wavesim, matprop, shots) end - return out end @doc """ @@ -116,14 +114,12 @@ function swmisfit!( if logger === nothing logger = current_logger() end - out = nothing - with_logger(logger) do + return with_logger(logger) do # Build wavesim wavesim = build_wavesim(params, matprop; parall=parall, gradient=false) # Compute misfit - out = run_swmisfit!(wavesim, matprop, shots; misfit=misfit) + run_swmisfit!(wavesim, matprop, shots; misfit=misfit) end - return out end @doc """ @@ -151,11 +147,9 @@ function swmisfit!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop if logger === nothing logger = current_logger() end - out = nothing - with_logger(logger) do - out = run_swmisfit!(wavesim, matprop, shots; kwargs...) + return with_logger(logger) do + run_swmisfit!(wavesim, matprop, shots; kwargs...) end - return out end ####################################################### @@ -206,14 +200,12 @@ function swgradient!( if logger === nothing logger = current_logger() end - out = nothing - with_logger(logger) do + return with_logger(logger) do # Build wavesim wavesim = build_wavesim(params, matprop; parall=parall, infoevery=infoevery, gradient=true, check_freq=check_freq, smooth_radius=smooth_radius) # Solve simulation - out = run_swgradient!(wavesim, matprop, shots; compute_misfit=compute_misfit, misfit=misfit) + run_swgradient!(wavesim, matprop, shots; compute_misfit=compute_misfit, misfit=misfit) end - return out end @doc """ @@ -250,11 +242,9 @@ function swgradient!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matpr if logger === nothing logger = current_logger() end - out = nothing - with_logger(logger) do - out = run_swgradient!(wavesim, matprop, shots; kwargs...) + return with_logger(logger) do + run_swgradient!(wavesim, matprop, shots; kwargs...) end - return out end ####################################################### From d1526217b91196f152fd2851a14d74bffbf823d2 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 12 Mar 2024 13:45:24 +0100 Subject: [PATCH 031/111] Remove MPI dep for now --- Project.toml | 1 - src/traits/grid.jl | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index 3e8fea2..baa2029 100644 --- a/Project.toml +++ b/Project.toml @@ -8,7 +8,6 @@ CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" -MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" ParallelStencil = "94395366-693c-11ea-3b26-d9b7aac5d958" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" diff --git a/src/traits/grid.jl b/src/traits/grid.jl index 892d126..dc215b1 100644 --- a/src/traits/grid.jl +++ b/src/traits/grid.jl @@ -1,4 +1,4 @@ -using MPI: MPI +# using MPI: MPI """ Abstract trait for a general finite difference grid. @@ -23,8 +23,8 @@ GridTrait(::Type) = error("GridTrait not implemented for type $(x)") get_maximum_func(model::WaveSimul) = get_maximum_func(GridTrait(model)) get_maximum_func(::LocalGrid) = Base.maximum -get_maximum_func(::GlobalGrid) = (x -> (max_l = maximum(x); MPI.Allreduce(max_l, MPI.MAX, MPI.COMM_WORLD))) +# get_maximum_func(::GlobalGrid) = (x -> (max_l = maximum(x); MPI.Allreduce(max_l, MPI.MAX, MPI.COMM_WORLD))) get_minimum_func(model::WaveSimul) = get_minimum_func(GridTrait(model)) get_minimum_func(::LocalGrid) = Base.minimum -get_minimum_func(::GlobalGrid) = (x -> (min_l = minimum(x); MPI.Allreduce(min_l, MPI.MIN, MPI.COMM_WORLD))) +# get_minimum_func(::GlobalGrid) = (x -> (min_l = minimum(x); MPI.Allreduce(min_l, MPI.MIN, MPI.COMM_WORLD))) From 3c5440b86363daa24edc2a98fa77acb063310e1c Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 12 Mar 2024 13:49:01 +0100 Subject: [PATCH 032/111] Remove more old comments --- src/models/acoustic/acou_forward.jl | 8 -------- src/models/acoustic/acou_gradient.jl | 8 -------- src/models/acoustic/acou_models.jl | 20 -------------------- src/models/cpmlcoeffs.jl | 19 ------------------- 4 files changed, 55 deletions(-) diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index af00fdd..2e62b9d 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -24,10 +24,6 @@ end ::CPMLBoundaryCondition, wavsim::AcousticCDCPMLWaveSimul{N}, shot::Shot - # possrcs, - # posrecs, - # srctf, - # recs ) where {N} # scale source time function, etc. @@ -101,10 +97,6 @@ end ::CPMLBoundaryCondition, wavsim::AcousticVDStaggeredCPMLWaveSimul{N}, shot::Shot - # possrcs, - # posrecs, - # srctf, - # recs ) where {N} # scale source time function, etc. diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 040f040..6d2fa43 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -5,10 +5,6 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = ::CPMLBoundaryCondition, model::AcousticCDWaveSimul{N}, shot::Shot, - # possrcs, - # posrecs, - # srctf, - # recs, misfit )::Array{<:Real} where {N} @@ -154,10 +150,6 @@ end ::CPMLBoundaryCondition, model::AcousticVDStaggeredCPMLWaveSimul{N}, shot::Shot, - # possrcs, - # posrecs, - # srctf, - # recs, misfit )::Array{<:Real} where {N} diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 6d8e692..2613809 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -29,16 +29,6 @@ end # Functions for all AcousticCDWaveSimul subtypes -# @views function scale_srctf(model::AcousticCDWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} -# # scale with boxcar and timestep size -# scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt^2) -# # scale with velocity squared at each source position -# for s in axes(scaled_tf, 2) -# scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] .^ 2 -# end -# return scaled_tf -# end - @views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{N}) where {N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" @@ -331,16 +321,6 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() end end -# @views function scale_srctf(model::AcousticVDStaggeredWaveSimul, srctf::Matrix{<:Real}, positions::Matrix{<:Int})::Matrix{<:Real} -# # scale with boxcar and timestep size -# scaled_tf = srctf ./ prod(model.gridspacing) .* (model.dt) -# # scale with velocity squared times density at each source position (its like dividing by m0) -# for s in axes(scaled_tf, 2) -# scaled_tf[:, s] .*= model.matprop.vp[positions[s, :]...] ^ 2 * model.matprop.rho[positions[s, :]...] -# end -# return scaled_tf -# end - @views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 6c6f492..7080b4f 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -41,13 +41,6 @@ function compute_CPML_coefficientsAxis!( a_l, a_r, b_l, b_r = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :startongrd) a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :starthalfgrd) - # @show size(cpmlcoeffs.a),size(a_l),size(a_r) - # @show size(cpmlcoeffs.a_h),size(a_hl),size(a_hr) - # @show a_l - # @show a_hl - # @show a_r - # @show a_hr - copyto!(cpmlcoeffs.a, vcat(a_l, a_r)) copyto!(cpmlcoeffs.a_h, vcat(a_hl, a_hr)) copyto!(cpmlcoeffs.b, vcat(b_l, b_r)) @@ -94,9 +87,6 @@ struct CPMLCoefficients end end -# Default type constructor -# CPMLCoefficients(halo) = CPMLCoefficients{Float64}(halo) - function calc_Kab_CPML_staggeredgrid( halo::Integer, dt::Float64, @@ -152,15 +142,6 @@ function calc_Kab_CPML_staggeredgrid( b_right = exp.(.-(d_right ./ K_right .+ alpha_right) .* dt) a_right = d_right .* (b_right .- 1.0) ./ (K_right .* (d_right .+ K_right .* alpha_right)) - # println() - # @show onwhere - # @show dist_left - # @show dist_right - # @show normdist_left - # @show normdist_right - # @show a_left - # @show a_right - if K_max_pml === nothing return a_left, a_right, b_left, b_right else From dc0fab0ba26ec066a9e87533a81f0328330367d8 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 29 Apr 2024 14:17:56 +0200 Subject: [PATCH 033/111] Fix snapshots with GPU backend --- src/models/acoustic/acou_models.jl | 8 ++++---- src/solve.jl | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 2613809..57b407d 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -67,7 +67,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} check_freq::Union{<:Integer, Nothing} # Snapshots snapevery::Union{<:Integer, Nothing} - snapshots::Union{<:Array{<:Real}, Nothing} + snapshots::Union{Any, Nothing} # Logging parameters infoevery::Integer # Gradient smoothing parameters @@ -219,7 +219,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} end # Initialize snapshots array - snapshots = (snapevery !== nothing ? zeros(ns..., div(nt, snapevery)) : nothing) + snapshots = (snapevery !== nothing ? backend.zeros(ns..., div(nt, snapevery)) : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -370,7 +370,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} check_freq::Union{<:Integer, Nothing} # Snapshots snapevery::Union{<:Integer, Nothing} - snapshots::Union{<:Array{<:Real}, Nothing} + snapshots::Union{Any, Nothing} # Logging parameters infoevery::Integer # Gradient smoothing parameters @@ -535,7 +535,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} end # Initialize snapshots array - snapshots = (snapevery !== nothing ? zeros(ns..., div(nt, snapevery)) : nothing) + snapshots = (snapevery !== nothing ? backend.zeros(ns..., div(nt, snapevery)) : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it diff --git a/src/solve.jl b/src/solve.jl index ba6e8de..87218b7 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -43,7 +43,7 @@ end # Save shot's snapshots if takesnapshots @info "Saving snapshots" - push!(snapshots_per_shot, copy(wavsim.snapshots)) + push!(snapshots_per_shot, Array(wavsim.snapshots)) end end From c864aacf986b261a0438b76d3a2b04c2f2ec1f67 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 29 Apr 2024 14:46:07 +0200 Subject: [PATCH 034/111] CUDA extension (first commit) --- Project.toml | 12 ++++++-- ext/CUDABackendExt.jl | 20 +++++++++++++ src/SeismicWaves.jl | 5 ---- src/models/backend_selection.jl | 52 +++++++++------------------------ 4 files changed, 43 insertions(+), 46 deletions(-) create mode 100644 ext/CUDABackendExt.jl diff --git a/Project.toml b/Project.toml index baa2029..4f1c136 100644 --- a/Project.toml +++ b/Project.toml @@ -4,7 +4,6 @@ authors = ["Andrea Zunino", "Giacomo Aloisi"] version = "0.7.0" [deps] -CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" @@ -12,11 +11,18 @@ ParallelStencil = "94395366-693c-11ea-3b26-d9b7aac5d958" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" +[weakdeps] +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + +[extensions] +CUDABackendExt = "CUDA" + [compat] -julia = "1.8 - 1.9" +julia = ">=1.9" [extras] +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["Test", "CUDA"] diff --git a/ext/CUDABackendExt.jl b/ext/CUDABackendExt.jl new file mode 100644 index 0000000..934363e --- /dev/null +++ b/ext/CUDABackendExt.jl @@ -0,0 +1,20 @@ +module CUDABackendExt + +using SeismicWaves, CUDA +using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimul, AcousticVDStaggeredCPMLWaveSimul + +# Include CUDA backends +include("../src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl") +include("../src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl") +include("../src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl") +include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") +include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") + +# Overload backend selection +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU + +end \ No newline at end of file diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index f2d6a42..54af139 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -83,15 +83,10 @@ include("models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl") # Acoustic parallel backends include("models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl") -include("models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl") include("models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl") -include("models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl") include("models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl") -include("models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl") include("models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl") -include("models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") include("models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl") -include("models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") # Elastic parallel backends diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index 17e2bb6..00c1721 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -19,45 +19,21 @@ end ## VD = variable density # Backend selections for AcousticCDCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:serial}}) = - Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:serial}}) = - Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:serial}}) = - Acoustic3D_CD_CPML_Serial - -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = - Acoustic1D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = - Acoustic2D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threads}}) = - Acoustic3D_CD_CPML_Threads - -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = - Acoustic1D_CD_CPML_GPU -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = - Acoustic2D_CD_CPML_GPU -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:GPU}}) = - Acoustic3D_CD_CPML_GPU - -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threadpersrc}}) = - Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threadpersrc}}) = - Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threadpersrc}}) = - Acoustic3D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:serial}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:serial}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:serial}}) = Acoustic3D_CD_CPML_Serial -# Backend selections for AcousticVDStaggeredCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = - Acoustic1D_VD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = - Acoustic1D_VD_CPML_GPU +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = Acoustic1D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = Acoustic2D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threads}}) = Acoustic3D_CD_CPML_Threads + +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threadpersrc}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threadpersrc}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = - Acoustic2D_VD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = - Acoustic2D_VD_CPML_GPU +# Backend selections for AcousticVDStaggeredCPMLWaveSimul +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads # Backend selections for ElasticIsoWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimul{2}}, ::Type{Val{:serial}}) = - Elastic2D_Iso_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimul{2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial From 2fb15084b7ad66105d8a2ce538bb02c93f56a5ca Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 2 May 2024 13:49:39 +0200 Subject: [PATCH 035/111] Start grid refactor (WIP) --- src/SeismicWaves.jl | 1 + src/checks.jl | 14 +- src/models/acoustic/acou_forward.jl | 23 +- src/models/acoustic/acou_gradient.jl | 103 ++++---- src/models/acoustic/acou_grid.jl | 132 ++++++++++ src/models/acoustic/acou_models.jl | 231 +++++------------- .../backends/Acoustic1D_CD_CPML_Serial.jl | 6 +- .../backends/Acoustic2D_CD_CPML_Serial.jl | 2 +- .../backends/Acoustic3D_CD_CPML_Serial.jl | 2 +- src/wrappers.jl | 4 +- 10 files changed, 276 insertions(+), 242 deletions(-) create mode 100644 src/models/acoustic/acou_grid.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 54af139..a567e2a 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -48,6 +48,7 @@ include("models/cpmlcoeffs.jl") # Acoustic include("models/acoustic/acou_abstract_types.jl") +include("models/acoustic/acou_grid.jl") include("models/acoustic/acou_material_properties.jl") include("models/acoustic/acou_models.jl") include("models/acoustic/acou_params.jl") diff --git a/src/checks.jl b/src/checks.jl index 503b0a5..2a7735b 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -1,7 +1,5 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, shots::Vector{<:Shot}) - tysim = typeof(wavsim) - tymatprop = typeof(matprop) tysource = typeof(shots[1].srcs) tyreceiver = typeof(shots[1].recs) @@ -14,20 +12,20 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s # Check that the subtypes of WaveSimul, MaterialProperties and Shot are consistent N = typeof(wavsim).parameters[1] - if tysim == AcousticCDCPMLWaveSimul{N} && - tymatprop == VpAcousticCDMaterialProperties{N} && + if wavsim isa AcousticCDCPMLWaveSimul{N} && + matprop isa VpAcousticCDMaterialProperties{N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif tysim == AcousticVDStaggeredCPMLWaveSimul{N} && - tymatprop == VpRhoAcousticVDMaterialProperties{N} && + elseif wavsim isa AcousticVDStaggeredCPMLWaveSimul{N} && + matprop isa VpRhoAcousticVDMaterialProperties{N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif tysim == ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< - tymatprop == ElasticIsoMaterialProperties{2} && + elseif wavsim isa ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< + matprop isa ElasticIsoMaterialProperties{2} && tysource <: MomentTensorSources && tyreceiver <: VectorReceivers return diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 2e62b9d..0379468 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -29,27 +29,30 @@ end # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) + forward_grid = wavsim.forward_grid + backend = select_backend(typeof(wavsim), wavsim.parall) + # Pressure arrays - pold = wavsim.pold - pcur = wavsim.pcur - pnew = wavsim.pnew + pold = forward_grid.pold + pcur = forward_grid.pcur + pnew = forward_grid.pnew # Numerics nt = wavsim.nt # Wrap sources and receivers arrays - possrcs_bk = wavsim.backend.Data.Array(possrcs) - posrecs_bk = wavsim.backend.Data.Array(posrecs) - srctf_bk = wavsim.backend.Data.Array(scal_srctf) - traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) + possrcs_bk = backend.Data.Array(possrcs) + posrecs_bk = backend.Data.Array(posrecs) + srctf_bk = backend.Data.Array(scal_srctf) + traces_bk = backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(wavsim) # Time loop for it in 1:nt # Compute one forward step - pold, pcur, pnew = wavsim.backend.forward_onestep_CPML!( - pold, pcur, pnew, wavsim.fact, + pold, pcur, pnew = backend.forward_onestep_CPML!( + pold, pcur, pnew, forward_grid.fact, wavsim.gridspacing..., wavsim.halo, - wavsim.ψ..., wavsim.ξ..., wavsim.a_coeffs..., wavsim.b_coeffs..., + forward_grid.ψ..., forward_grid.ξ..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 6d2fa43..fc37a78 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -11,31 +11,36 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) + forward_grid = model.forward_grid + adjoint_grid = model.adjoint_grid + checkpointing = model.checkpointing + backend = select_backend(typeof(model), model.parall) + # Numerics nt = model.nt # Initialize pressure and factors arrays - pold = model.pold - pcur = model.pcur - pnew = model.pnew + pold = forward_grid.pold + pcur = forward_grid.pcur + pnew = forward_grid.pnew # Initialize adjoint arrays - adjold = model.adjold - adjcur = model.adjcur - adjnew = model.adjnew + adjold = adjoint_grid.adjold + adjcur = adjoint_grid.adjcur + adjnew = adjoint_grid.adjnew # Wrap sources and receivers arrays - possrcs_bk = model.backend.Data.Array(possrcs) - posrecs_bk = model.backend.Data.Array(posrecs) - srctf_bk = model.backend.Data.Array(scal_srctf) - traces_bk = model.backend.Data.Array(shot.recs.seismograms) + possrcs_bk = backend.Data.Array(possrcs) + posrecs_bk = backend.Data.Array(posrecs) + srctf_bk = backend.Data.Array(scal_srctf) + traces_bk = backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(model) # Forward time loop for it in 1:nt # Compute one forward step - pold, pcur, pnew = model.backend.forward_onestep_CPML!( - pold, pcur, pnew, model.fact, + pold, pcur, pnew = backend.forward_onestep_CPML!( + pold, pcur, pnew, forward_grid.fact, model.gridspacing..., model.halo, - model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., + forward_grid.ψ..., forward_grid.ξ..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info @@ -43,22 +48,22 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @debug @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) end # Save checkpoint - if model.check_freq !== nothing && it % model.check_freq == 0 + if checkpointing.check_freq !== nothing && it % checkpointing.check_freq == 0 @debug @sprintf("Saving checkpoint at iteration: %d", it) # Save current and last timestep pressure - copyto!(model.checkpoints[it], pcur) - copyto!(model.checkpoints[it-1], pold) + copyto!(checkpointing.checkpoints[it], pcur) + copyto!(checkpointing.checkpoints[it-1], pold) # Also save CPML arrays - for i in eachindex(model.ψ) - copyto!(model.checkpoints_ψ[it][i], model.ψ[i]) + for i in eachindex(forward_grid.ψ) + copyto!(checkpointing.checkpoints_ψ[it][i], forward_grid.ψ[i]) end - for i in eachindex(model.ξ) - copyto!(model.checkpoints_ξ[it][i], model.ξ[i]) + for i in eachindex(forward_grid.ξ) + copyto!(checkpointing.checkpoints_ξ[it][i], forward_grid.ξ[i]) end end # Start populating save buffer just before last checkpoint - if it >= model.last_checkpoint - 1 - copyto!(model.save_buffer[fill(Colon(), N)..., it-(model.last_checkpoint-1)+1], pcur) + if it >= checkpointing.last_checkpoint - 1 + copyto!(checkpointing.save_buffer[it-(checkpointing.last_checkpoint-1)+1], pcur) end end @@ -66,21 +71,21 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = copyto!(shot.recs.seismograms, traces_bk) @debug "Computing residuals" - residuals_bk = model.backend.Data.Array(dχ_du(misfit, shot.recs)) + residuals_bk = backend.Data.Array(dχ_du(misfit, shot.recs)) # Prescale residuals (fact = vel^2 * dt^2) - model.backend.prescale_residuals!(residuals_bk, posrecs_bk, model.fact) + backend.prescale_residuals!(residuals_bk, posrecs_bk, forward_grid.fact) @debug "Computing gradients" # Current checkpoint - curr_checkpoint = model.last_checkpoint + curr_checkpoint = checkpointing.last_checkpoint # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step - adjold, adjcur, adjnew = model.backend.forward_onestep_CPML!( - adjold, adjcur, adjnew, model.fact, + adjold, adjcur, adjnew = backend.forward_onestep_CPML!( + adjold, adjcur, adjnew, forward_grid.fact, model.gridspacing..., model.halo, - model.ψ_adj..., model.ξ_adj..., model.a_coeffs..., model.b_coeffs..., + adjoint_grid.ψ_adj..., adjoint_grid.ξ_adj..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., posrecs_bk, residuals_bk, nothing, nothing, it; # adjoint sources positions are receivers save_trace=false ) @@ -93,29 +98,29 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @debug @sprintf("Out of save buffer at iteration: %d", it) # Shift last checkpoint old_checkpoint = curr_checkpoint - curr_checkpoint -= model.check_freq + curr_checkpoint -= checkpointing.check_freq # Shift start of save buffer - copyto!(model.save_buffer[fill(Colon(), N)..., 1], model.checkpoints[curr_checkpoint-1]) - copyto!(model.save_buffer[fill(Colon(), N)..., 2], model.checkpoints[curr_checkpoint]) + copyto!(checkpointing.save_buffer[1], checkpointing.checkpoints[curr_checkpoint-1]) + copyto!(checkpointing.save_buffer[2], checkpointing.checkpoints[curr_checkpoint]) # Shift end of save buffer - copyto!(model.save_buffer[fill(Colon(), N)..., end-1], model.checkpoints[old_checkpoint-1]) - copyto!(model.save_buffer[fill(Colon(), N)..., end], model.checkpoints[old_checkpoint]) + copyto!(checkpointing.save_buffer[end-1], checkpointing.checkpoints[old_checkpoint-1]) + copyto!(checkpointing.save_buffer[end], checkpointing.checkpoints[old_checkpoint]) # Recover pressure and CPML arrays from current checkpoint - copyto!(pold, model.checkpoints[curr_checkpoint-1]) - copyto!(pcur, model.checkpoints[curr_checkpoint]) + copyto!(pold, checkpointing.checkpoints[curr_checkpoint-1]) + copyto!(pcur, checkpointing.checkpoints[curr_checkpoint]) pnew .= 0.0 - for i in eachindex(model.checkpoints_ψ[curr_checkpoint]) - copyto!(model.ψ[i], model.checkpoints_ψ[curr_checkpoint][i]) + for i in eachindex(checkpointing.checkpoints_ψ[curr_checkpoint]) + copyto!(forward_grid.ψ[i], checkpointing.checkpoints_ψ[curr_checkpoint][i]) end - for i in eachindex(model.checkpoints_ξ[curr_checkpoint]) - copyto!(model.ξ[i], model.checkpoints_ξ[curr_checkpoint][i]) + for i in eachindex(checkpointing.checkpoints_ξ[curr_checkpoint]) + copyto!(forward_grid.ξ[i], checkpointing.checkpoints_ξ[curr_checkpoint][i]) end # Forward recovery time loop for recit in (curr_checkpoint+1):((old_checkpoint-1)-1) - pold, pcur, pnew = model.backend.forward_onestep_CPML!( - pold, pcur, pnew, model.fact, + pold, pcur, pnew = backend.forward_onestep_CPML!( + pold, pcur, pnew, forward_grid.fact, model.gridspacing..., model.halo, - model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., + forward_grid.ψ..., forward_grid.ξ..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false ) @@ -123,20 +128,20 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @debug @sprintf("Recovering iteration: %d", recit) end # Save recovered pressure in save buffer - copyto!(model.save_buffer[fill(Colon(), N)..., recit-(curr_checkpoint+1)+3], pcur) + copyto!(checkpointing.save_buffer[recit-(curr_checkpoint+1)+3], pcur) end end # Get pressure fields from saved buffer - pcur_corr = model.save_buffer[fill(Colon(), N)..., ((it-1)-curr_checkpoint)+1] - pold_corr = model.save_buffer[fill(Colon(), N)..., ((it-1)-curr_checkpoint)+2] - pveryold_corr = model.save_buffer[fill(Colon(), N)..., ((it-1)-curr_checkpoint)+3] + pcur_corr = checkpointing.save_buffer[((it-1)-curr_checkpoint)+1] + pold_corr = checkpointing.save_buffer[((it-1)-curr_checkpoint)+2] + pveryold_corr = checkpointing.save_buffer[((it-1)-curr_checkpoint)+3] # Correlate for gradient computation - model.backend.correlate_gradient!(model.curgrad, adjcur, pcur_corr, pold_corr, pveryold_corr, model.dt) + backend.correlate_gradient!(adjoint_grid.curgrad, adjcur, pcur_corr, pold_corr, pveryold_corr, model.dt) end # get gradient - gradient = Array(model.curgrad) + gradient = Array(adjoint_grid.curgrad) # smooth gradient - model.backend.smooth_gradient!(gradient, possrcs, model.smooth_radius) + backend.smooth_gradient!(gradient, possrcs, adjoint_grid.smooth_radius) # rescale gradient gradient .= (2.0 ./ (model.matprop.vp .^ 3)) .* gradient # add regularization if needed diff --git a/src/models/acoustic/acou_grid.jl b/src/models/acoustic/acou_grid.jl new file mode 100644 index 0000000..e1126f0 --- /dev/null +++ b/src/models/acoustic/acou_grid.jl @@ -0,0 +1,132 @@ +struct AcousticCDForwardGrid{N, T, A <: AbstractArray{T,N}, V <: AbstractVector{T}} + fact::A + pold::A + pcur::A + pnew::A + ψ::Vector{A} + ξ::Vector{A} + a_coeffs::Vector{V} + b_coeffs::Vector{V} + + function AcousticCDForwardGrid(ns::NTuple{N, Int}, halo::Int, cpmlcoeffs::NTuple{N, CPMLCoefficients}, backend::Module, T::Type) where {N} + A = backend.Data.Array{N} + V = backend.Data.Array{1} + # Initialize computational arrays + fact = backend.zeros(ns...) + pold = backend.zeros(ns...) + pcur = backend.zeros(ns...) + pnew = backend.zeros(ns...) + # Initialize CPML arrays + ψ = [] + ξ = [] + for i in 1:N + ψ_ns = [ns...] + ξ_ns = [ns...] + ψ_ns[i] = halo + 1 + ξ_ns[i] = halo + append!(ψ, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) + append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + end + # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) + a_coeffs = [] + b_coeffs = [] + for i in 1:N + append!(a_coeffs, [cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr]) + append!(b_coeffs, [cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr]) + end + + new{N,T,A,V}(fact, pold, pcur, pnew, ψ, ξ, a_coeffs, b_coeffs) + end +end + +struct AcousticCDAdjointGrid{N, T, A <: AbstractArray{T,N}} + curgrad::A + adjold::A + adjcur::A + adjnew::A + ψ_adj::Vector{A} + ξ_adj::Vector{A} + totgrad_size::Vector{Int} + smooth_radius::Int + + function AcousticCDAdjointGrid(ns::NTuple{N, Int}, halo::Int, backend::Module, smooth_radius::Int, T::Type) where {N} + A = backend.Data.Array{N} + + totgrad_size = [ns...] + # Current gradient array + curgrad = backend.zeros(ns...) + # Adjoint arrays + adjold = backend.zeros(ns...) + adjcur = backend.zeros(ns...) + adjnew = backend.zeros(ns...) + # Initialize CPML arrays + ψ_adj = [] + ξ_adj = [] + for i in 1:N + ψ_ns = [ns...] + ξ_ns = [ns...] + ψ_ns[i] = halo + 1 + ξ_ns[i] = halo + append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) + append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + end + + new{N,T,A}(curgrad, adjold, adjcur, adjnew, ψ_adj, ξ_adj, totgrad_size, smooth_radius) + end +end + +struct AcousticCDCheckpointing{N, T, A <: AbstractArray{T,N}} + check_freq::Union{Int, Nothing} + last_checkpoint::Int + save_buffer::Vector{A} + checkpoints::Dict{Int, A} + checkpoints_ψ::Dict{Int, Vector{A}} + checkpoints_ξ::Dict{Int, Vector{A}} + + function AcousticCDCheckpointing( + check_freq::Union{Int, Nothing}, + nt::Int, + ns::NTuple{N, Int}, + forward_grid::AcousticCDForwardGrid{N}, + backend::Module, + T::Type + ) where {N} + A = backend.Data.Array{N} + if check_freq !== nothing + @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" + @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" + # Time step of last checkpoint + last_checkpoint = floor(Int, nt / check_freq) * check_freq + # Checkpointing arrays + save_buffer = [backend.zeros(ns...) for _ in 1:(check_freq + 2)] # pressure window buffer + checkpoints = Dict{Int, A}() # pressure checkpoints + checkpoints_ψ = Dict{Int, Vector{A}}() # ψ arrays checkpoints + checkpoints_ξ = Dict{Int, Vector{A}}() # ξ arrays checkpoints + # Save initial conditions as first checkpoint + checkpoints[-1] = copy(forward_grid.pold) + checkpoints[0] = copy(forward_grid.pcur) + checkpoints_ψ[0] = copy.(forward_grid.ψ) + checkpoints_ξ[0] = copy.(forward_grid.ξ) + # Preallocate future checkpoints + for it in 1:(nt+1) + if it % check_freq == 0 + checkpoints[it] = backend.zeros(ns...) + checkpoints[it-1] = backend.zeros(ns...) + checkpoints_ψ[it] = copy.(forward_grid.ψ) + checkpoints_ξ[it] = copy.(forward_grid.ξ) + end + end + else # no checkpointing + last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) + save_buffer = [backend.zeros(ns...) for _ in 1:(nt + 2)] # save all timesteps (from -1 to nt+1 so nt+2) + checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) + checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) + checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) + end + # Save first 2 timesteps in save buffer + copyto!(save_buffer[1], forward_grid.pold) + copyto!(save_buffer[2], forward_grid.pcur) + + new{N,T,A}(check_freq, last_checkpoint, save_buffer, checkpoints, checkpoints_ψ, checkpoints_ξ) + end +end \ No newline at end of file diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 57b407d..bba2465 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -45,78 +45,58 @@ end precompute_fact!(model) end -@views precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.fact, (model.dt^2) .* (model.matprop.vp .^ 2)) +@views precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.forward_grid.fact, (model.dt^2) .* (model.matprop.vp .^ 2)) ########################################################### -struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} +struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T,N}, V <: AbstractVector{T}} <: AcousticCDWaveSimul{N} # Physics - domainextent::NTuple{N, <:Real} + domainextent::NTuple{N, T} # Numerics - ns::NTuple{N, <:Integer} - gridspacing::NTuple{N, <:Real} - nt::Integer - dt::Real + ns::NTuple{N, Int} + gridspacing::NTuple{N, T} + nt::Int + dt::T # BDC and CPML parameters - halo::Integer - rcoef::Real + halo::Int + rcoef::T freetop::Bool # Gradient computation setup gradient::Bool - totgrad_size::Union{Vector{<:Integer}, Nothing} - check_freq::Union{<:Integer, Nothing} + totgrad_size::Union{Vector{Int}, Nothing} # Snapshots - snapevery::Union{<:Integer, Nothing} - snapshots::Union{Any, Nothing} + snapevery::Union{Int, Nothing} + snapshots::Union{Vector{A}, Nothing} # Logging parameters - infoevery::Integer - # Gradient smoothing parameters - smooth_radius::Integer + infoevery::Int # Material properties matprop::VpAcousticCDMaterialProperties # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} - # Forward computation arrays - fact::Any - pold::Any - pcur::Any - pnew::Any - ψ::Any - ξ::Any - a_coeffs::Any - b_coeffs::Any - # Gradient computation arrays - curgrad::Any - adjold::Any - adjcur::Any - adjnew::Any - ψ_adj::Any - ξ_adj::Any + # Forward computation grid + forward_grid::AcousticCDForwardGrid{N, T, A, V} + # Adjoint computation grid + adjoint_grid::Union{AcousticCDAdjointGrid{N, T, A}, Nothing} # Checkpointing setup - last_checkpoint::Union{<:Integer, Nothing} - save_buffer::Any - checkpoints::Any - checkpoints_ψ::Any - checkpoints_ξ::Any - # Backend - backend::Module + checkpointing::Union{AcousticCDCheckpointing{N, T, A}, Nothing} + # Parallelization type parall::Symbol - function AcousticCDCPMLWaveSimul{N}( - ns::NTuple{N, <:Integer}, - gridspacing::NTuple{N, <:Real}, - nt::Integer, - dt::Real, - halo::Integer, - rcoef::Real; + function AcousticCDCPMLWaveSimul( + ns::NTuple{N, Int}, + gridspacing::NTuple{N, T}, + nt::Int, + dt::T, + halo::Int, + rcoef::T; parall::Symbol=:threads, freetop::Bool=true, gradient::Bool=false, - check_freq::Union{<:Integer, Nothing}=nothing, - snapevery::Union{<:Integer, Nothing}=nothing, - infoevery::Union{<:Integer, Nothing}=nothing, - smooth_radius::Integer=5 - ) where {N} + check_freq::Union{Int, Nothing}=nothing, + snapevery::Union{Int, Nothing}=nothing, + infoevery::Union{Int, Nothing}=nothing, + smooth_radius::Int=5 + ) where {N,T} # Check numerics @assert all(ns .> 0) "All numbers of grid points must be positive!" @assert all(gridspacing .> 0) "All cell sizes must be positive!" @@ -134,92 +114,24 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} matprop = VpAcousticCDMaterialProperties(zeros(ns...)) # Select backend - backend = select_backend(AcousticCDCPMLWaveSimul{N}, parall) + backend = select_backend(AcousticCDCPMLWaveSimul{N,T}, parall) + A = backend.Data.Array{N} + V = backend.Data.Array{1} - # Initialize computational arrays - fact = backend.zeros(ns...) - pold = backend.zeros(ns...) - pcur = backend.zeros(ns...) - pnew = backend.zeros(ns...) - # Initialize CPML arrays - ψ = [] - ξ = [] - for i in 1:N - ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) - end # Initialize CPML coefficients cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, true) for _ in 1:N]...) - # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) - a_coeffs = [] - b_coeffs = [] - for i in 1:N - append!(a_coeffs, [cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr]) - append!(b_coeffs, [cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr]) - end - # Initialize gradient arrays if needed + # Initialize forward grid + forward_grid = AcousticCDForwardGrid(ns, halo, cpmlcoeffs, backend, T) + + # Initialize gradient grid if needed if gradient - totgrad_size = [ns...] - # Current gradient array - curgrad = backend.zeros(ns...) - # Adjoint arrays - adjold = backend.zeros(ns...) - adjcur = backend.zeros(ns...) - adjnew = backend.zeros(ns...) - # Initialize CPML arrays - ψ_adj = [] - ξ_adj = [] - for i in 1:N - ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) - end + adjoint_grid = AcousticCDAdjointGrid(ns, halo, backend, smooth_radius, T) # Checkpointing setup - if check_freq !== nothing - @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" - @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" - # Time step of last checkpoint - last_checkpoint = floor(Int, nt / check_freq) * check_freq - # Checkpointing arrays - save_buffer = backend.zeros(ns..., check_freq + 2) # pressure window buffer - checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints - checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints - checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints - # Save initial conditions as first checkpoint - checkpoints[-1] = copy(pold) - checkpoints[0] = copy(pcur) - checkpoints_ψ[0] = copy.(ψ) - checkpoints_ξ[0] = copy.(ξ) - # Preallocate future checkpoints - for it in 1:(nt+1) - if it % check_freq == 0 - checkpoints[it] = backend.zeros(ns...) - checkpoints[it-1] = backend.zeros(ns...) - checkpoints_ψ[it] = copy.(ψ) - checkpoints_ξ[it] = copy.(ξ) - end - end - else # no checkpointing - last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) - save_buffer = backend.zeros(ns..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) - checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) - checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) - checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) - end - # Save first 2 timesteps in save buffer - copyto!(save_buffer[fill(Colon(), N)..., 1], pold) - copyto!(save_buffer[fill(Colon(), N)..., 2], pcur) + checkpointing = AcousticCDCheckpointing(check_freq, nt, ns, forward_grid, backend, T) end # Initialize snapshots array - snapshots = (snapevery !== nothing ? backend.zeros(ns..., div(nt, snapevery)) : nothing) + snapshots = (snapevery !== nothing ? [backend.zeros(ns...) for _ in 1:div(nt, snapevery)] : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -227,7 +139,7 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - return new( + return new{N,T,A,V}( domainextent, ns, gridspacing, @@ -237,34 +149,15 @@ struct AcousticCDCPMLWaveSimul{N} <: AcousticCDWaveSimul{N} rcoef, freetop, gradient, - gradient ? totgrad_size : nothing, - gradient ? check_freq : nothing, + gradient ? adjoint_grid.totgrad_size : nothing, snapevery, snapshots, infoevery, - smooth_radius, matprop, cpmlcoeffs, - fact, - pold, - pcur, - pnew, - ψ, - ξ, - a_coeffs, - b_coeffs, - gradient ? curgrad : nothing, - gradient ? adjold : nothing, - gradient ? adjcur : nothing, - gradient ? adjnew : nothing, - gradient ? ψ_adj : nothing, - gradient ? ξ_adj : nothing, - gradient ? last_checkpoint : nothing, - gradient ? save_buffer : nothing, - gradient ? checkpoints : nothing, - gradient ? checkpoints_ψ : nothing, - gradient ? checkpoints_ξ : nothing, - backend, + forward_grid, + gradient ? adjoint_grid : nothing, + gradient ? checkpointing : nothing, parall ) end @@ -275,27 +168,29 @@ end # Specific functions for AcousticCDCPMLWaveSimul @views function reset!(model::AcousticCDCPMLWaveSimul{N}) where {N} + forwad_grid = model.forward_grid + adjoint_grid = model.adjoint_grid # Reset computational arrays - model.pold .= 0.0 - model.pcur .= 0.0 - model.pnew .= 0.0 - for i in eachindex(model.ψ) - model.ψ[i] .= 0.0 + forwad_grid.pold .= 0.0 + forwad_grid.pcur .= 0.0 + forwad_grid.pnew .= 0.0 + for i in eachindex(forwad_grid.ψ) + forwad_grid.ψ[i] .= 0.0 end - for i in eachindex(model.ξ) - model.ξ[i] .= 0.0 + for i in eachindex(forwad_grid.ξ) + forwad_grid.ξ[i] .= 0.0 end # Reset gradient arrays if model.gradient - model.curgrad .= 0.0 - model.adjold .= 0.0 - model.adjcur .= 0.0 - model.adjnew .= 0.0 - for i in eachindex(model.ψ_adj) - model.ψ_adj[i] .= 0.0 + adjoint_grid.curgrad .= 0.0 + adjoint_grid.adjold .= 0.0 + adjoint_grid.adjcur .= 0.0 + adjoint_grid.adjnew .= 0.0 + for i in eachindex(adjoint_grid.ψ_adj) + adjoint_grid.ψ_adj[i] .= 0.0 end - for i in eachindex(model.ξ_adj) - model.ξ_adj[i] .= 0.0 + for i in eachindex(adjoint_grid.ξ_adj) + adjoint_grid.ξ_adj[i] .= 0.0 end end end diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index bd6feef..d0df550 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -4,7 +4,7 @@ include("shared/smooth_gradient_1D.jl") # Dummy data module module Data -Array = Base.Array +Array = Base.Array{Float64} end ##### @@ -14,7 +14,7 @@ zeros = Base.zeros @views function inject_sources!(pnew, dt2srctf, possrcs, it) _, nsrcs = size(dt2srctf) for i in 1:nsrcs - isrc = possrcs[i, 1] + isrc = floor(Int, possrcs[i, 1]) pnew[isrc] += dt2srctf[it, i] end end @@ -22,7 +22,7 @@ end @views function record_receivers!(pnew, traces, posrecs, it) _, nrecs = size(traces) for s in 1:nrecs - irec = posrecs[s, 1] + irec = floor(Int, posrecs[s, 1]) traces[it, s] = pnew[irec] end end diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl index cd5c9b9..c7533be 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl @@ -5,7 +5,7 @@ include("shared/smooth_gradient_2D.jl") # Dummy data module module Data -Array = Base.Array +Array = Base.Array{Float64} end # the backend needs these diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl index b9d3e17..c7ac424 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl @@ -5,7 +5,7 @@ include("shared/smooth_gradient_3D.jl") # Dummy data module module Data -Array = Base.Array +Array = Base.Array{Float64} end # the backend needs these diff --git a/src/wrappers.jl b/src/wrappers.jl index 0d1c250..7f3a5d9 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -286,7 +286,7 @@ build_concrete_wavesim( cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... -) where {N} = AcousticCDCPMLWaveSimul{N}( +) where {N} = AcousticCDCPMLWaveSimul( params.gridsize, params.gridspacing, params.ntimesteps, @@ -294,7 +294,7 @@ build_concrete_wavesim( cpmlparams.halo, cpmlparams.rcoef; freetop=cpmlparams.freeboundtop, - parall, + parall=parall, kwargs... ) From bb60945628639085019549d1555016106d27712a Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 14 Jun 2024 09:49:21 +0200 Subject: [PATCH 036/111] Better tests --- test/runtests.jl | 15 ++++++++++++--- ...ical_vs_numerical_acoustic_constant_density.jl | 14 ++------------ ...ical_vs_numerical_acoustic_variable_density.jl | 10 +++------- test/test_forward_constant_density.jl | 10 +++------- test/test_gradient_acoustic_constant_density.jl | 14 ++++++-------- test/test_gradient_acoustic_variable_density.jl | 12 +++++------- test/test_misfit_acoustic_constant_density.jl | 12 +++++------- 7 files changed, 36 insertions(+), 51 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 3546290..58d4d97 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,11 +2,20 @@ # the following lines allow for precompiling of depencencies, making tests run faster push!(LOAD_PATH, "../src") -using SeismicWaves: SeismicWaves using Test, TestSetExtensions +using DSP, NumericalIntegration, LinearAlgebra +using Logging +using SeismicWaves -# Run all specified tests +# Load CUDA only if requested for testing +if "CUDA" in ARGS + using CUDA +end + +include("utils/setup_models.jl") + +# Run all tests @testset ExtendedTestSet "SeismicWaves Tests" begin - @includetests ARGS + @includetests end diff --git a/test/test_analytical_vs_numerical_acoustic_constant_density.jl b/test/test_analytical_vs_numerical_acoustic_constant_density.jl index 44be766..5b8b3ea 100644 --- a/test/test_analytical_vs_numerical_acoustic_constant_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_constant_density.jl @@ -1,17 +1,7 @@ -using Test -using DSP, NumericalIntegration, LinearAlgebra -using CUDA: CUDA - -using SeismicWaves - -include("utils/setup_models.jl") - -using Logging -error_logger = ConsoleLogger(stderr, Logging.Error) -with_logger(error_logger) do +with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional - if CUDA.functional() + if @isdefined(CUDA) && CUDA.functional() push!(test_backends, :GPU) end diff --git a/test/test_analytical_vs_numerical_acoustic_variable_density.jl b/test/test_analytical_vs_numerical_acoustic_variable_density.jl index c806129..043650a 100644 --- a/test/test_analytical_vs_numerical_acoustic_variable_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_variable_density.jl @@ -1,17 +1,13 @@ using Test using DSP, NumericalIntegration, LinearAlgebra using CUDA: CUDA - +using Logging using SeismicWaves -include("utils/setup_models.jl") - -using Logging -error_logger = ConsoleLogger(stderr, Logging.Error) -with_logger(error_logger) do +with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:threads] # test GPU backend only if CUDA is functional - if CUDA.functional() + if @isdefined(CUDA) && CUDA.functional() push!(test_backends, :GPU) end diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index df73109..418ca33 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -1,17 +1,13 @@ using Test using DSP, NumericalIntegration, LinearAlgebra using CUDA: CUDA - +using Logging using SeismicWaves -include("utils/setup_models.jl") - -using Logging -error_logger = ConsoleLogger(stderr, Logging.Error) -with_logger(error_logger) do +with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional - if CUDA.functional() + if @isdefined(CUDA) && CUDA.functional() push!(test_backends, :GPU) end diff --git a/test/test_gradient_acoustic_constant_density.jl b/test/test_gradient_acoustic_constant_density.jl index 5d45914..87b903c 100644 --- a/test/test_gradient_acoustic_constant_density.jl +++ b/test/test_gradient_acoustic_constant_density.jl @@ -1,15 +1,13 @@ -using Test, LinearAlgebra -using SeismicWaves +using Test +using DSP, NumericalIntegration, LinearAlgebra using CUDA: CUDA - -include("utils/setup_models.jl") - using Logging -error_logger = ConsoleLogger(stderr, Logging.Error) -with_logger(error_logger) do +using SeismicWaves + +with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional - if CUDA.functional() + if @isdefined(CUDA) && CUDA.functional() push!(test_backends, :GPU) end diff --git a/test/test_gradient_acoustic_variable_density.jl b/test/test_gradient_acoustic_variable_density.jl index 4ab8283..2a30071 100644 --- a/test/test_gradient_acoustic_variable_density.jl +++ b/test/test_gradient_acoustic_variable_density.jl @@ -1,15 +1,13 @@ using Test -using SeismicWaves +using DSP, NumericalIntegration, LinearAlgebra using CUDA: CUDA - -include("utils/setup_models.jl") - using Logging -error_logger = ConsoleLogger(stderr, Logging.Error) -with_logger(error_logger) do +using SeismicWaves + +with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:threads] # test GPU backend only if CUDA is functional - if CUDA.functional() + if @isdefined(CUDA) && CUDA.functional() push!(test_backends, :GPU) end diff --git a/test/test_misfit_acoustic_constant_density.jl b/test/test_misfit_acoustic_constant_density.jl index 788e737..ab017bf 100644 --- a/test/test_misfit_acoustic_constant_density.jl +++ b/test/test_misfit_acoustic_constant_density.jl @@ -1,15 +1,13 @@ using Test -using SeismicWaves +using DSP, NumericalIntegration, LinearAlgebra using CUDA: CUDA - -include("utils/setup_models.jl") - using Logging -error_logger = ConsoleLogger(stderr, Logging.Error) -with_logger(error_logger) do +using SeismicWaves + +with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional - if CUDA.functional() + if @isdefined(CUDA) && CUDA.functional() push!(test_backends, :GPU) end From 8ba7f1c2eda799dc88483ea5a75b0ebbca4701c0 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 14 Jun 2024 10:13:50 +0200 Subject: [PATCH 037/111] Better logging --- src/models/acoustic/acou_forward.jl | 8 +++---- src/models/acoustic/acou_gradient.jl | 19 ++++------------ src/models/acoustic/acou_models.jl | 6 ++--- src/models/elastic/ela_forward.jl | 2 +- src/models/elastic/ela_models.jl | 4 ++-- src/solve.jl | 34 ++++++++++++++-------------- 6 files changed, 31 insertions(+), 42 deletions(-) diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 0379468..db811ea 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -57,7 +57,7 @@ end ) # Print timestep info if it % wavsim.infoevery == 0 - @debug @sprintf( + @info @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, wavsim.dt * (it - 1), @@ -67,7 +67,7 @@ end # Save snapshot if snapenabled(wavsim) && it % wavsim.snapevery == 0 - @debug @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) + @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], pcur) end end @@ -129,7 +129,7 @@ end ) # Print timestep info if it % wavsim.infoevery == 0 - @debug @sprintf( + @info @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, wavsim.dt * (it - 1), @@ -139,7 +139,7 @@ end # Save snapshot if snapenabled(wavsim) && it % wavsim.snapevery == 0 - @debug @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) + @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], pcur) end end diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index fc37a78..cb77208 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -45,7 +45,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = ) # Print timestep info if it % model.infoevery == 0 - @debug @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) + @info @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) end # Save checkpoint if checkpointing.check_freq !== nothing && it % checkpointing.check_freq == 0 @@ -91,7 +91,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = ) # Print timestep info if it % model.infoevery == 0 - @debug @sprintf("Backward iteration: %d", it) + @info @sprintf("Backward iteration: %d", it) end # Check if out of save buffer if (it - 1) < curr_checkpoint @@ -124,9 +124,6 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false ) - if recit % model.infoevery == 0 - @debug @sprintf("Recovering iteration: %d", recit) - end # Save recovered pressure in save buffer copyto!(checkpointing.save_buffer[recit-(curr_checkpoint+1)+3], pcur) end @@ -188,7 +185,7 @@ end ) # Print timestep info if it % model.infoevery == 0 - @debug @sprintf("Forward iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, model.dt * it, maximum(abs.(Array(pcur)))) + @info @sprintf("Forward iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, model.dt * it, maximum(abs.(Array(pcur)))) end # Save checkpoint if model.check_freq !== nothing && it % model.check_freq == 0 @@ -235,7 +232,7 @@ end ) # Print timestep info if it % model.infoevery == 0 - @debug @sprintf("Backward iteration: %d", it) + @info @sprintf("Backward iteration: %d", it) end # Check if out of save buffer if (it - 1) < curr_checkpoint @@ -267,14 +264,6 @@ end possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false ) - if recit % model.infoevery == 0 - @debug @sprintf( - "Recover forward iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", - recit, - model.dt * recit, - maximum(abs.(Array(pcur))) - ) - end # Save recovered pressure in save buffer copyto!(model.save_buffer[fill(Colon(), N)..., recit-(curr_checkpoint+1)+2], pcur) end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index bba2465..88c84db 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -6,7 +6,7 @@ vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) courant = vel_max * model.dt * tmp - @debug "Courant number: $(courant)" + @info "Courant number: $(courant)" if courant > 1.0 @warn "Courant condition not satisfied! [$(courant)]" end @@ -21,7 +21,7 @@ function check_numerics( vel_min = get_minimum_func(model)(model.matprop.vp) h_max = maximum(model.gridspacing) ppw = vel_min / shot.srcs.domfreq / h_max - @debug "Points per wavelength: $(ppw)" + @info "Points per wavelength: $(ppw)" @assert ppw >= min_ppw "Not enough points per wavelengh!" end @@ -210,7 +210,7 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil - @debug "Courant number: $(courant)" + @info "Courant number: $(courant)" if courant > 1 @warn "Courant condition not satisfied! [$(courant)]" end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 0bce1b7..126dce0 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -107,7 +107,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # Save snapshot if snapenabled(wavsim) && it % wavsim.snapevery == 0 #error("Snapshot for elastic not yet implemented...") - @debug @sprintf("Snapping iteration: %d", it) + @info @sprintf("Snapping iteration: %d", it) dummyidxs = fill(Colon(), N) # Vx wavsim.snapshots[1][dummyidxs..., div(it, wavsim.snapevery)] .= Array(wavsim.velpartic.vx) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 632691a..effd001 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -15,7 +15,7 @@ vel_max = get_maximum_func(wavsim)(vp) tmp = sqrt.(sum(1 ./ wavsim.gridspacing .^ 2)) courant = vel_max * wavsim.dt * tmp - @debug "Courant number: $(courant)" + @info "Courant number: $(courant)" if courant > 1.0 @warn "Courant condition not satisfied! [$(courant)]" end @@ -34,7 +34,7 @@ function check_numerics( h_max = maximum(wavsim.gridspacing) fmax = shot.srcs.domfreq * 2.0 ppw = vel_min / (fmax * h_max) - @debug "Points per wavelength: $(ppw)" + @info "Points per wavelength: $(ppw)" dh0 = round((vel_min / (min_ppw * fmax)); digits=2) @assert ppw >= min_ppw "Not enough points per wavelength (assuming fmax = 2*domfreq)! \n [$(round(ppw,digits=1)) instead of >= $min_ppw]\n Grid spacing should be <= $dh0" diff --git a/src/solve.jl b/src/solve.jl index 87218b7..6284274 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -22,7 +22,7 @@ end # Set wavesim material properties # Remark: matprop in wavesim are mutated - @info "Setting wavesim material properties" + @debug "Setting wavesim material properties" set_wavesim_matprop!(wavsim, matprop) # Now onwards matprop from "outside" should not be used anymore!!! @@ -33,12 +33,13 @@ end end # Shots loop - for singleshot in shots + for (s, singleshot) in enumerate(shots) + @info "Shot #$s" # Initialize shot - @info "Initializing shot" + @debug "Initializing shot" init_shot!(wavsim, singleshot) # Compute forward solver - @info "Forward modelling for one shot" + @info "Computing forward solver" swforward_1shot!(wavsim, singleshot) # Save shot's snapshots if takesnapshots @@ -71,7 +72,7 @@ end check_sim_consistency(wavsim[w], matprop, shots) # Set wavesim material properties # Remark: matprop in wavesim are mutated - @info "Setting wavesim material properties" + @debug "Setting wavesim material properties" set_wavesim_matprop!(wavsim[w], matprop) # Now onwards matprop from outside should not be used anymore!!! @@ -88,14 +89,13 @@ end Threads.@threads for w in 1:nwsim # loop on the subset of shots per each WaveSimul for s in grpshots[w] + @info "Shot #$s" singleshot = shots[s] # Initialize shot - @info "Initializing shot" - #possrcs, posrecs, srctf = init_shot!(wavsim[w], singleshot) + @debug "Initializing shot" init_shot!(wavsim[w], singleshot) # Compute forward solver - @info "Forward modelling for one shot" - #swforward_1shot!(wavsim[w], possrcs, posrecs, srctf, recs) + @info "Computing forward solver" swforward_1shot!(wavsim[w], singleshot) # Save shot's snapshots if snapenabled(wavsim[w]) @@ -124,9 +124,10 @@ end # Solve forward model for all shots run_swforward!(wavsim, matprop, shots) # Compute total misfit for all shots + @info "Computing misfit" totmisfitval = 0 for singleshot in shots - @info "Checking invcov matrix" + @debug "Checking invcov matrix" if typeof(wavsim) <: Vector{<:WaveSimul} for i in eachindex(wavsim) check_invcov_matrix(wavsim[i], singleshot.recs.invcov) @@ -134,7 +135,6 @@ end else check_invcov_matrix(wavsim, singleshot.recs.invcov) end - @info "Computing misfit" totmisfitval += misfit(singleshot.recs, matprop) end @@ -157,7 +157,7 @@ end check_sim_consistency(wavsim, matprop, shots) # Set wavesim material properties - @info "Setting wavesim material properties" + @debug "Setting wavesim material properties" set_wavesim_matprop!(wavsim, matprop) # Initialize total gradient and total misfit @@ -167,9 +167,9 @@ end for (s, singleshot) in enumerate(shots) @info "Shot #$s" # Initialize shot - @info "Initializing shot" + @debug "Initializing shot" init_shot!(wavsim, singleshot) - @info "Checking invcov matrix" + @debug "Checking invcov matrix" check_invcov_matrix(wavsim, singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" @@ -205,7 +205,7 @@ end check_sim_consistency(wavsim[w], matprop, shots) # Set wavesim material properties - @info "Setting wavesim material properties" + @debug "Setting wavesim material properties" set_wavesim_matprop!(wavsim[w], matprop) end @@ -227,9 +227,9 @@ end singleshot = shots[s] @info "Shot #$s" # Initialize shot - @info "Initializing shot" + @debug "Initializing shot" init_shot!(wavsim[w], singleshot) - @info "Checking invcov matrix" + @debug "Checking invcov matrix" check_invcov_matrix(wavsim[w], singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" From 8202dc85b73600480302a4b1cc48fd6fbd931dee Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 14 Jun 2024 10:23:36 +0200 Subject: [PATCH 038/111] Fix return in wrappers --- src/wrappers.jl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/wrappers.jl b/src/wrappers.jl index 7f3a5d9..e7398b2 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -72,11 +72,9 @@ function swforward!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matpro if logger === nothing logger = current_logger() end - out = nothing - with_logger(logger) do - out = run_swforward!(wavesim, matprop, shots; kwargs...) + return with_logger(logger) do + run_swforward!(wavesim, matprop, shots; kwargs...) end - return out end ####################################################### @@ -272,8 +270,7 @@ Builds a wave similation based on the input paramters `params` and keyword argum function build_wavesim(params::InputParameters, matprop::MaterialProperties; parall::Symbol, kwargs...) if parall == :threadpersrc nthr = Threads.nthreads() - #println(" build_wavesim :threadpersrc") - wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for s in 1:nthr] + wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for _ in 1:nthr] else wsim = build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) end From 7f72a6965d08a8ebaf335f5cc12c6955692895d8 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 14 Jun 2024 19:16:08 +0200 Subject: [PATCH 039/111] First overhaul (WIP) --- src/SeismicWaves.jl | 5 + src/checks.jl | 12 +- src/grids/abstract_types.jl | 5 + src/grids/checkpointers.jl | 106 +++++++++++++++ src/grids/fields.jl | 35 +++++ src/grids/grids.jl | 34 +++++ src/models/acoustic/acou_forward.jl | 16 +-- src/models/acoustic/acou_gradient.jl | 107 ++++++---------- src/models/acoustic/acou_grid.jl | 185 ++++++++------------------- src/models/acoustic/acou_init_bc.jl | 2 +- src/models/acoustic/acou_models.jl | 158 ++++++++++++++--------- src/shot.jl | 2 +- 12 files changed, 387 insertions(+), 280 deletions(-) create mode 100644 src/grids/abstract_types.jl create mode 100644 src/grids/checkpointers.jl create mode 100644 src/grids/fields.jl create mode 100644 src/grids/grids.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index a567e2a..9e9ea96 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -46,6 +46,11 @@ include("srcrec_interpolation.jl") include("models/cpmlcoeffs.jl") +include("grids/abstract_types.jl") +include("grids/fields.jl") +include("grids/grids.jl") +include("grids/checkpointers.jl") + # Acoustic include("models/acoustic/acou_abstract_types.jl") include("models/acoustic/acou_grid.jl") diff --git a/src/checks.jl b/src/checks.jl index 2a7735b..9e85b3f 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -36,12 +36,12 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s end function check_shot(model::WaveSimul, shot::Shot; kwargs...) - @debug "Checking model/shot numerics" - check_numerics(model, shot; kwargs...) - @debug "Checking sources positions" - check_positions(model, shot.srcs.positions) - @debug "Checking receivers positions" - check_positions(model, shot.recs.positions) + # @debug "Checking model/shot numerics" + # check_numerics(model, shot; kwargs...) + # @debug "Checking sources positions" + # check_positions(model, shot.srcs.positions) + # @debug "Checking receivers positions" + # check_positions(model, shot.recs.positions) return end diff --git a/src/grids/abstract_types.jl b/src/grids/abstract_types.jl new file mode 100644 index 0000000..f60a902 --- /dev/null +++ b/src/grids/abstract_types.jl @@ -0,0 +1,5 @@ +abstract type AbstractField{N, T} end + +abstract type AbstractGrid{N, T} end + +abstract type AbstractCheckpointer{N, T} end \ No newline at end of file diff --git a/src/grids/checkpointers.jl b/src/grids/checkpointers.jl new file mode 100644 index 0000000..25d8e2a --- /dev/null +++ b/src/grids/checkpointers.jl @@ -0,0 +1,106 @@ +mutable struct LinearCheckpointer{N, T} <: AbstractCheckpointer{N, T} + nt::Int + check_freq::Int + last_checkpoint::Int + curr_checkpoint::Int + buffers::Dict{String, Vector{<:AbstractField{N, T}}} + checkpoints::Dict{Int, Dict{String, <:AbstractField{N, T}}} + widths::Dict{String, Int} + + function LinearCheckpointer( + nt::Int, + check_freq::Int, + checkpointed_fields::Dict{String, <:AbstractField{N, T}}, + buffered_fields::Vector{String}; + widths::Dict{String, Int}=Dict() + ) where {N, T} + @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" + # Time step of last checkpoint + last_checkpoint = floor(Int, nt / check_freq) * check_freq + # Preallocate checkpoints + checkpoints = Dict{Int, Dict{String, AbstractField{N,T}}}() + for it in 0:(nt+1) + if it % check_freq == 0 + for (name, field) in checkpointed_fields + w = haskey(widths, name) ? widths[name] : 1 + for itw in it:-1:it-w+1 + if !haskey(checkpoints, itw) + checkpoints[itw] = Dict() + end + checkpoints[itw][name] = deepcopy(field) + end + end + end + end + # Preallocate buffers + buffers = Dict{String, Vector{AbstractField{N, T}}}() + for name in buffered_fields + buffers[name] = [deepcopy(checkpointed_fields[name]) for _ in 1:check_freq+1] + end + new{N,T}(nt, check_freq, last_checkpoint, last_checkpoint, buffers, checkpoints, widths) + end +end + +function savecheckpoint!(checkpointer::LinearCheckpointer{N,T}, field::Pair{String, <:AbstractField{N,T}}, it::Int) where {N,T} + # Save field in checkpoints + w = haskey(checkpointer.widths, field.first) ? checkpointer.widths[field.first] : 1 + for itw in it:it+w-1 + if itw % checkpointer.check_freq == 0 + copyto!(checkpointer.checkpoints[it][field.first], field.second) + end + end + # Start populating buffer at last checkpoint + if it >= checkpointer.last_checkpoint + copyto!(checkpointer.buffers[field.first][it - checkpointer.last_checkpoint + 1], field.second) + end +end + +function isbuffered(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::Bool where {N,T} + return haskey(checkpointer.buffers, field) && (checkpointer.curr_checkpoint <= it <= checkpointer.curr_checkpoint + checkpointer.check_freq) +end + +function getbuffered(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::AbstractField{N,T} where {N,T} + @assert isbuffered(checkpointer, field, it) + return checkpointer.buffers[field][it - checkpointer.curr_checkpoint + 1] +end + +function ischeckpointed(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::Bool where {N,T} + return haskey(checkpointer.checkpoints, it) && haskey(checkpointer.checkpoints[it], field) +end + +function getcheckpointed(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::AbstractField{N,T} where {N,T} + @assert ischeckpointed(checkpointer, field, it) + return checkpointer.checkpoints[it][field] +end + +function issaved(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::Bool where {N,T} + return isbuffered(checkpointer, field, it) || ischeckpointed(checkpointer, field, it) +end + +function getsaved(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::AbstractField{N,T} where {N,T} + if ischeckpointed(checkpointer, field, it) + return getcheckpointed(checkpointer, field, it) + end + return getbuffered(checkpointer, field, it) +end + +function initrecover!(checkpointer::LinearCheckpointer{N,T}) where {N,T} + old_checkpoint = checkpointer.curr_checkpoint + checkpointer.curr_checkpoint -= checkpointer.check_freq + for (name, buffer) in checkpointer.buffers + copyto!(buffer[1], checkpointer.checkpoints[checkpointer.curr_checkpoint][name]) + copyto!(buffer[end], checkpointer.checkpoints[old_checkpoint][name]) + end +end +function recover!(checkpointer::LinearCheckpointer{N,T}, recoverfun) where {N,T} + for it in (checkpointer.curr_checkpoint+1):(old_checkpoint-1) + recovered_fields = recoverfun(it) + for (name, field) in recovered_fields + copyto!(buffer[name][it - (checkpointer.curr_checkpoint+1) + 2], field) + end + end +end + +function reset!(checkpointer::LinearCheckpointer) + checkpointer.curr_checkpoint = checkpointer.last_checkpoint +end \ No newline at end of file diff --git a/src/grids/fields.jl b/src/grids/fields.jl new file mode 100644 index 0000000..f184f9a --- /dev/null +++ b/src/grids/fields.jl @@ -0,0 +1,35 @@ +struct ScalarConstantField{N, T} <: AbstractField{N, T} + value::T +end + +struct ScalarVariableField{N, T, A <: AbstractArray{T}} <: AbstractField{N, T} + value::A +end + +struct MultiConstantField{N, T, V <: AbstractArray{T}} <: AbstractField{N, T} + value::V +end + +struct MultiVariableField{N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} <: AbstractField{N, T} + value::V +end + +function SeismicWaves.copyto!(dest::ScalarVariableField{N, T, A}, src::ScalarConstantField{N, T}) where {N, T, A <: AbstractArray{T}} + dest.value .= src.value +end +SeismicWaves.copyto!(dest::ScalarVariableField{N, T, A}, src::ScalarVariableField{N, T, A}) where {N, T, A <: AbstractArray{T}} = copyto!(dest.value, src.value) +function SeismicWaves.copyto!(dest::MultiVariableField{N,T,A,V}, src::ScalarConstantField{N,T}) where {N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} + for vdest in dest.value + vdest .= src.value + end +end +function SeismicWaves.copyto!(dest::MultiVariableField{N,T,A,V1}, src::MultiConstantField{N,T,V2}) where {N, T, A <: AbstractArray{T}, V1 <: AbstractArray{A}, V2 <: AbstractArray{T}} + for (vdest, vsrc) in zip(dest.value, src.value) + vdest .= vsrc + end +end +function SeismicWaves.copyto!(dest::MultiVariableField{N,T,A,V}, src::MultiVariableField{N,T,A,V}) where {N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} + for (vdest, vsrc) in zip(dest.value, src.value) + copyto!(vdest, vsrc) + end +end \ No newline at end of file diff --git a/src/grids/grids.jl b/src/grids/grids.jl new file mode 100644 index 0000000..fa99811 --- /dev/null +++ b/src/grids/grids.jl @@ -0,0 +1,34 @@ +struct UniformFiniteDifferenceGrid{N, T} <: AbstractGrid{N, T} + domainextent::NTuple{N, T} + ns::NTuple{N, Int} + gridspacing::NTuple{N, T} + fields::Dict{String, AbstractField{N,T}} + + function UniformFiniteDifferenceGrid( + ns::NTuple{N, Int}, gridspacing::NTuple{N, T} + ) where {N, T} + # Check numerics + @assert all(ns .> 0) "All numbers of grid points must be positive!" + @assert all(gridspacing .> 0) "All cell sizes must be positive!" + # Compute domain extent + domainextent = gridspacing .* (ns .- 1) + new{N, T}(domainextent, ns, gridspacing, Dict()) + end +end + +function addfield!(grid::UniformFiniteDifferenceGrid{N, T}, field::Pair{String, <:AbstractField{N,T}}) where {N, T} + name = field.first + if !haskey(grid.fields, name) + grid.fields[name] = field.second + else + error("Field with name [$(name)] already in the grid!") + end +end + +function reset!(grid::UniformFiniteDifferenceGrid{N,T}; except::Vector{String}=[]) where {N,T} + for (name, field) in grid.fields + if !(name in except) + copyto!(field, ScalarConstantField{N,T}(0.0)) + end + end +end \ No newline at end of file diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index db811ea..ffabb65 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -11,7 +11,7 @@ swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(Boundary # source time function # scale with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(wavsim.gridspacing) .* (wavsim.dt^2) + scal_srctf = shot.srcs.tf ./ prod(wavsim.grid.gridspacing) .* (wavsim.dt^2) # scale with velocity squared at each source position for s in axes(scal_srctf, 2) scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 @@ -29,13 +29,13 @@ end # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) - forward_grid = wavsim.forward_grid + grid = wavsim.grid backend = select_backend(typeof(wavsim), wavsim.parall) # Pressure arrays - pold = forward_grid.pold - pcur = forward_grid.pcur - pnew = forward_grid.pnew + pold = grid.fields["pold"].value + pcur = grid.fields["pcur"].value + pnew = grid.fields["pnew"].value # Numerics nt = wavsim.nt # Wrap sources and receivers arrays @@ -50,9 +50,9 @@ end for it in 1:nt # Compute one forward step pold, pcur, pnew = backend.forward_onestep_CPML!( - pold, pcur, pnew, forward_grid.fact, - wavsim.gridspacing..., wavsim.halo, - forward_grid.ψ..., forward_grid.ξ..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., + pold, pcur, pnew, grid.fields["fact"].value, + wavsim.grid.gridspacing..., wavsim.halo, + grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index cb77208..97cb132 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -11,21 +11,20 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) - forward_grid = model.forward_grid - adjoint_grid = model.adjoint_grid - checkpointing = model.checkpointing + grid = model.grid + checkpointer = model.checkpointer backend = select_backend(typeof(model), model.parall) # Numerics nt = model.nt # Initialize pressure and factors arrays - pold = forward_grid.pold - pcur = forward_grid.pcur - pnew = forward_grid.pnew + pold = grid.fields["pold"].value + pcur = grid.fields["pcur"].value + pnew = grid.fields["pnew"].value # Initialize adjoint arrays - adjold = adjoint_grid.adjold - adjcur = adjoint_grid.adjcur - adjnew = adjoint_grid.adjnew + adjold = grid.fields["adjold"].value + adjcur = grid.fields["adjcur"].value + adjnew = grid.fields["adjnew"].value # Wrap sources and receivers arrays possrcs_bk = backend.Data.Array(possrcs) posrecs_bk = backend.Data.Array(posrecs) @@ -38,9 +37,9 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = for it in 1:nt # Compute one forward step pold, pcur, pnew = backend.forward_onestep_CPML!( - pold, pcur, pnew, forward_grid.fact, - model.gridspacing..., model.halo, - forward_grid.ψ..., forward_grid.ξ..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., + pold, pcur, pnew, grid.fields["fact"].value, + wavsim.grid.gridspacing..., wavsim.halo, + grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value, grid.fields["b_pml"].value..., possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info @@ -48,23 +47,9 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @info @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) end # Save checkpoint - if checkpointing.check_freq !== nothing && it % checkpointing.check_freq == 0 - @debug @sprintf("Saving checkpoint at iteration: %d", it) - # Save current and last timestep pressure - copyto!(checkpointing.checkpoints[it], pcur) - copyto!(checkpointing.checkpoints[it-1], pold) - # Also save CPML arrays - for i in eachindex(forward_grid.ψ) - copyto!(checkpointing.checkpoints_ψ[it][i], forward_grid.ψ[i]) - end - for i in eachindex(forward_grid.ξ) - copyto!(checkpointing.checkpoints_ξ[it][i], forward_grid.ξ[i]) - end - end - # Start populating save buffer just before last checkpoint - if it >= checkpointing.last_checkpoint - 1 - copyto!(checkpointing.save_buffer[it-(checkpointing.last_checkpoint-1)+1], pcur) - end + savecheckpoint!(checkpointer, "pcur" => pcur, it) + savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], it) + savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], it) end @info "Saving seismograms" @@ -74,18 +59,16 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = residuals_bk = backend.Data.Array(dχ_du(misfit, shot.recs)) # Prescale residuals (fact = vel^2 * dt^2) - backend.prescale_residuals!(residuals_bk, posrecs_bk, forward_grid.fact) + backend.prescale_residuals!(residuals_bk, posrecs_bk, grid.fields["fact"]) @debug "Computing gradients" - # Current checkpoint - curr_checkpoint = checkpointing.last_checkpoint # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step adjold, adjcur, adjnew = backend.forward_onestep_CPML!( - adjold, adjcur, adjnew, forward_grid.fact, - model.gridspacing..., model.halo, - adjoint_grid.ψ_adj..., adjoint_grid.ξ_adj..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., + adjold, adjcur, adjnew, grid.fields["fact"].value, + model.grid.gridspacing..., model.halo, + grid.fields["ψ_adj"].value..., grid.fields["ξ_adj"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., posrecs_bk, residuals_bk, nothing, nothing, it; # adjoint sources positions are receivers save_trace=false ) @@ -94,51 +77,35 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @info @sprintf("Backward iteration: %d", it) end # Check if out of save buffer - if (it - 1) < curr_checkpoint + if !issaved(checkpointer, "pcur", it-2) @debug @sprintf("Out of save buffer at iteration: %d", it) - # Shift last checkpoint - old_checkpoint = curr_checkpoint - curr_checkpoint -= checkpointing.check_freq - # Shift start of save buffer - copyto!(checkpointing.save_buffer[1], checkpointing.checkpoints[curr_checkpoint-1]) - copyto!(checkpointing.save_buffer[2], checkpointing.checkpoints[curr_checkpoint]) - # Shift end of save buffer - copyto!(checkpointing.save_buffer[end-1], checkpointing.checkpoints[old_checkpoint-1]) - copyto!(checkpointing.save_buffer[end], checkpointing.checkpoints[old_checkpoint]) - # Recover pressure and CPML arrays from current checkpoint - copyto!(pold, checkpointing.checkpoints[curr_checkpoint-1]) - copyto!(pcur, checkpointing.checkpoints[curr_checkpoint]) - pnew .= 0.0 - for i in eachindex(checkpointing.checkpoints_ψ[curr_checkpoint]) - copyto!(forward_grid.ψ[i], checkpointing.checkpoints_ψ[curr_checkpoint][i]) - end - for i in eachindex(checkpointing.checkpoints_ξ[curr_checkpoint]) - copyto!(forward_grid.ξ[i], checkpointing.checkpoints_ξ[curr_checkpoint][i]) - end - # Forward recovery time loop - for recit in (curr_checkpoint+1):((old_checkpoint-1)-1) - pold, pcur, pnew = backend.forward_onestep_CPML!( - pold, pcur, pnew, forward_grid.fact, - model.gridspacing..., model.halo, - forward_grid.ψ..., forward_grid.ξ..., forward_grid.a_coeffs..., forward_grid.b_coeffs..., + initrecover!(checkpointer) + copyto!(pold, getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint - 1).value) + copyto!(pcur, getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint).value) + copyto!(grid.fields["ψ"], getsaved(checkpointer, "ψ", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ξ"], getsaved(checkpointer, "ξ", checkpointer.curr_checkpoint)) + recoverbuffer!(checkpointer, recit -> begin + _, recovered_pcur, _ = backend.forward_onestep_CPML!( + pold, pcur, pnew, grid.fields["fact"].value, + wavsim.grid.gridspacing..., wavsim.halo, + grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value, grid.fields["b_pml"].value..., possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false ) - # Save recovered pressure in save buffer - copyto!(checkpointing.save_buffer[recit-(curr_checkpoint+1)+3], pcur) - end + return recovered_pcur + end) end # Get pressure fields from saved buffer - pcur_corr = checkpointing.save_buffer[((it-1)-curr_checkpoint)+1] - pold_corr = checkpointing.save_buffer[((it-1)-curr_checkpoint)+2] - pveryold_corr = checkpointing.save_buffer[((it-1)-curr_checkpoint)+3] + pcur_corr = getsaved(checkpointer, "pcur", it-2).value + pold_corr = getsaved(checkpointer, "pcur", it-1).value + pveryold_corr = getsaved(checkpointer, "pcur", it).value # Correlate for gradient computation - backend.correlate_gradient!(adjoint_grid.curgrad, adjcur, pcur_corr, pold_corr, pveryold_corr, model.dt) + backend.correlate_gradient!(grid.fields["grad_vp"].value, adjcur, pcur_corr, pold_corr, pveryold_corr, model.dt) end # get gradient - gradient = Array(adjoint_grid.curgrad) + gradient = Array(grid.fields["grad_vp"].value) # smooth gradient - backend.smooth_gradient!(gradient, possrcs, adjoint_grid.smooth_radius) + backend.smooth_gradient!(gradient, possrcs, model.smooth_radius) # rescale gradient gradient .= (2.0 ./ (model.matprop.vp .^ 3)) .* gradient # add regularization if needed diff --git a/src/models/acoustic/acou_grid.jl b/src/models/acoustic/acou_grid.jl index e1126f0..d25d173 100644 --- a/src/models/acoustic/acou_grid.jl +++ b/src/models/acoustic/acou_grid.jl @@ -1,132 +1,53 @@ -struct AcousticCDForwardGrid{N, T, A <: AbstractArray{T,N}, V <: AbstractVector{T}} - fact::A - pold::A - pcur::A - pnew::A - ψ::Vector{A} - ξ::Vector{A} - a_coeffs::Vector{V} - b_coeffs::Vector{V} - - function AcousticCDForwardGrid(ns::NTuple{N, Int}, halo::Int, cpmlcoeffs::NTuple{N, CPMLCoefficients}, backend::Module, T::Type) where {N} - A = backend.Data.Array{N} - V = backend.Data.Array{1} - # Initialize computational arrays - fact = backend.zeros(ns...) - pold = backend.zeros(ns...) - pcur = backend.zeros(ns...) - pnew = backend.zeros(ns...) - # Initialize CPML arrays - ψ = [] - ξ = [] - for i in 1:N - ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) - end - # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) - a_coeffs = [] - b_coeffs = [] - for i in 1:N - append!(a_coeffs, [cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr]) - append!(b_coeffs, [cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr]) - end - - new{N,T,A,V}(fact, pold, pcur, pnew, ψ, ξ, a_coeffs, b_coeffs) - end -end - -struct AcousticCDAdjointGrid{N, T, A <: AbstractArray{T,N}} - curgrad::A - adjold::A - adjcur::A - adjnew::A - ψ_adj::Vector{A} - ξ_adj::Vector{A} - totgrad_size::Vector{Int} - smooth_radius::Int - - function AcousticCDAdjointGrid(ns::NTuple{N, Int}, halo::Int, backend::Module, smooth_radius::Int, T::Type) where {N} - A = backend.Data.Array{N} - - totgrad_size = [ns...] - # Current gradient array - curgrad = backend.zeros(ns...) - # Adjoint arrays - adjold = backend.zeros(ns...) - adjcur = backend.zeros(ns...) - adjnew = backend.zeros(ns...) - # Initialize CPML arrays - ψ_adj = [] - ξ_adj = [] - for i in 1:N - ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) - end - - new{N,T,A}(curgrad, adjold, adjcur, adjnew, ψ_adj, ξ_adj, totgrad_size, smooth_radius) - end -end - -struct AcousticCDCheckpointing{N, T, A <: AbstractArray{T,N}} - check_freq::Union{Int, Nothing} - last_checkpoint::Int - save_buffer::Vector{A} - checkpoints::Dict{Int, A} - checkpoints_ψ::Dict{Int, Vector{A}} - checkpoints_ξ::Dict{Int, Vector{A}} - - function AcousticCDCheckpointing( - check_freq::Union{Int, Nothing}, - nt::Int, - ns::NTuple{N, Int}, - forward_grid::AcousticCDForwardGrid{N}, - backend::Module, - T::Type - ) where {N} - A = backend.Data.Array{N} - if check_freq !== nothing - @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" - @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" - # Time step of last checkpoint - last_checkpoint = floor(Int, nt / check_freq) * check_freq - # Checkpointing arrays - save_buffer = [backend.zeros(ns...) for _ in 1:(check_freq + 2)] # pressure window buffer - checkpoints = Dict{Int, A}() # pressure checkpoints - checkpoints_ψ = Dict{Int, Vector{A}}() # ψ arrays checkpoints - checkpoints_ξ = Dict{Int, Vector{A}}() # ξ arrays checkpoints - # Save initial conditions as first checkpoint - checkpoints[-1] = copy(forward_grid.pold) - checkpoints[0] = copy(forward_grid.pcur) - checkpoints_ψ[0] = copy.(forward_grid.ψ) - checkpoints_ξ[0] = copy.(forward_grid.ξ) - # Preallocate future checkpoints - for it in 1:(nt+1) - if it % check_freq == 0 - checkpoints[it] = backend.zeros(ns...) - checkpoints[it-1] = backend.zeros(ns...) - checkpoints_ψ[it] = copy.(forward_grid.ψ) - checkpoints_ξ[it] = copy.(forward_grid.ξ) - end - end - else # no checkpointing - last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) - save_buffer = [backend.zeros(ns...) for _ in 1:(nt + 2)] # save all timesteps (from -1 to nt+1 so nt+2) - checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) - checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) - checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) - end - # Save first 2 timesteps in save buffer - copyto!(save_buffer[1], forward_grid.pold) - copyto!(save_buffer[2], forward_grid.pcur) - - new{N,T,A}(check_freq, last_checkpoint, save_buffer, checkpoints, checkpoints_ψ, checkpoints_ξ) - end -end \ No newline at end of file +# struct AcousticCDCheckpointing{N, T, A <: AbstractArray{T,N}} +# check_freq::Union{Int, Nothing} +# last_checkpoint::Int +# save_buffer::Vector{A} +# checkpoints::Dict{Int, A} +# checkpoints_ψ::Dict{Int, Vector{A}} +# checkpoints_ξ::Dict{Int, Vector{A}} + +# function AcousticCDCheckpointing( +# check_freq::Union{Int, Nothing}, +# nt::Int, +# ns::NTuple{N, Int}, +# grid::UniformFiniteDifferenceGrid{N,T}, +# backend::Module +# ) where {N,T,A} +# if check_freq !== nothing +# @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" +# @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" +# # Time step of last checkpoint +# last_checkpoint = floor(Int, nt / check_freq) * check_freq +# # Checkpointing arrays +# save_buffer = [backend.zeros(ns...) for _ in 1:(check_freq + 2)] # pressure window buffer +# checkpoints = Dict{Int, A}() # pressure checkpoints +# checkpoints_ψ = Dict{Int, Vector{A}}() # ψ arrays checkpoints +# checkpoints_ξ = Dict{Int, Vector{A}}() # ξ arrays checkpoints +# # Save initial conditions as first checkpoint +# checkpoints[-1] = copy(grid.fields["pold"]) +# checkpoints[0] = copy(grid.fields["pcur"]) +# checkpoints_ψ[0] = copy.(forward_grid.ψ) +# checkpoints_ξ[0] = copy.(forward_grid.ξ) +# # Preallocate future checkpoints +# for it in 1:(nt+1) +# if it % check_freq == 0 +# checkpoints[it] = backend.zeros(ns...) +# checkpoints[it-1] = backend.zeros(ns...) +# checkpoints_ψ[it] = copy.(forward_grid.ψ) +# checkpoints_ξ[it] = copy.(forward_grid.ξ) +# end +# end +# else # no checkpointing +# last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) +# save_buffer = [backend.zeros(ns...) for _ in 1:(nt + 2)] # save all timesteps (from -1 to nt+1 so nt+2) +# checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) +# checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) +# checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) +# end +# # Save first 2 timesteps in save buffer +# copyto!(save_buffer[1], forward_grid.pold) +# copyto!(save_buffer[2], forward_grid.pcur) + +# new{N,T,A}(check_freq, last_checkpoint, save_buffer, checkpoints, checkpoints_ψ, checkpoints_ξ) +# end +# end \ No newline at end of file diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index 2a16649..72b1f07 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -17,7 +17,7 @@ init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimul, srcs::Sources model.dt, model.halo, model.rcoef, - model.gridspacing[n] * model.halo, + model.grid.gridspacing[n] * model.halo, srcs.domfreq ) end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 88c84db..a321aca 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -4,7 +4,7 @@ @views function check_courant_condition(model::AcousticWaveSimul{N}, vp::Array{<:Real, N}) where {N} vel_max = get_maximum_func(model)(vp) - tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) + tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) courant = vel_max * model.dt * tmp @info "Courant number: $(courant)" if courant > 1.0 @@ -19,7 +19,7 @@ function check_numerics( ) # Check points per wavelength vel_min = get_minimum_func(model)(model.matprop.vp) - h_max = maximum(model.gridspacing) + h_max = maximum(model.grid.gridspacing) ppw = vel_min / shot.srcs.domfreq / h_max @info "Points per wavelength: $(ppw)" @assert ppw >= min_ppw "Not enough points per wavelengh!" @@ -32,7 +32,7 @@ end @views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{N}) where {N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(matprop.vp) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.ns)" + @assert size(matprop.vp) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.ns)" @assert all(matprop.vp .> 0) "Pressure velocity material property must be positive!" # Check courant condition check_courant_condition(model, matprop.vp) @@ -45,18 +45,16 @@ end precompute_fact!(model) end -@views precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.forward_grid.fact, (model.dt^2) .* (model.matprop.vp .^ 2)) +@views precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) ########################################################### -struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T,N}, V <: AbstractVector{T}} <: AcousticCDWaveSimul{N} - # Physics - domainextent::NTuple{N, T} +struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWaveSimul{N} # Numerics - ns::NTuple{N, Int} - gridspacing::NTuple{N, T} nt::Int dt::T + # Computational grid + grid::UniformFiniteDifferenceGrid{N, T} # BDC and CPML parameters halo::Int rcoef::T @@ -64,6 +62,7 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T,N}, V <: AbstractVecto # Gradient computation setup gradient::Bool totgrad_size::Union{Vector{Int}, Nothing} + smooth_radius::Int # Snapshots snapevery::Union{Int, Nothing} snapshots::Union{Vector{A}, Nothing} @@ -73,12 +72,8 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T,N}, V <: AbstractVecto matprop::VpAcousticCDMaterialProperties # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} - # Forward computation grid - forward_grid::AcousticCDForwardGrid{N, T, A, V} - # Adjoint computation grid - adjoint_grid::Union{AcousticCDAdjointGrid{N, T, A}, Nothing} # Checkpointing setup - checkpointing::Union{AcousticCDCheckpointing{N, T, A}, Nothing} + checkpointer::LinearCheckpointer{N, T} # Parallelization type parall::Symbol @@ -96,10 +91,8 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T,N}, V <: AbstractVecto snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, smooth_radius::Int=5 - ) where {N,T} + ) where {N, T} # Check numerics - @assert all(ns .> 0) "All numbers of grid points must be positive!" - @assert all(gridspacing .> 0) "All cell sizes must be positive!" @assert nt > 0 "Number of timesteps must be positive!" @assert dt > 0 "Timestep size must be positive!" @@ -108,28 +101,69 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T,N}, V <: AbstractVecto ns_cpml = freetop ? ns[1:(end-1)] : ns @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" - # Compute model sizes - domainextent = gridspacing .* (ns .- 1) - # Initialize material properties - matprop = VpAcousticCDMaterialProperties(zeros(ns...)) - # Select backend - backend = select_backend(AcousticCDCPMLWaveSimul{N,T}, parall) + backend = select_backend(AcousticCDCPMLWaveSimul{N, T}, parall) A = backend.Data.Array{N} V = backend.Data.Array{1} - + # Initialize computational grid + grid = UniformFiniteDifferenceGrid(ns, gridspacing) + # Initialize material properties + matprop = VpAcousticCDMaterialProperties(zeros(ns...)) # Initialize CPML coefficients cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, true) for _ in 1:N]...) - # Initialize forward grid - forward_grid = AcousticCDForwardGrid(ns, halo, cpmlcoeffs, backend, T) - # Initialize gradient grid if needed + # Populate computational grid + addfield!(grid, "fact" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "pold" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "pcur" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "pnew" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) if gradient - adjoint_grid = AcousticCDAdjointGrid(ns, halo, backend, smooth_radius, T) - # Checkpointing setup - checkpointing = AcousticCDCheckpointing(check_freq, nt, ns, forward_grid, backend, T) + addfield!(grid, "grad_vp" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "adjold" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "adjcur" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "adjnew" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + end + # CPML coefficients + addfield!( + grid, + "a_pml" => MultiVariableField{N, T, V, Vector{V}}( + cat([[cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hr] for i in 1:N]...; dims=1) + ) + ) + addfield!( + grid, + "b_pml" => MultiVariableField{N, T, V, Vector{V}}( + cat([[cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hr] for i in 1:N]...; dims=1) + ) + ) + # CPML memory variables + addfield!(grid, "ψ" => MultiVariableField{N, T, A, Vector{A}}( + cat([[backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + )) + addfield!(grid, "ξ" => MultiVariableField{N, T, A, Vector{A}}( + cat([[backend.zeros([j == i ? halo : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + )) + if gradient + addfield!(grid, "ψ_adj" => MultiVariableField{N, T, A, Vector{A}}( + cat([[backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + )) + addfield!(grid, "ξ_adj" => MultiVariableField{N, T, A, Vector{A}}( + cat([[backend.zeros([j == i ? halo : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + )) end + # Initialize checkpointer + checkpointer = LinearCheckpointer( + nt, + check_freq === nothing ? 1 : check_freq, + filter(p -> p.first in ["pcur", "ψ", "ξ"], grid.fields), + ["pcur"]; + widths=Dict("pcur" => 2) + ) + # Save first two timesteps + savecheckpoint!(checkpointer, "pcur" => grid.fields["pold"], -1) + savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) + # Initialize snapshots array snapshots = (snapevery !== nothing ? [backend.zeros(ns...) for _ in 1:div(nt, snapevery)] : nothing) # Check infoevery @@ -139,25 +173,22 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T,N}, V <: AbstractVecto @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - return new{N,T,A,V}( - domainextent, - ns, - gridspacing, + new{N, T, A}( nt, dt, + grid, halo, rcoef, freetop, gradient, gradient ? adjoint_grid.totgrad_size : nothing, + smooth_radius, snapevery, snapshots, infoevery, matprop, cpmlcoeffs, - forward_grid, - gradient ? adjoint_grid : nothing, - gradient ? checkpointing : nothing, + checkpointer, parall ) end @@ -165,34 +196,24 @@ end ########################################################### +@views function find_nearest_grid_points(model::AcousticCDCPMLWaveSimul, positions::Matrix{<:Real})::Matrix{<:Int} + # source time functions + nsrcs = size(positions, 1) # number of sources + ncoos = size(positions, 2) # number of coordinates + # find nearest grid point for each source + idx_positions = zeros(Int, size(positions)) # sources positions (in grid points) + for s in 1:nsrcs + tmp = [positions[s, i] / model.grid.gridspacing[i] + 1 for i in 1:ncoos] + idx_positions[s, :] .= round.(Int, tmp, RoundNearestTiesUp) + end + return idx_positions +end + # Specific functions for AcousticCDCPMLWaveSimul @views function reset!(model::AcousticCDCPMLWaveSimul{N}) where {N} - forwad_grid = model.forward_grid - adjoint_grid = model.adjoint_grid - # Reset computational arrays - forwad_grid.pold .= 0.0 - forwad_grid.pcur .= 0.0 - forwad_grid.pnew .= 0.0 - for i in eachindex(forwad_grid.ψ) - forwad_grid.ψ[i] .= 0.0 - end - for i in eachindex(forwad_grid.ξ) - forwad_grid.ξ[i] .= 0.0 - end - # Reset gradient arrays - if model.gradient - adjoint_grid.curgrad .= 0.0 - adjoint_grid.adjold .= 0.0 - adjoint_grid.adjcur .= 0.0 - adjoint_grid.adjnew .= 0.0 - for i in eachindex(adjoint_grid.ψ_adj) - adjoint_grid.ψ_adj[i] .= 0.0 - end - for i in eachindex(adjoint_grid.ξ_adj) - adjoint_grid.ξ_adj[i] .= 0.0 - end - end + reset!(model.grid; except=["fact", "a_pml", "b_pml"]) + reset!(model.checkpointer) end ########################################################### @@ -216,6 +237,19 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() end end +function check_numerics( + model::AcousticVDStaggeredWaveSimul, + shot::Shot; + min_ppw::Integer=10 +) + # Check points per wavelength + vel_min = get_minimum_func(model)(model.matprop.vp) + h_max = maximum(model.gridspacing) + ppw = vel_min / shot.srcs.domfreq / h_max + @info "Points per wavelength: $(ppw)" + @assert ppw >= min_ppw "Not enough points per wavelengh!" +end + @views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" diff --git a/src/shot.jl b/src/shot.jl index 903816b..08868b0 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -33,4 +33,4 @@ end idx_positions[s, :] .= round.(Int, tmp, RoundNearestTiesUp) end return idx_positions -end +end \ No newline at end of file From 6f0f3372371aa59102a7a9eab845503269cc126b Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 17 Jun 2024 11:54:28 +0200 Subject: [PATCH 040/111] First overhaul (tests passing) --- src/grids/checkpointers.jl | 9 ++++++--- src/grids/fields.jl | 4 ++-- src/models/acoustic/acou_gradient.jl | 28 ++++++++++++++-------------- src/models/acoustic/acou_init_bc.jl | 28 +++++++++++++++++++++++++++- src/models/acoustic/acou_models.jl | 16 ++++++++-------- 5 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/grids/checkpointers.jl b/src/grids/checkpointers.jl index 25d8e2a..07edcb3 100644 --- a/src/grids/checkpointers.jl +++ b/src/grids/checkpointers.jl @@ -50,7 +50,7 @@ function savecheckpoint!(checkpointer::LinearCheckpointer{N,T}, field::Pair{Stri end end # Start populating buffer at last checkpoint - if it >= checkpointer.last_checkpoint + if haskey(checkpointer.buffers, field.first) && it >= checkpointer.last_checkpoint copyto!(checkpointer.buffers[field.first][it - checkpointer.last_checkpoint + 1], field.second) end end @@ -92,11 +92,14 @@ function initrecover!(checkpointer::LinearCheckpointer{N,T}) where {N,T} copyto!(buffer[end], checkpointer.checkpoints[old_checkpoint][name]) end end + function recover!(checkpointer::LinearCheckpointer{N,T}, recoverfun) where {N,T} - for it in (checkpointer.curr_checkpoint+1):(old_checkpoint-1) + start_rec_it = checkpointer.curr_checkpoint + 1 + end_rec_it = checkpointer.curr_checkpoint + checkpointer.check_freq - 1 + for it in start_rec_it:end_rec_it recovered_fields = recoverfun(it) for (name, field) in recovered_fields - copyto!(buffer[name][it - (checkpointer.curr_checkpoint+1) + 2], field) + copyto!(checkpointer.buffers[name][it - start_rec_it + 2], field) end end end diff --git a/src/grids/fields.jl b/src/grids/fields.jl index f184f9a..c8e3b57 100644 --- a/src/grids/fields.jl +++ b/src/grids/fields.jl @@ -2,7 +2,7 @@ struct ScalarConstantField{N, T} <: AbstractField{N, T} value::T end -struct ScalarVariableField{N, T, A <: AbstractArray{T}} <: AbstractField{N, T} +mutable struct ScalarVariableField{N, T, A <: AbstractArray{T}} <: AbstractField{N, T} value::A end @@ -10,7 +10,7 @@ struct MultiConstantField{N, T, V <: AbstractArray{T}} <: AbstractField{N, T} value::V end -struct MultiVariableField{N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} <: AbstractField{N, T} +mutable struct MultiVariableField{N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} <: AbstractField{N, T} value::V end diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 97cb132..0332674 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -36,10 +36,10 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # Forward time loop for it in 1:nt # Compute one forward step - pold, pcur, pnew = backend.forward_onestep_CPML!( - pold, pcur, pnew, grid.fields["fact"].value, - wavsim.grid.gridspacing..., wavsim.halo, - grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value, grid.fields["b_pml"].value..., + grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value = backend.forward_onestep_CPML!( + grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value, grid.fields["fact"].value, + model.grid.gridspacing..., model.halo, + grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it ) # Print timestep info @@ -47,7 +47,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @info @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) end # Save checkpoint - savecheckpoint!(checkpointer, "pcur" => pcur, it) + savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], it) savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], it) savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], it) end @@ -59,7 +59,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = residuals_bk = backend.Data.Array(dχ_du(misfit, shot.recs)) # Prescale residuals (fact = vel^2 * dt^2) - backend.prescale_residuals!(residuals_bk, posrecs_bk, grid.fields["fact"]) + backend.prescale_residuals!(residuals_bk, posrecs_bk, grid.fields["fact"].value) @debug "Computing gradients" # Adjoint time loop (backward in time) @@ -80,19 +80,19 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = if !issaved(checkpointer, "pcur", it-2) @debug @sprintf("Out of save buffer at iteration: %d", it) initrecover!(checkpointer) - copyto!(pold, getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint - 1).value) - copyto!(pcur, getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint).value) + copyto!(grid.fields["pold"], getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint - 1)) + copyto!(grid.fields["pcur"], getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint)) copyto!(grid.fields["ψ"], getsaved(checkpointer, "ψ", checkpointer.curr_checkpoint)) copyto!(grid.fields["ξ"], getsaved(checkpointer, "ξ", checkpointer.curr_checkpoint)) - recoverbuffer!(checkpointer, recit -> begin - _, recovered_pcur, _ = backend.forward_onestep_CPML!( - pold, pcur, pnew, grid.fields["fact"].value, - wavsim.grid.gridspacing..., wavsim.halo, - grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value, grid.fields["b_pml"].value..., + recover!(checkpointer, recit -> begin + grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value = backend.forward_onestep_CPML!( + grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value, grid.fields["fact"].value, + model.grid.gridspacing..., model.halo, + grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false ) - return recovered_pcur + return ["pcur" => grid.fields["pcur"]] end) end # Get pressure fields from saved buffer diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index 72b1f07..e738138 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -17,7 +17,7 @@ init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimul, srcs::Sources model.dt, model.halo, model.rcoef, - model.grid.gridspacing[n] * model.halo, + model.gridspacing[n] * model.halo, srcs.domfreq ) end @@ -29,3 +29,29 @@ init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimul, srcs::Sources model.cpmlcoeffs[N].b_hl .= 1.0 end end + +@views function init_bdc!( + ::CPMLBoundaryCondition, + model::AcousticCDCPMLWaveSimul, + srcs::Sources +) + N = length(model.cpmlcoeffs) + for n in 1:N + compute_CPML_coefficients!( + model.cpmlcoeffs[n], + get_maximum_func(model)(model.matprop.vp), + model.dt, + model.halo, + model.rcoef, + model.grid.gridspacing[n] * model.halo, + srcs.domfreq + ) + end + + if model.freetop && N >= 1 + model.cpmlcoeffs[N].a_l .= 0.0 + model.cpmlcoeffs[N].a_hl .= 0.0 + model.cpmlcoeffs[N].b_l .= 1.0 + model.cpmlcoeffs[N].b_hl .= 1.0 + end +end \ No newline at end of file diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index a321aca..6b8017d 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -127,28 +127,28 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWave addfield!( grid, "a_pml" => MultiVariableField{N, T, V, Vector{V}}( - cat([[cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hr] for i in 1:N]...; dims=1) + cat([[cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr] for i in 1:N]...; dims=1) ) ) addfield!( grid, "b_pml" => MultiVariableField{N, T, V, Vector{V}}( - cat([[cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hr] for i in 1:N]...; dims=1) + cat([[cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr] for i in 1:N]...; dims=1) ) ) # CPML memory variables addfield!(grid, "ψ" => MultiVariableField{N, T, A, Vector{A}}( - cat([[backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) )) addfield!(grid, "ξ" => MultiVariableField{N, T, A, Vector{A}}( - cat([[backend.zeros([j == i ? halo : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros([j == i ? halo : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) )) if gradient addfield!(grid, "ψ_adj" => MultiVariableField{N, T, A, Vector{A}}( - cat([[backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) )) addfield!(grid, "ξ_adj" => MultiVariableField{N, T, A, Vector{A}}( - cat([[backend.zeros([j == i ? halo : ns[i] for j in 1:N]...), backend.zeros([j == i ? halo : ns[i] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros([j == i ? halo : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) )) end @@ -181,7 +181,7 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWave rcoef, freetop, gradient, - gradient ? adjoint_grid.totgrad_size : nothing, + gradient ? [ns...] : nothing, smooth_radius, snapevery, snapshots, @@ -295,7 +295,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} freetop::Bool # Gradient computation setup gradient::Bool - totgrad_size::Union{Vector{<:Integer}, Nothing} + totgrad_size::Union{Vector{Int}, Nothing} check_freq::Union{<:Integer, Nothing} # Snapshots snapevery::Union{<:Integer, Nothing} From 41f425c0ef8701b8c051691b78c72ba070a44b86 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 17 Jun 2024 12:13:58 +0200 Subject: [PATCH 041/111] Preparing to test FD gradient (constant density) --- .../constant_density/gradient_check_fd.jl | 59 ++++++++++--------- examples/plotting_utils.jl | 2 +- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index 4cf9375..de3f3b7 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -5,8 +5,8 @@ using LinearAlgebra ################################################################### using Logging using Plots - using CUDA + using Serialization info_logger = ConsoleLogger(stderr, Logging.Info) @@ -34,7 +34,7 @@ function setup(nt, c0, c0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) ##======================================== # shots definition nshots = 10 - f0 = 10 + f0 = 10.0 t0 = 4 / f0 srctf = 1000.0 .* rickerstf.(t, t0, f0) dd = 60 @@ -60,12 +60,12 @@ function setup(nt, c0, c0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], boundcond) # Wave simulation builder - wavesim = build_wavesim(params, matprop_const; gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt))) + wavesim = build_wavesim(params, matprop_const; smooth_radius=0, gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt))) return wavesim, shots, matprop_const, matprop_gauss end -function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) +function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss; compute_fd=true) println("Computing forward solver") # compute forward gaussian @@ -74,7 +74,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) end # new receivers with observed seismograms - shots_obs = Vector{Shot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() + shots_obs = Vector{Shot}() #Pair{ScalarSources, ScalarReceivers}}() for i in eachindex(shots) # receivers definition recs = ScalarReceivers( @@ -93,37 +93,39 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) gradient, misfit = with_logger(error_logger) do swgradient!(wavesim, matprop_const, shots_obs; compute_misfit=true) end + # save current gradient into file + serialize("adjgrad.dat", gradient) println("Initial misfit: $misfit") - # Compute gradient with finite differences - fd_gradient = zeros(nx, ny) - dm = -1e-3 - for i in 1:nx - for j in 1:ny - println("Computing ($i, $j) gradient with FD") - vp_perturbed = copy(matprop_const.vp) - vp_perturbed[i, j] += dm - matprop_perturbed = VpAcousticCDMaterialProperties(vp_perturbed) - @time new_misfit = with_logger(error_logger) do - swmisfit!(wavesim, matprop_perturbed, shots_obs) + if compute_fd + # Compute gradient with finite differences + fd_gradient = zeros(nx, ny) + dm = -1e-3 + for i in 1:nx + for j in 1:ny + println("Computing ($i, $j) gradient with FD") + vp_perturbed = copy(matprop_const.vp) + vp_perturbed[i, j] += dm + matprop_perturbed = VpAcousticCDMaterialProperties(vp_perturbed) + @time new_misfit = with_logger(error_logger) do + swmisfit!(wavesim, matprop_perturbed, shots_obs) + end + println("New misfit: $new_misfit") + fd_gradient[i, j] = (new_misfit - misfit) / dm end - println("New misfit: $new_misfit") - fd_gradient[i, j] = (new_misfit - misfit) / dm end + # save FD gradient into file + serialize("fdgrad.dat", fd_gradient) end - - # save FD gradient into file - serialize("fdgrad.dat", fd_gradient) - serialize("fdgrad_diff.dat", fd_gradient .- gradient) end function load_gradients() # deserialize saved gradients + grad = deserialize("adjgrad.dat") fdgrad = deserialize("fdgrad.dat") - fdgrad_diff = deserialize("fdgrad_diff.dat") - grad = fdgrad .- fdgrad_diff - return grad, fdgrad, -fdgrad_diff + fdgrad_diff = fdgrad .- grad + return grad, fdgrad, fdgrad_diff end ######################################################################## @@ -142,7 +144,6 @@ if length(ARGS) >= 1 @show device() end end -run = "--run" in ARGS # Numerical parameters nt = 1000 @@ -160,14 +161,14 @@ ly = (ny - 1) * dy # setup wavesim, shots, matprop_const, matprop_gauss = setup(nt, c0, c0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) -if run - gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) -end +gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss; compute_fd=true) # load saved results adjgrad, fdgrad, grad_diff = load_gradients() ################################################################## +# Plotting + corner1 = 21 corner2 = round(Int, 300 ÷ dx) l = @layout([A B C]) diff --git a/examples/plotting_utils.jl b/examples/plotting_utils.jl index 52d28c6..c0295be 100644 --- a/examples/plotting_utils.jl +++ b/examples/plotting_utils.jl @@ -1,5 +1,5 @@ using Plots, Plots.Measures -pyplot() +# pyplot() function plot_nice_heatmap(A; lx=size(A, 1), ly=size(A, 2), dx=1, dy=1, shift=0) heatmap( From efeae1faa84bbe0d557647bad3b5f85448861097 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 1 Jul 2024 13:41:22 +0200 Subject: [PATCH 042/111] Finish structure of Grid, Fields and Checkpointer --- src/grids/abstract_types.jl | 4 +- src/grids/checkpointers.jl | 48 ++++++++++++------------ src/grids/fields.jl | 42 +++++++++++++-------- src/grids/grids.jl | 11 +++--- src/models/acoustic/acou_gradient.jl | 29 +++++++------- src/models/acoustic/acou_models.jl | 56 +++++++++++++++++----------- 6 files changed, 107 insertions(+), 83 deletions(-) diff --git a/src/grids/abstract_types.jl b/src/grids/abstract_types.jl index f60a902..42bbcfe 100644 --- a/src/grids/abstract_types.jl +++ b/src/grids/abstract_types.jl @@ -1,5 +1,5 @@ -abstract type AbstractField{N, T} end +abstract type AbstractField{T} end abstract type AbstractGrid{N, T} end -abstract type AbstractCheckpointer{N, T} end \ No newline at end of file +abstract type AbstractCheckpointer{T} end \ No newline at end of file diff --git a/src/grids/checkpointers.jl b/src/grids/checkpointers.jl index 07edcb3..bf2b365 100644 --- a/src/grids/checkpointers.jl +++ b/src/grids/checkpointers.jl @@ -1,24 +1,24 @@ -mutable struct LinearCheckpointer{N, T} <: AbstractCheckpointer{N, T} +mutable struct LinearCheckpointer{T} <: AbstractCheckpointer{T} nt::Int check_freq::Int last_checkpoint::Int curr_checkpoint::Int - buffers::Dict{String, Vector{<:AbstractField{N, T}}} - checkpoints::Dict{Int, Dict{String, <:AbstractField{N, T}}} + buffers::Dict{String, Vector{<:AbstractField{T}}} + checkpoints::Dict{Int, Dict{String, <:AbstractField{T}}} widths::Dict{String, Int} function LinearCheckpointer( nt::Int, check_freq::Int, - checkpointed_fields::Dict{String, <:AbstractField{N, T}}, + checkpointed_fields::Dict{String, <:AbstractField{T}}, buffered_fields::Vector{String}; widths::Dict{String, Int}=Dict() - ) where {N, T} + ) where {T} @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" # Time step of last checkpoint last_checkpoint = floor(Int, nt / check_freq) * check_freq # Preallocate checkpoints - checkpoints = Dict{Int, Dict{String, AbstractField{N,T}}}() + checkpoints = Dict{Int, Dict{String, AbstractField{T}}}() for it in 0:(nt+1) if it % check_freq == 0 for (name, field) in checkpointed_fields @@ -27,21 +27,21 @@ mutable struct LinearCheckpointer{N, T} <: AbstractCheckpointer{N, T} if !haskey(checkpoints, itw) checkpoints[itw] = Dict() end - checkpoints[itw][name] = deepcopy(field) + checkpoints[itw][name] = zero(field) end end end end # Preallocate buffers - buffers = Dict{String, Vector{AbstractField{N, T}}}() + buffers = Dict{String, Vector{AbstractField{T}}}() for name in buffered_fields - buffers[name] = [deepcopy(checkpointed_fields[name]) for _ in 1:check_freq+1] + buffers[name] = [zero(checkpointed_fields[name]) for _ in 1:check_freq+1] end - new{N,T}(nt, check_freq, last_checkpoint, last_checkpoint, buffers, checkpoints, widths) + new{T}(nt, check_freq, last_checkpoint, last_checkpoint, buffers, checkpoints, widths) end end -function savecheckpoint!(checkpointer::LinearCheckpointer{N,T}, field::Pair{String, <:AbstractField{N,T}}, it::Int) where {N,T} +function savecheckpoint!(checkpointer::LinearCheckpointer{T}, field::Pair{String, <:AbstractField{T}}, it::Int) where {T} # Save field in checkpoints w = haskey(checkpointer.widths, field.first) ? checkpointer.widths[field.first] : 1 for itw in it:it+w-1 @@ -51,40 +51,40 @@ function savecheckpoint!(checkpointer::LinearCheckpointer{N,T}, field::Pair{Stri end # Start populating buffer at last checkpoint if haskey(checkpointer.buffers, field.first) && it >= checkpointer.last_checkpoint - copyto!(checkpointer.buffers[field.first][it - checkpointer.last_checkpoint + 1], field.second) + copyto!(checkpointer.buffers[field.first][it-checkpointer.last_checkpoint+1], field.second) end end -function isbuffered(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::Bool where {N,T} +function isbuffered(checkpointer::LinearCheckpointer, field::String, it::Int)::Bool return haskey(checkpointer.buffers, field) && (checkpointer.curr_checkpoint <= it <= checkpointer.curr_checkpoint + checkpointer.check_freq) end -function getbuffered(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::AbstractField{N,T} where {N,T} +function getbuffered(checkpointer::LinearCheckpointer, field::String, it::Int)::AbstractField @assert isbuffered(checkpointer, field, it) - return checkpointer.buffers[field][it - checkpointer.curr_checkpoint + 1] + return checkpointer.buffers[field][it-checkpointer.curr_checkpoint+1] end -function ischeckpointed(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::Bool where {N,T} +function ischeckpointed(checkpointer::LinearCheckpointer, field::String, it::Int)::Bool return haskey(checkpointer.checkpoints, it) && haskey(checkpointer.checkpoints[it], field) end -function getcheckpointed(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::AbstractField{N,T} where {N,T} +function getcheckpointed(checkpointer::LinearCheckpointer{T}, field::String, it::Int)::AbstractField{T} where {T} @assert ischeckpointed(checkpointer, field, it) return checkpointer.checkpoints[it][field] end -function issaved(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::Bool where {N,T} +function issaved(checkpointer::LinearCheckpointer, field::String, it::Int)::Bool return isbuffered(checkpointer, field, it) || ischeckpointed(checkpointer, field, it) end -function getsaved(checkpointer::LinearCheckpointer{N,T}, field::String, it::Int)::AbstractField{N,T} where {N,T} +function getsaved(checkpointer::LinearCheckpointer{T}, field::String, it::Int)::AbstractField{T} where {T} if ischeckpointed(checkpointer, field, it) return getcheckpointed(checkpointer, field, it) end return getbuffered(checkpointer, field, it) end -function initrecover!(checkpointer::LinearCheckpointer{N,T}) where {N,T} +function initrecover!(checkpointer::LinearCheckpointer) old_checkpoint = checkpointer.curr_checkpoint checkpointer.curr_checkpoint -= checkpointer.check_freq for (name, buffer) in checkpointer.buffers @@ -93,17 +93,15 @@ function initrecover!(checkpointer::LinearCheckpointer{N,T}) where {N,T} end end -function recover!(checkpointer::LinearCheckpointer{N,T}, recoverfun) where {N,T} +function recover!(checkpointer::LinearCheckpointer, recoverfun) start_rec_it = checkpointer.curr_checkpoint + 1 end_rec_it = checkpointer.curr_checkpoint + checkpointer.check_freq - 1 for it in start_rec_it:end_rec_it recovered_fields = recoverfun(it) for (name, field) in recovered_fields - copyto!(checkpointer.buffers[name][it - start_rec_it + 2], field) + copyto!(checkpointer.buffers[name][it-start_rec_it+2], field) end end end -function reset!(checkpointer::LinearCheckpointer) - checkpointer.curr_checkpoint = checkpointer.last_checkpoint -end \ No newline at end of file +reset!(checkpointer::LinearCheckpointer) = checkpointer.curr_checkpoint = checkpointer.last_checkpoint \ No newline at end of file diff --git a/src/grids/fields.jl b/src/grids/fields.jl index c8e3b57..4c7da3a 100644 --- a/src/grids/fields.jl +++ b/src/grids/fields.jl @@ -1,35 +1,47 @@ -struct ScalarConstantField{N, T} <: AbstractField{N, T} +mutable struct ScalarConstantField{T} <: AbstractField{T} value::T end -mutable struct ScalarVariableField{N, T, A <: AbstractArray{T}} <: AbstractField{N, T} +mutable struct ScalarVariableField{T, N, A <: AbstractArray{T, N}} <: AbstractField{T} value::A end -struct MultiConstantField{N, T, V <: AbstractArray{T}} <: AbstractField{N, T} - value::V +mutable struct MultiConstantField{T, N} <: AbstractField{T} + value::Vector{T} + MultiConstantField(value::NTuple{N, T}) where {T, N} = new{T, N}(collect(value)) end -mutable struct MultiVariableField{N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} <: AbstractField{N, T} +mutable struct MultiVariableField{T, N, A <: AbstractArray{T, N}, V <: Vector{A}} <: AbstractField{T} value::V end -function SeismicWaves.copyto!(dest::ScalarVariableField{N, T, A}, src::ScalarConstantField{N, T}) where {N, T, A <: AbstractArray{T}} - dest.value .= src.value -end -SeismicWaves.copyto!(dest::ScalarVariableField{N, T, A}, src::ScalarVariableField{N, T, A}) where {N, T, A <: AbstractArray{T}} = copyto!(dest.value, src.value) -function SeismicWaves.copyto!(dest::MultiVariableField{N,T,A,V}, src::ScalarConstantField{N,T}) where {N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} +Base.copyto!(dest::ScalarConstantField, src::ScalarConstantField) = (dest.value = src.value) +Base.copyto!(dest::ScalarVariableField, src::Union{ScalarConstantField, ScalarVariableField}) = (dest.value .= src.value) +Base.copyto!(dest::MultiConstantField, src::Union{ScalarConstantField, MultiConstantField}) = (dest.value .= src.value) +Base.copyto!(dest::MultiVariableField, src::ScalarConstantField) = begin for vdest in dest.value vdest .= src.value end end -function SeismicWaves.copyto!(dest::MultiVariableField{N,T,A,V1}, src::MultiConstantField{N,T,V2}) where {N, T, A <: AbstractArray{T}, V1 <: AbstractArray{A}, V2 <: AbstractArray{T}} +Base.copyto!(dest::MultiVariableField, src::Union{MultiConstantField, MultiVariableField}) = begin for (vdest, vsrc) in zip(dest.value, src.value) vdest .= vsrc end end -function SeismicWaves.copyto!(dest::MultiVariableField{N,T,A,V}, src::MultiVariableField{N,T,A,V}) where {N, T, A <: AbstractArray{T}, V <: AbstractArray{A}} - for (vdest, vsrc) in zip(dest.value, src.value) - copyto!(vdest, vsrc) + +setzero!(field::ScalarConstantField{T}) where {T} = (field.value = zero(T); return field) +setzero!(field::MultiConstantField{T}) where {T} = (field.value .= zero(T); return field) +setzero!(field::ScalarVariableField{T}) where {T} = (field.value .= zero(T); return field) +setzero!(field::MultiVariableField{T}) where {T} = begin + for vfield in field.value + vfield .= zero(T) end -end \ No newline at end of file + return field +end + +Base.zero(::Type{ScalarConstantField{T}}) where {T} = ScalarConstantField(zero(T)) +Base.zero(::Type{MultiConstantField{T, N}}) where {T, N} = MultiConstantField(ntuple(_ -> zero(T), N)) +Base.zero(::ScalarConstantField{T}) where {T} = zero(ScalarConstantField{T}) +Base.zero(::MultiConstantField{T, N}) where {T, N} = zero(MultiConstantField{T, N}) +Base.zero(field::ScalarVariableField{T, N, A}) where {T, N, A} = ScalarVariableField(zero(field.value)) +Base.zero(field::MultiVariableField{T, N, A, V}) where {T, N, A, V} = MultiVariableField([zero(f) for f in field.value]) \ No newline at end of file diff --git a/src/grids/grids.jl b/src/grids/grids.jl index fa99811..6e28cec 100644 --- a/src/grids/grids.jl +++ b/src/grids/grids.jl @@ -2,7 +2,7 @@ struct UniformFiniteDifferenceGrid{N, T} <: AbstractGrid{N, T} domainextent::NTuple{N, T} ns::NTuple{N, Int} gridspacing::NTuple{N, T} - fields::Dict{String, AbstractField{N,T}} + fields::Dict{String, AbstractField{T}} function UniformFiniteDifferenceGrid( ns::NTuple{N, Int}, gridspacing::NTuple{N, T} @@ -16,7 +16,7 @@ struct UniformFiniteDifferenceGrid{N, T} <: AbstractGrid{N, T} end end -function addfield!(grid::UniformFiniteDifferenceGrid{N, T}, field::Pair{String, <:AbstractField{N,T}}) where {N, T} +function addfield!(grid::UniformFiniteDifferenceGrid{N, T}, field::Pair{String, <:AbstractField{T}}) where {N, T} name = field.first if !haskey(grid.fields, name) grid.fields[name] = field.second @@ -25,10 +25,9 @@ function addfield!(grid::UniformFiniteDifferenceGrid{N, T}, field::Pair{String, end end -function reset!(grid::UniformFiniteDifferenceGrid{N,T}; except::Vector{String}=[]) where {N,T} +reset!(grid::UniformFiniteDifferenceGrid{N, T}; except::Vector{String}=[]) where {N, T} = for (name, field) in grid.fields if !(name in except) - copyto!(field, ScalarConstantField{N,T}(0.0)) + setzero!(field) end - end -end \ No newline at end of file + end \ No newline at end of file diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 0332674..c00656e 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -77,27 +77,30 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @info @sprintf("Backward iteration: %d", it) end # Check if out of save buffer - if !issaved(checkpointer, "pcur", it-2) + if !issaved(checkpointer, "pcur", it - 2) @debug @sprintf("Out of save buffer at iteration: %d", it) initrecover!(checkpointer) copyto!(grid.fields["pold"], getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint - 1)) copyto!(grid.fields["pcur"], getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint)) copyto!(grid.fields["ψ"], getsaved(checkpointer, "ψ", checkpointer.curr_checkpoint)) copyto!(grid.fields["ξ"], getsaved(checkpointer, "ξ", checkpointer.curr_checkpoint)) - recover!(checkpointer, recit -> begin - grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value = backend.forward_onestep_CPML!( - grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value, grid.fields["fact"].value, - model.grid.gridspacing..., model.halo, - grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., - possrcs_bk, srctf_bk, nothing, nothing, recit; - save_trace=false - ) - return ["pcur" => grid.fields["pcur"]] - end) + recover!( + checkpointer, + recit -> begin + grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value = backend.forward_onestep_CPML!( + grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value, grid.fields["fact"].value, + model.grid.gridspacing..., model.halo, + grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., + possrcs_bk, srctf_bk, nothing, nothing, recit; + save_trace=false + ) + return ["pcur" => grid.fields["pcur"]] + end + ) end # Get pressure fields from saved buffer - pcur_corr = getsaved(checkpointer, "pcur", it-2).value - pold_corr = getsaved(checkpointer, "pcur", it-1).value + pcur_corr = getsaved(checkpointer, "pcur", it - 2).value + pold_corr = getsaved(checkpointer, "pcur", it - 1).value pveryold_corr = getsaved(checkpointer, "pcur", it).value # Correlate for gradient computation backend.correlate_gradient!(grid.fields["grad_vp"].value, adjcur, pcur_corr, pold_corr, pveryold_corr, model.dt) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 6b8017d..2a5fe99 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -73,7 +73,7 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWave # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} # Checkpointing setup - checkpointer::LinearCheckpointer{N, T} + checkpointer::LinearCheckpointer{T} # Parallelization type parall::Symbol @@ -113,43 +113,55 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWave cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, true) for _ in 1:N]...) # Populate computational grid - addfield!(grid, "fact" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) - addfield!(grid, "pold" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) - addfield!(grid, "pcur" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) - addfield!(grid, "pnew" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "fact" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "pold" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "pnew" => ScalarVariableField(backend.zeros(ns...))) if gradient - addfield!(grid, "grad_vp" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) - addfield!(grid, "adjold" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) - addfield!(grid, "adjcur" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) - addfield!(grid, "adjnew" => ScalarVariableField{N, T, A}(backend.zeros(ns...))) + addfield!(grid, "grad_vp" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "adjold" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "adjcur" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "adjnew" => ScalarVariableField(backend.zeros(ns...))) end # CPML coefficients addfield!( grid, - "a_pml" => MultiVariableField{N, T, V, Vector{V}}( + "a_pml" => MultiVariableField( cat([[cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr] for i in 1:N]...; dims=1) ) ) addfield!( grid, - "b_pml" => MultiVariableField{N, T, V, Vector{V}}( + "b_pml" => MultiVariableField( cat([[cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr] for i in 1:N]...; dims=1) ) ) # CPML memory variables - addfield!(grid, "ψ" => MultiVariableField{N, T, A, Vector{A}}( - cat([[backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) - )) - addfield!(grid, "ξ" => MultiVariableField{N, T, A, Vector{A}}( - cat([[backend.zeros([j == i ? halo : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) - )) - if gradient - addfield!(grid, "ψ_adj" => MultiVariableField{N, T, A, Vector{A}}( + addfield!( + grid, + "ψ" => MultiVariableField( cat([[backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) - )) - addfield!(grid, "ξ_adj" => MultiVariableField{N, T, A, Vector{A}}( + ) + ) + addfield!( + grid, + "ξ" => MultiVariableField( cat([[backend.zeros([j == i ? halo : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) - )) + ) + ) + if gradient + addfield!( + grid, + "ψ_adj" => MultiVariableField( + cat([[backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + ) + ) + addfield!( + grid, + "ξ_adj" => MultiVariableField( + cat([[backend.zeros([j == i ? halo : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + ) + ) end # Initialize checkpointer From c197c3f3ba79a23b750b29360e4ca05ad9ce65be Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 1 Jul 2024 15:33:16 +0200 Subject: [PATCH 043/111] Simplified grid passing --- src/models/acoustic/acou_forward.jl | 11 +- src/models/acoustic/acou_gradient.jl | 32 +----- .../backends/Acoustic1D_CD_CPML_Serial.jl | 65 ++++++++++-- .../backends/Acoustic2D_CD_CPML_Serial.jl | 73 +++++++++++-- .../backends/Acoustic3D_CD_CPML_Serial.jl | 81 ++++++++++++-- .../backends/shared/acoustic1D_xPU.jl | 64 +++++++++-- .../backends/shared/acoustic2D_xPU.jl | 79 ++++++++++++-- .../backends/shared/acoustic3D_xPU.jl | 100 ++++++++++++++++-- 8 files changed, 417 insertions(+), 88 deletions(-) diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index ffabb65..bf802f8 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -32,10 +32,6 @@ end grid = wavsim.grid backend = select_backend(typeof(wavsim), wavsim.parall) - # Pressure arrays - pold = grid.fields["pold"].value - pcur = grid.fields["pcur"].value - pnew = grid.fields["pnew"].value # Numerics nt = wavsim.nt # Wrap sources and receivers arrays @@ -49,12 +45,7 @@ end # Time loop for it in 1:nt # Compute one forward step - pold, pcur, pnew = backend.forward_onestep_CPML!( - pold, pcur, pnew, grid.fields["fact"].value, - wavsim.grid.gridspacing..., wavsim.halo, - grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., - possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it - ) + backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % wavsim.infoevery == 0 @info @sprintf( diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index c00656e..8ffa8cf 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -17,14 +17,6 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # Numerics nt = model.nt - # Initialize pressure and factors arrays - pold = grid.fields["pold"].value - pcur = grid.fields["pcur"].value - pnew = grid.fields["pnew"].value - # Initialize adjoint arrays - adjold = grid.fields["adjold"].value - adjcur = grid.fields["adjcur"].value - adjnew = grid.fields["adjnew"].value # Wrap sources and receivers arrays possrcs_bk = backend.Data.Array(possrcs) posrecs_bk = backend.Data.Array(posrecs) @@ -36,12 +28,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # Forward time loop for it in 1:nt # Compute one forward step - grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value = backend.forward_onestep_CPML!( - grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value, grid.fields["fact"].value, - model.grid.gridspacing..., model.halo, - grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., - possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it - ) + backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) @@ -65,11 +52,8 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step - adjold, adjcur, adjnew = backend.forward_onestep_CPML!( - adjold, adjcur, adjnew, grid.fields["fact"].value, - model.grid.gridspacing..., model.halo, - grid.fields["ψ_adj"].value..., grid.fields["ξ_adj"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., - posrecs_bk, residuals_bk, nothing, nothing, it; # adjoint sources positions are receivers + backend.adjoint_onestep_CPML!( + grid, posrecs_bk, residuals_bk, nothing, nothing, it; # adjoint sources positions are receivers save_trace=false ) # Print timestep info @@ -87,13 +71,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = recover!( checkpointer, recit -> begin - grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value = backend.forward_onestep_CPML!( - grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value, grid.fields["fact"].value, - model.grid.gridspacing..., model.halo, - grid.fields["ψ"].value..., grid.fields["ξ"].value..., grid.fields["a_pml"].value..., grid.fields["b_pml"].value..., - possrcs_bk, srctf_bk, nothing, nothing, recit; - save_trace=false - ) + backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false) return ["pcur" => grid.fields["pcur"]] end ) @@ -103,7 +81,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = pold_corr = getsaved(checkpointer, "pcur", it - 1).value pveryold_corr = getsaved(checkpointer, "pcur", it).value # Correlate for gradient computation - backend.correlate_gradient!(grid.fields["grad_vp"].value, adjcur, pcur_corr, pold_corr, pveryold_corr, model.dt) + backend.correlate_gradient!(grid.fields["grad_vp"].value, grid.fields["adjcur"].value, pcur_corr, pold_corr, pveryold_corr, model.dt) end # get gradient gradient = Array(grid.fields["grad_vp"].value) diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index d0df550..f321622 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -95,14 +95,20 @@ end end @views function forward_onestep_CPML!( - pold, pcur, pnew, fact, dx, - halo, ψ_l, ψ_r, ξ_l, ξ_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - possrcs, dt2srctf, posrecs, traces, it; + grid, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) - nx = length(pcur) + # Extract info from grid + nx = grid.ns[1] + dx = grid.gridspacing[1] + pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value + fact = grid.fields["fact"].value + ψ_l, ψ_r = grid.fields["ψ"].value + ξ_l, ξ_r = grid.fields["ξ"].value + a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / dx _dx2 = 1 / dx^2 @@ -120,7 +126,52 @@ end record_receivers!(pnew, traces, posrecs, it) end - return pcur, pnew, pold + # Exchange pressures in grid + grid.fields["pold"] = grid.fields["pcur"] + grid.fields["pcur"] = grid.fields["pnew"] + grid.fields["pnew"] = grid.fields["pold"] + + return nothing +end + +@views function adjoint_onestep_CPML!( + grid, possrcs, dt2srctf, posrecs, traces, it; + save_trace=true +) + # Extract info from grid + nx = grid.ns[1] + dx = grid.gridspacing[1] + pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value + fact = grid.fields["fact"].value + ψ_l, ψ_r = grid.fields["ψ_adj"].value + ξ_l, ξ_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions + _dx = 1 / dx + _dx2 = 1 / dx^2 + + update_ψ!(ψ_l, ψ_r, pcur, + halo, nx, _dx, + a_x_hl, a_x_hr, + b_x_hl, b_x_hr) + update_p_CPML!(pold, pcur, pnew, halo, fact, nx, _dx, _dx2, + ψ_l, ψ_r, + ξ_l, ξ_r, + a_x_l, a_x_r, + b_x_l, b_x_r) + inject_sources!(pnew, dt2srctf, possrcs, it) + if save_trace + record_receivers!(pnew, traces, posrecs, it) + end + + # Exchange pressures in grid + grid.fields["adjold"] = grid.fields["adjcur"] + grid.fields["adjcur"] = grid.fields["adjnew"] + grid.fields["adjnew"] = grid.fields["adjold"] + + return nothing end function correlate_gradient!(curgrad, adjcur, pcur, pold, pveryold, dt) diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl index c7533be..365f0af 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl @@ -111,17 +111,66 @@ prescale_residuals!(residuals, posrecs, fact) = end function forward_onestep_CPML!( - pold, pcur, pnew, fact, dx, dy, halo, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - possrcs, dt2srctf, posrecs, traces, it; + grid, possrcs, dt2srctf, posrecs, traces, it; + save_trace=true +) + # Extract info from grid + nx, ny = grid.ns + dx, dy = grid.gridspacing + pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + _dx = 1 / dx + _dx2 = 1 / dx^2 + _dy = 1 / dy + _dy2 = 1 / dy^2 + + # update ψ arrays + update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + + update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) + + # update pressure and ξ arrays + update_p_CPML!(pold, pcur, pnew, halo, fact, + _dx, _dx2, _dy, _dy2, nx, ny, + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, + a_x_l, a_x_r, b_x_l, b_x_r, + a_y_l, a_y_r, b_y_l, b_y_r) + + # inject sources + inject_sources!(pnew, dt2srctf, possrcs, it) + # record receivers + if save_trace + record_receivers!(pnew, traces, posrecs, it) + end + + # Exchange pressures in grid + grid.fields["pold"] = grid.fields["pcur"] + grid.fields["pcur"] = grid.fields["pnew"] + grid.fields["pnew"] = grid.fields["pold"] + return nothing +end + +function adjoint_onestep_CPML!( + grid, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) - nx, ny = size(pcur) + # Extract info from grid + nx, ny = grid.ns + dx, dy = grid.gridspacing + pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / dx _dx2 = 1 / dx^2 _dy = 1 / dy @@ -147,7 +196,11 @@ function forward_onestep_CPML!( record_receivers!(pnew, traces, posrecs, it) end - return pcur, pnew, pold + # Exchange pressures in grid + grid.fields["adjold"] = grid.fields["adjcur"] + grid.fields["adjcur"] = grid.fields["adjnew"] + grid.fields["adjnew"] = grid.fields["adjold"] + return nothing end ######################################### diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl index c7ac424..6ca6ecd 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl @@ -155,19 +155,79 @@ prescale_residuals!(residuals, posrecs, fact) = end function forward_onestep_CPML!( - pold, pcur, pnew, fact, dx, dy, dz, halo, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r, + grid, possrcs, dt2srctf, posrecs, traces, it; + save_trace=true +) + # Extract info from grid + nx, ny, nz = grid.ns + dx, dy, dz = grid.gridspacing + pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ"].value a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr, - a_z_l, a_z_r, a_z_hl, a_z_hr, + a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr, - b_z_l, b_z_r, b_z_hl, b_z_hr, - possrcs, dt2srctf, posrecs, traces, it; + b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions + _dx = 1 / dx + _dx2 = 1 / dx^2 + _dy = 1 / dy + _dy2 = 1 / dy^2 + _dz = 1 / dz + _dz2 = 1 / dz^2 + + # update ψ arrays + update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) + update_ψ_z!(ψ_z_l, ψ_z_r, pcur, halo, _dz, nz, a_z_hl, a_z_hr, b_z_hl, b_z_hr) + + # update presure and ξ arrays + update_p_CPML!(pold, pcur, pnew, halo, fact, + _dx, _dx2, _dy, _dy2, _dz, _dz2, nx, ny, nz, + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r, + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r, + a_x_l, a_x_r, b_x_l, b_x_r, + a_y_l, a_y_r, b_y_l, b_y_r, + a_z_l, a_z_r, b_z_l, b_z_r) + + # inject sources + inject_sources!(pnew, dt2srctf, possrcs, it) + # record receivers + if save_trace + record_receivers!(pnew, traces, posrecs, it) + end + + # Exchange pressures in grid + grid.fields["pold"] = grid.fields["pcur"] + grid.fields["pcur"] = grid.fields["pnew"] + grid.fields["pnew"] = grid.fields["pold"] + + return nothing +end + +function adjoint_onestep_CPML!( + grid, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) - nx, ny, nz = size(pcur) + # Extract info from grid + nx, ny, nz = grid.ns + dx, dy, dz = grid.gridspacing + pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ_adj"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, + a_y_l, a_y_r, a_y_hl, a_y_hr, + a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, + b_y_l, b_y_r, b_y_hl, b_y_hr, + b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / dx _dx2 = 1 / dx^2 _dy = 1 / dy @@ -196,7 +256,12 @@ function forward_onestep_CPML!( record_receivers!(pnew, traces, posrecs, it) end - return pcur, pnew, pold + # Exchange pressures in grid + grid.fields["adjold"] = grid.fields["adjcur"] + grid.fields["adjcur"] = grid.fields["adjnew"] + grid.fields["adjnew"] = grid.fields["adjold"] + + return nothing end ######################################### diff --git a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl index 520de09..92561bc 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl @@ -95,14 +95,20 @@ end end @views function forward_onestep_CPML!( - pold, pcur, pnew, fact, dx, halo, - ψ_l, ψ_r, ξ_l, ξ_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - possrcs, dt2srctf, posrecs, traces, it; + grid, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) - nx = length(pcur) + # Extract info from grid + nx = grid.ns[1] + dx = grid.gridspacing[1] + pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value + fact = grid.fields["fact"].value + ψ_l, ψ_r = grid.fields["ψ"].value + ξ_l, ξ_r = grid.fields["ξ"].value + a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / dx _dx2 = 1 / dx^2 @@ -120,5 +126,49 @@ end @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) end - return pcur, pnew, pold + # Exchange pressures in grid + grid.fields["pold"] = grid.fields["pcur"] + grid.fields["pcur"] = grid.fields["pnew"] + grid.fields["pnew"] = grid.fields["pold"] + return nothing +end + +@views function adjoint_onestep_CPML!( + grid, possrcs, dt2srctf, posrecs, traces, it; + save_trace=true +) + # Extract info from grid + nx = grid.ns[1] + dx = grid.gridspacing[1] + pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value + fact = grid.fields["fact"].value + ψ_l, ψ_r = grid.fields["ψ_adj"].value + ξ_l, ξ_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions + _dx = 1 / dx + _dx2 = 1 / dx^2 + + @parallel (1:(halo+1)) update_ψ!(ψ_l, ψ_r, pcur, + halo, nx, _dx, + a_x_hl, a_x_hr, + b_x_hl, b_x_hr) + @parallel (2:(nx-1)) update_p_CPML!(pold, pcur, pnew, halo, fact, nx, _dx, _dx2, + ψ_l, ψ_r, + ξ_l, ξ_r, + a_x_l, a_x_r, + b_x_l, b_x_r) + @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) + if save_trace + @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) + end + + # Exchange pressures in grid + grid.fields["adjold"] = grid.fields["adjcur"] + grid.fields["adjcur"] = grid.fields["adjnew"] + grid.fields["adjnew"] = grid.fields["adjold"] + + return nothing end diff --git a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl index 1f72775..0ac6c7e 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl @@ -105,17 +105,19 @@ end end @views function forward_onestep_CPML!( - pold, pcur, pnew, fact, dx, dy, halo, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - possrcs, dt2srctf, posrecs, traces, it; + grid, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) - nx, ny = size(pcur) + # Extract info from grid + nx, ny = grid.ns + dx, dy = grid.gridspacing + pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value + halo = length(a_x_r) _dx = 1 / dx _dx2 = 1 / dx^2 _dy = 1 / dy @@ -147,5 +149,62 @@ end @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) end - return pcur, pnew, pold + # Exchange pressures in grid + grid.fields["pold"] = grid.fields["pcur"] + grid.fields["pcur"] = grid.fields["pnew"] + grid.fields["pnew"] = grid.fields["pold"] + return nothing +end + +@views function adjoint_onestep_CPML!( + grid, possrcs, dt2srctf, posrecs, traces, it; + save_trace=true +) + # Extract info from grid + nx, ny = grid.ns + dx, dy = grid.gridspacing + pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions + _dx = 1 / dx + _dx2 = 1 / dx^2 + _dy = 1 / dy + _dy2 = 1 / dy^2 + + # update ψ arrays + @parallel_async (1:(halo+1), 1:ny) update_ψ_x!(ψ_x_l, ψ_x_r, pcur, + halo, _dx, nx, + a_x_hl, a_x_hr, + b_x_hl, b_x_hr) + @parallel_async (1:nx, 1:(halo+1)) update_ψ_y!(ψ_y_l, ψ_y_r, pcur, + halo, _dy, ny, + a_y_hl, a_y_hr, + b_y_hl, b_y_hr) + @synchronize + + # update pressure and ξ arrays + @parallel (2:(nx-1), 2:(ny-1)) update_p_CPML!(pold, pcur, pnew, halo, fact, + _dx, _dx2, _dy, _dy2, nx, ny, + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, + a_x_l, a_x_r, b_x_l, b_x_r, + a_y_l, a_y_r, b_y_l, b_y_r) + + # inject sources + @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) + # record receivers + if save_trace + @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) + end + + # Exchange pressures in grid + grid.fields["adjold"] = grid.fields["adjcur"] + grid.fields["adjcur"] = grid.fields["adjnew"] + grid.fields["adjnew"] = grid.fields["adjold"] + return nothing end diff --git a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl index 91e3c81..fd8909c 100644 --- a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl @@ -142,19 +142,96 @@ end end @views function forward_onestep_CPML!( - pold, pcur, pnew, fact, dx, dy, dz, halo, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r, + grid, possrcs, dt2srctf, posrecs, traces, it; + save_trace=true +) + # Extract info from grid + nx, ny, nz = grid.ns + dx, dy, dz = grid.gridspacing + pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ"].value a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr, - a_z_l, a_z_r, a_z_hl, a_z_hr, + a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr, - b_z_l, b_z_r, b_z_hl, b_z_hr, - possrcs, dt2srctf, posrecs, traces, it; + b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions + _dx = 1 / dx + _dx2 = 1 / dx^2 + _dy = 1 / dy + _dy2 = 1 / dy^2 + _dz = 1 / dz + _dz2 = 1 / dz^2 + + # update ψ arrays + @parallel_async (1:(halo+1), 1:ny, 1:nz) update_ψ_x!(ψ_x_l, ψ_x_r, pcur, + halo, _dx, nx, + a_x_hl, a_x_hr, + b_x_hl, b_x_hr) + @parallel_async (1:nx, 1:(halo+1), 1:nz) update_ψ_y!(ψ_y_l, ψ_y_r, pcur, + halo, _dy, ny, + a_y_hl, a_y_hr, + b_y_hl, b_y_hr) + @parallel_async (1:nx, 1:ny, 1:(halo+1)) update_ψ_z!(ψ_z_l, ψ_z_r, pcur, + halo, _dz, nz, + a_z_hl, a_z_hr, + b_z_hl, b_z_hr) + @synchronize + + # update presure and ξ arrays + @parallel (2:(nx-1), 2:(ny-1), 2:(nz-1)) update_p_CPML!(pold, pcur, pnew, halo, + fact, + _dx, _dx2, _dy, _dy2, _dz, + _dz2, nx, ny, nz, + ψ_x_l, ψ_x_r, ψ_y_l, + ψ_y_r, ψ_z_l, ψ_z_r, + ξ_x_l, ξ_x_r, ξ_y_l, + ξ_y_r, ξ_z_l, ξ_z_r, + a_x_l, a_x_r, b_x_l, + b_x_r, + a_y_l, a_y_r, b_y_l, + b_y_r, + a_z_l, a_z_r, b_z_l, + b_z_r) + + # inject sources + @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) + # record receivers + if save_trace + @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) + end + + # Exchange pressures in grid + grid.fields["pold"] = grid.fields["pcur"] + grid.fields["pcur"] = grid.fields["pnew"] + grid.fields["pnew"] = grid.fields["pold"] + + return nothing +end + +@views function adjoint_onestep_CPML!( + grid, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) - nx, ny, nz = size(pcur) + # Extract info from grid + nx, ny, nz = grid.ns + dx, dy, dz = grid.gridspacing + pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value + fact = grid.fields["fact"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ_adj"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, + a_y_l, a_y_r, a_y_hl, a_y_hr, + a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, + b_y_l, b_y_r, b_y_hl, b_y_hr, + b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / dx _dx2 = 1 / dx^2 _dy = 1 / dy @@ -200,5 +277,10 @@ end @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) end - return pcur, pnew, pold -end + # Exchange pressures in grid + grid.fields["adjold"] = grid.fields["adjcur"] + grid.fields["adjcur"] = grid.fields["adjnew"] + grid.fields["adjnew"] = grid.fields["adjold"] + + return nothing +end \ No newline at end of file From a4d9c078c5f86c4d273c5a312bde8acba457497e Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 1 Jul 2024 16:16:29 +0200 Subject: [PATCH 044/111] MatProps now depend on data type --- src/abstract_types.jl | 2 +- src/checks.jl | 6 +-- src/misfits.jl | 8 ++-- .../acoustic/acou_material_properties.jl | 40 +++++++------------ src/models/acoustic/acou_models.jl | 10 ++--- src/models/elastic/ela_abstract_types.jl | 4 +- src/models/elastic/ela_material_properties.jl | 30 +++++++------- src/solve.jl | 22 +++++----- src/utils.jl | 2 + src/wrappers.jl | 38 ++++++++++-------- 10 files changed, 80 insertions(+), 82 deletions(-) diff --git a/src/abstract_types.jl b/src/abstract_types.jl index e53c0e3..9e74dfe 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -10,7 +10,7 @@ abstract type InputParameters{N} end abstract type InputBoundaryConditionParameters end -abstract type MaterialProperties{N} end +abstract type MaterialProperties{T, N} end abstract type Sources end diff --git a/src/checks.jl b/src/checks.jl index 9e85b3f..a9de505 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -13,19 +13,19 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s # Check that the subtypes of WaveSimul, MaterialProperties and Shot are consistent N = typeof(wavsim).parameters[1] if wavsim isa AcousticCDCPMLWaveSimul{N} && - matprop isa VpAcousticCDMaterialProperties{N} && + matprop isa VpAcousticCDMaterialProperties{<:Real, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return elseif wavsim isa AcousticVDStaggeredCPMLWaveSimul{N} && - matprop isa VpRhoAcousticVDMaterialProperties{N} && + matprop isa VpRhoAcousticVDMaterialProperties{<:Real, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return elseif wavsim isa ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< - matprop isa ElasticIsoMaterialProperties{2} && + matprop isa ElasticIsoMaterialProperties{<:Real, 2} && tysource <: MomentTensorSources && tyreceiver <: VectorReceivers return diff --git a/src/misfits.jl b/src/misfits.jl index 620749e..0c77789 100644 --- a/src/misfits.jl +++ b/src/misfits.jl @@ -44,14 +44,14 @@ Base.@kwdef struct ZerothOrderTikhonovRegularization{M <: MaterialProperties} <: alpha::Real end -function (regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{N}})(matprop::VpAcousticCDMaterialProperties{N}) where {N} +function (regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{T, N}})(matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} vp = matprop.vp vp_prior = regularization.matprop_prior.vp vp_norm_sq = norm(vp - vp_prior)^2 return regularization.alpha / 2 * vp_norm_sq end -function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{N}})(matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} +function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{T, N}})(matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp @@ -61,13 +61,13 @@ function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMater return regularization.alpha / 2 * (vp_norm_sq + rho_norm_sq) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{N}}, matprop::VpAcousticCDMaterialProperties{N}) where {N} +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{T, N}}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} vp = matprop.vp vp_prior = regularization.matprop_prior.vp return regularization.alpha * (vp - vp_prior) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{N}}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{T, N}}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp diff --git a/src/models/acoustic/acou_material_properties.jl b/src/models/acoustic/acou_material_properties.jl index 51a0272..542c6bc 100644 --- a/src/models/acoustic/acou_material_properties.jl +++ b/src/models/acoustic/acou_material_properties.jl @@ -7,9 +7,9 @@ Material properties for acoustic constant-density simulation. $(TYPEDFIELDS) """ -struct VpAcousticCDMaterialProperties{N} <: MaterialProperties{N} +struct VpAcousticCDMaterialProperties{T, N} <: MaterialProperties{T, N} "P-wave velocity" - vp::Array{<:Float64, N} + vp::Array{T, N} end @doc """ @@ -19,38 +19,28 @@ Material properties for acoustic variable-density simulation. $(TYPEDFIELDS) """ -mutable struct VpRhoAcousticVDMaterialProperties{N} <: MaterialProperties{N} +mutable struct VpRhoAcousticVDMaterialProperties{T, N} <: MaterialProperties{T, N} "P-wave velocity" - vp::Array{<:Float64, N} + vp::Array{T, N} "Density" - rho::Array{<:Float64, N} + rho::Array{T, N} "Interpolation method" interp_method::InterpolationMethod @doc """ - VpRhoAcousticVDMaterialProperties{N}( - vp::Array{<:Float64, N}, - rho::Array{<:Float64, N}; + VpRhoAcousticVDMaterialProperties( + vp::Array{T, N}, + rho::Array{T, N}; interp_method::InterpolationMethod=ArithmeticAverageInterpolation(2) - ) where {N} + ) where {T, N} Constructor for material properties for acoustic variable-density simulation. """ - function VpRhoAcousticVDMaterialProperties{N}( - vp::Array{<:Float64, N}, - rho::Array{<:Float64, N}; + function VpRhoAcousticVDMaterialProperties( + vp::Array{T, N}, + rho::Array{T, N}; interp_method::InterpolationMethod=ArithmeticAverageInterpolation(2) - ) where {N} - return new(vp, rho, interp_method) + ) where {T, N} + return new{T, N}(vp, rho, interp_method) end -end - -@doc """ -$(SIGNATURES) - -Constructor to avoid specifying dimensions to create material properties for acoustic variable-density simulation. -""" -VpRhoAcousticVDMaterialProperties(vp, rho; kwargs...) = VpRhoAcousticVDMaterialProperties{length(size(vp))}(vp, rho; kwargs...) - -interpolate(a::Array{<:Float64, N}, interp_method) where {N} = collect(interp(interp_method, a, i) for i in 1:N) -interpolate_jacobian(a::Array{<:Float64, N}, interp_method) where {N} = collect(jacobian(interp_method, a, i) for i in 1:N) +end \ No newline at end of file diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 2a5fe99..3a77f34 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -29,7 +29,7 @@ end # Functions for all AcousticCDWaveSimul subtypes -@views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{N}) where {N} +@views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.ns)" @@ -38,7 +38,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{N}) where {N} +@views function update_matprop!(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) # Precompute factors @@ -262,7 +262,7 @@ function check_numerics( @assert ppw >= min_ppw "Not enough points per wavelengh!" end -@views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} +@views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == size(matprop.rho) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.ns)" @@ -272,7 +272,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{N}) where {N} +@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) copyto!(model.matprop.rho, matprop.rho) @@ -317,7 +317,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} # Gradient smoothing parameters smooth_radius::Integer # Material properties - matprop::VpRhoAcousticVDMaterialProperties{N} + matprop::VpRhoAcousticVDMaterialProperties # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} # Forward computation arrays diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index e615a87..7621d86 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -3,6 +3,6 @@ abstract type ElasticWaveSimul{N} <: WaveSimul{N} end abstract type ElasticIsoWaveSimul{N} <: ElasticWaveSimul{N} end -abstract type ElasticMaterialProperties{N} <: MaterialProperties{N} end +abstract type ElasticMaterialProperties{T, N} <: MaterialProperties{T, N} end -abstract type AbstrElasticIsoMaterialProperties{N} <: ElasticMaterialProperties{N} end +abstract type AbstrElasticIsoMaterialProperties{T, N} <: ElasticMaterialProperties{T, N} end diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index ca5f141..9171726 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -1,23 +1,23 @@ -Base.@kwdef struct ElasticIsoMaterialProperties{N} <: AbstrElasticIsoMaterialProperties{N} - λ::Array{<:AbstractFloat, N} - μ::Array{<:AbstractFloat, N} - ρ::Array{<:AbstractFloat, N} +Base.@kwdef struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIsoMaterialProperties{T, N} + λ::Array{T, N} + μ::Array{T, N} + ρ::Array{T, N} end # Material properties for 2D simulations -Base.@kwdef struct ElasticIsoMaterialProperties2D <: AbstrElasticIsoMaterialProperties{2} - λ::Array{<:AbstractFloat, 2} - μ::Array{<:AbstractFloat, 2} - ρ::Array{<:AbstractFloat, 2} - λ_ihalf::Array{<:AbstractFloat, 2} - μ_ihalf::Array{<:AbstractFloat, 2} - μ_jhalf::Array{<:AbstractFloat, 2} - ρ_ihalf_jhalf::Array{<:AbstractFloat, 2} +Base.@kwdef struct ElasticIsoMaterialProperties2D{T} <: AbstrElasticIsoMaterialProperties{T, 2} + λ::Array{T, 2} + μ::Array{T, 2} + ρ::Array{T, 2} + λ_ihalf::Array{T, 2} + μ_ihalf::Array{T, 2} + μ_jhalf::Array{T, 2} + ρ_ihalf_jhalf::Array{T, 2} - # function ElasticIsoMaterialProperties{N}(ρ::Array{<:AbstractFloat, N}, - # μ::Array{<:AbstractFloat, N}, - # λ::Array{<:AbstractFloat, N}) where {N} + # function ElasticIsoMaterialProperties{N}(ρ::Array{T, N}, + # μ::Array{T, N}, + # λ::Array{T, N}) where {N} # @assert ndims(λ)==2 # nx,ny = size(λ) diff --git a/src/solve.jl b/src/solve.jl index 6284274..e8305f8 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -1,6 +1,6 @@ ### UPDATE MATERIAL PROPERTIES ## -@views function set_wavesim_matprop!(wavesim::WaveSimul{N}, matprop::MaterialProperties{N}) where {N} +@views function set_wavesim_matprop!(wavesim::WaveSimul{N}, matprop::MaterialProperties{T, N}) where {T, N} @debug "Checking new material properties" check_matprop(wavesim, matprop) @debug "Updating WaveSimul material properties" @@ -12,9 +12,9 @@ end ## single WaveSimul object @views function run_swforward!( wavsim::WaveSimul{N}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; -)::Union{Vector{Array}, Nothing} where {N} +)::Union{Vector{Array}, Nothing} where {T, N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -57,9 +57,9 @@ end ## :threadpersrc, multiple WaveSimul objects @views function run_swforward!( wavsim::Vector{<:WaveSimul{N}}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; -)::Union{Vector{Array}, Nothing} where {N} +)::Union{Vector{Array}, Nothing} where {T, N} nwsim = length(wavsim) nthr = Threads.nthreads() # make sure the number of threads has not changed! @@ -116,10 +116,10 @@ end ## single or multiple WaveSimul objects @views function run_swmisfit!( wavsim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; misfit::AbstractMisfit=L2Misfit(nothing) -)::Real where {N} +)::T where {T, N} # Solve forward model for all shots run_swforward!(wavsim, matprop, shots) @@ -146,11 +146,11 @@ end ## single WaveSimul object @views function run_swgradient!( wavsim::WaveSimul{N}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) -)::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} +)::Union{Array{T}, Tuple{Array{T}, T}} where {T, N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -189,11 +189,11 @@ end ## :threadpersrc, multiple WaveSimul objects @views function run_swgradient!( wavsim::Vector{<:WaveSimul{N}}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) -)::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} +)::Union{Array{T}, Tuple{Array{T}, T}} where {T, N} nwsim = length(wavsim) nthr = Threads.nthreads() # make sure the number of threads has not changed! diff --git a/src/utils.jl b/src/utils.jl index a1ac5d2..ce92a45 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -23,6 +23,8 @@ struct ArithmeticAverageInterpolation <: InterpolationMethod width::Int end +interpolate(a::Array{T, N}, interp_method) where {T, N} = collect(interp(interp_method, a, i) for i in 1:N) + @views function interp(method::ArithmeticAverageInterpolation, a::Array{<:Real, N}, dim) where {N} return sum( a[CartesianIndices(Tuple(i == dim ? (j:size(a, i)+j-method.width) : (1:size(a, i)) for i in 1:N))] for j in 1:method.width diff --git a/src/wrappers.jl b/src/wrappers.jl index e7398b2..cfc422e 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -14,7 +14,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments - `params::InputParameters{N}`: input parameters for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). -- `matprop::MaterialProperties{N}`: material properties for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments @@ -28,13 +28,13 @@ See also [`Sources`](@ref), [`Receivers`](@ref). """ function swforward!( params::InputParameters{N}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; parall::Symbol=:threads, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, logger::Union{Nothing, AbstractLogger}=nothing -)::Union{Vector{AbstractArray}, Nothing} where {N} +)::Union{Vector{Array{T, N}}, Nothing} where {T, N} if logger === nothing logger = current_logger() end @@ -57,6 +57,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments - `wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -67,8 +69,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function swforward!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} +function swforward!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() end @@ -87,7 +89,7 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Positional arguments - `params::InputParameters{N}`: input parameters for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). -- `matprop::MaterialProperties{N}`: material properties for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments @@ -103,12 +105,12 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ function swmisfit!( params::InputParameters{N}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; #<:Pair{<:Sources{<:Real}, <:Receivers{<:Real}}}; parall::Symbol=:threads, misfit::AbstractMisfit=L2Misfit(nothing), logger::Union{Nothing, AbstractLogger}=nothing -)::Real where {N} +)::Real where {T, N} if logger === nothing logger = current_logger() end @@ -128,6 +130,8 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Positional arguments - `wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -140,8 +144,8 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ -function swmisfit!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} +function swmisfit!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() end @@ -168,7 +172,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Positional arguments - `params::InputParameters{N}`: input parameters for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). -- `matprop::MaterialProperties{N}`: material properties for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments @@ -185,7 +189,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi """ function swgradient!( params::InputParameters{N}, - matprop::MaterialProperties{N}, + matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; parall::Symbol=:threads, check_freq::Union{Int, Nothing}=nothing, @@ -194,7 +198,7 @@ function swgradient!( misfit::AbstractMisfit=L2Misfit(nothing), smooth_radius::Integer=5, logger::Union{Nothing, AbstractLogger}=nothing -)::Union{AbstractArray, Tuple{AbstractArray, Real}} where {N} +)::Union{AbstractArray, Tuple{AbstractArray, Real}} where {T, N} if logger === nothing logger = current_logger() end @@ -222,6 +226,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Positional arguments - `wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -235,8 +241,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `smooth_radius::Integer = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ -function swgradient!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{N}, shots::Vector{<:Shot}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {N} +function swgradient!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() end @@ -267,7 +273,7 @@ Builds a wave similation based on the input paramters `params` and keyword argum - `snapevery::Union{<:Integer, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). - `infoevery::Union{<:Integer, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function build_wavesim(params::InputParameters, matprop::MaterialProperties; parall::Symbol, kwargs...) +function build_wavesim(params::InputParameters{N}, matprop::MaterialProperties{T, N}; parall::Symbol, kwargs...) where {T, N} if parall == :threadpersrc nthr = Threads.nthreads() wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for _ in 1:nthr] From af5c062fff51011fa9fb120914a4d235e3003fad Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 1 Jul 2024 16:49:46 +0200 Subject: [PATCH 045/111] InputParameters now depend on data type --- examples/forward_example.jl | 2 +- .../constant_density/gradient_check_fd.jl | 2 +- .../variable_density/gradient_check_fd.jl | 2 +- examples/simple_example_acoustic.jl | 2 +- examples/simple_example_elastic.jl | 2 +- examples/simple_example_wavesim.jl | 2 +- ext/CUDABackendExt.jl | 6 +- src/abstract_types.jl | 2 +- src/checks.jl | 7 +- src/models/acoustic/acou_forward.jl | 8 +-- src/models/acoustic/acou_models.jl | 10 +-- src/models/acoustic/acou_params.jl | 69 ++++--------------- src/models/backend_selection.jl | 18 ++--- src/models/elastic/ela_params.jl | 36 +++++----- src/wrappers.jl | 30 ++++---- test/test_forward_constant_density.jl | 8 +-- test/utils/setup_models.jl | 10 +-- 17 files changed, 85 insertions(+), 131 deletions(-) diff --git a/examples/forward_example.jl b/examples/forward_example.jl index 9c1f57e..4b8373b 100644 --- a/examples/forward_example.jl +++ b/examples/forward_example.jl @@ -55,7 +55,7 @@ function forward_example() snapevery = 50 infoevery = 500 boundcond = CPMLBoundaryConditionParameters(; halo=20, rcoef=0.0001, freeboundtop=true) - params = InputParametersAcoustic(nt, dt, [nx, nz], [dh, dh], boundcond) + params = InputParametersAcoustic(nt, dt, (nx, nz), (dh, dh), boundcond) ## Show parameters dump(params) ##=============================================== diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index de3f3b7..23e5fe1 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -57,7 +57,7 @@ function setup(nt, c0, c0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) ##============================================ ## Input parameters for acoustic simulation boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false) - params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], boundcond) + params = InputParametersAcoustic(nt, dt, (nx, ny), (dx, dy), boundcond) # Wave simulation builder wavesim = build_wavesim(params, matprop_const; smooth_radius=0, gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt))) diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index 5a9b4c4..5b3995e 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -72,7 +72,7 @@ function setup(nt, c0, c0max, rho0, rho0max, r, dx, dy, dt, halo, rcoef, nx, ny, ##============================================ ## Input parameters for acoustic simulation boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false) - params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], boundcond) + params = InputParametersAcoustic(nt, dt, (nx, ny), (dx, dy), boundcond) # Wave simulation builder wavesim = build_wavesim(params, matprop_const; gradient=true, parall=parall, check_freq=ceil(Int, sqrt(nt)), smooth_radius=0) diff --git a/examples/simple_example_acoustic.jl b/examples/simple_example_acoustic.jl index 98266aa..00d7a9b 100644 --- a/examples/simple_example_acoustic.jl +++ b/examples/simple_example_acoustic.jl @@ -85,7 +85,7 @@ function exacouprob(parall=:serial) snapevery = 50 infoevery = 500 boundcond = CPMLBoundaryConditionParameters(; halo=20, rcoef=0.0001, freeboundtop=true) - params = InputParametersAcoustic(nt, dt, [nx, nz], [dh, dh], boundcond) + params = InputParametersAcoustic(nt, dt, (nx, nz), (dh, dh), boundcond) #@show (boundcond.halo-1)*dh ##=============================================== diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index b24cfdf..998aa82 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -120,7 +120,7 @@ function exelaprob() @show halo @show rcoef boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=freetop) - params = InputParametersElastic(nt, dt, [nx, nz], [dh, dh], boundcond) + params = InputParametersElastic(nt, dt, (nx, nz), (dh, dh), boundcond) ##=============================================== ## compute the seismograms diff --git a/examples/simple_example_wavesim.jl b/examples/simple_example_wavesim.jl index 2c35f95..9049253 100644 --- a/examples/simple_example_wavesim.jl +++ b/examples/simple_example_wavesim.jl @@ -88,7 +88,7 @@ function exacouprob_wavsim(parall=:serial) snapevery = 50 infoevery = 500 boundcond = CPMLBoundaryConditionParameters(; halo=20, rcoef=0.0001, freeboundtop=true) - params = InputParametersAcoustic(nt, dt, [nx, nz], [dh, dh], boundcond) + params = InputParametersAcoustic(nt, dt, (nx, nz), (dh, dh), boundcond) #@show (boundcond.halo-1)*dh ##=============================================== diff --git a/ext/CUDABackendExt.jl b/ext/CUDABackendExt.jl index 934363e..4aa105c 100644 --- a/ext/CUDABackendExt.jl +++ b/ext/CUDABackendExt.jl @@ -11,9 +11,9 @@ include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") # Overload backend selection -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU diff --git a/src/abstract_types.jl b/src/abstract_types.jl index 9e74dfe..1e496f3 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -6,7 +6,7 @@ Abstract type for wave simulations. """ abstract type WaveSimul{N} end -abstract type InputParameters{N} end +abstract type InputParameters{T, N} end abstract type InputBoundaryConditionParameters end diff --git a/src/checks.jl b/src/checks.jl index a9de505..7a65758 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -1,5 +1,5 @@ -function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, shots::Vector{<:Shot}) +function check_sim_consistency(wavsim::WaveSimul{N}, matprop::MaterialProperties, shots::Vector{<:Shot}) where {N} tysource = typeof(shots[1].srcs) tyreceiver = typeof(shots[1].recs) @@ -11,8 +11,7 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s end # Check that the subtypes of WaveSimul, MaterialProperties and Shot are consistent - N = typeof(wavsim).parameters[1] - if wavsim isa AcousticCDCPMLWaveSimul{N} && + if wavsim isa AcousticCDCPMLWaveSimul{<:Real, N, <:AbstractArray{<:Real}} && matprop isa VpAcousticCDMaterialProperties{<:Real, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers @@ -31,7 +30,7 @@ function check_sim_consistency(wavsim::WaveSimul, matprop::MaterialProperties, s return end - return error("Types of WaveSimul, MaterialProperties and Sources/Receivers are incosistent \ + return error("Types of WaveSimul, MaterialProperties and Sources/Receivers are inconsistent \ \n $(typeof(wavsim)), \n $(typeof(matprop)), \n $(typeof(shots[1].srcs)), $(typeof(shots[1].recs))") end diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index bf802f8..de00f8f 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -3,8 +3,8 @@ swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) # Scaling for AcousticCDWaveSimul -@views function possrcrec_scaletf(wavsim::AcousticCDCPMLWaveSimul{N}, - shot::Shot) where {N} +@views function possrcrec_scaletf(wavsim::AcousticCDCPMLWaveSimul{T,N}, + shot::Shot) where {T,N} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) @@ -22,9 +22,9 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::AcousticCDCPMLWaveSimul{N}, + wavsim::AcousticCDCPMLWaveSimul{T,N}, shot::Shot -) where {N} +) where {T,N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 3a77f34..9b34d0d 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -49,7 +49,7 @@ end ########################################################### -struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWaveSimul{N} +struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWaveSimul{N} # Numerics nt::Int dt::T @@ -91,7 +91,7 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWave snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, smooth_radius::Int=5 - ) where {N, T} + ) where {T, N} # Check numerics @assert nt > 0 "Number of timesteps must be positive!" @assert dt > 0 "Timestep size must be positive!" @@ -102,7 +102,7 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWave @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Select backend - backend = select_backend(AcousticCDCPMLWaveSimul{N, T}, parall) + backend = select_backend(AcousticCDCPMLWaveSimul{T, N}, parall) A = backend.Data.Array{N} V = backend.Data.Array{1} # Initialize computational grid @@ -185,7 +185,7 @@ struct AcousticCDCPMLWaveSimul{N, T, A <: AbstractArray{T, N}} <: AcousticCDWave @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - new{N, T, A}( + new{T, N, A}( nt, dt, grid, @@ -223,7 +223,7 @@ end # Specific functions for AcousticCDCPMLWaveSimul -@views function reset!(model::AcousticCDCPMLWaveSimul{N}) where {N} +@views function reset!(model::AcousticCDCPMLWaveSimul) reset!(model.grid; except=["fact", "a_pml", "b_pml"]) reset!(model.checkpointer) end diff --git a/src/models/acoustic/acou_params.jl b/src/models/acoustic/acou_params.jl index 5941772..8323206 100644 --- a/src/models/acoustic/acou_params.jl +++ b/src/models/acoustic/acou_params.jl @@ -6,67 +6,26 @@ Parameters for acoustic wave simulations. $(TYPEDFIELDS) """ -struct InputParametersAcoustic{N} <: InputParameters{N} +struct InputParametersAcoustic{T,N} <: InputParameters{T,N} "Number of time steps" ntimesteps::Int "Time step" - dt::Real + dt::T "Grid size for each dimension" - gridsize::NTuple{N, <:Int} + gridsize::NTuple{N, Int} "Grid spacing in each direction" - gridspacing::NTuple{N, <:Real} + gridspacing::NTuple{N, T} "Kind of boundary conditions" boundcond::InputBoundaryConditionParameters -end - -function InputParametersAcoustic( - ntimesteps::Int, - dt::Real, - gridsize::AbstractVector{<:Int}, - gridspacing::AbstractVector{<:Real}, - boundcond::InputBoundaryConditionParameters -) - # Check dimensionality - N = length(gridsize) - @assert N == length(gridspacing) "Dimensionality mismatch between number of grid points and grid step sizes!" - @assert N > 0 "Dimensionality must positive!" - @assert N <= 3 "Dimensionality must be less than or equal to 3!" - return InputParametersAcoustic{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) + function InputParametersAcoustic( + ntimesteps::Int, + dt::T, + gridsize::NTuple{N, Int}, + gridspacing::NTuple{N, T}, + boundcond::InputBoundaryConditionParameters + ) where {T, N} + @assert N <= 3 "Dimensionality must be less than or equal to 3!" + new{T,N}(ntimesteps, dt, gridsize, gridspacing, boundcond) + end end - -# @doc """ -# $(TYPEDEF) - -# Parameters for variable-density acoustic wave simulations. - -# $(TYPEDFIELDS) -# """ -# struct InputParametersAcousticVariableDensity{N} <: InputParameters{N} -# "Number of time steps" -# ntimesteps::Int -# "Time step" -# dt::Real -# "Grid size for each dimension" -# gridsize::NTuple{N, <:Int} -# "Grid spacing in each direction" -# gridspacing::NTuple{N, <:Real} -# "Kind of boundary conditions" -# boundcond::InputBoundaryConditionParameters -# end - -# function InputParametersAcousticVariableDensity( -# ntimesteps::Int, -# dt::Real, -# gridsize::AbstractVector{<:Int}, -# gridspacing::AbstractVector{<:Real}, -# boundcond::InputBoundaryConditionParameters -# ) -# # Check dimensionality -# N = length(gridsize) -# @assert N == length(gridspacing) "Dimensionality mismatch between number of grid points and grid step sizes!" -# @assert N > 0 "Dimensionality must positive!" -# @assert N <= 3 "Dimensionality must be less than or equal to 3!" - -# return InputParametersAcousticVariableDensity{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) -# end diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index 00c1721..e901e4a 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -19,17 +19,17 @@ end ## VD = variable density # Backend selections for AcousticCDCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:serial}}) = Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:serial}}) = Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:serial}}) = Acoustic3D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:serial}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:serial}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:serial}}) = Acoustic3D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = Acoustic1D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = Acoustic2D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threads}}) = Acoustic3D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:threads}}) = Acoustic3D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{1}}, ::Type{Val{:threadpersrc}}) = Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{2}}, ::Type{Val{:threadpersrc}}) = Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:threadpersrc}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:threadpersrc}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial # Backend selections for AcousticVDStaggeredCPMLWaveSimul select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl index a3021c2..79f7717 100644 --- a/src/models/elastic/ela_params.jl +++ b/src/models/elastic/ela_params.jl @@ -5,31 +5,27 @@ Parameters for elastic wave simulations $(TYPEDFIELDS) """ -struct InputParametersElastic{N} <: InputParameters{N} +struct InputParametersElastic{T,N} <: InputParameters{T,N} "Number of time steps" ntimesteps::Int "Time step" - dt::Real + dt::T "Grid size for each dimension" - gridsize::NTuple{N, <:Int} + gridsize::NTuple{N, Int} "Grid spacing in each direction" - gridspacing::NTuple{N, <:Real} + gridspacing::NTuple{N, T} "Kind of boundary conditions" boundcond::InputBoundaryConditionParameters -end -function InputParametersElastic( - ntimesteps::Int, - dt::Real, - gridsize::AbstractVector{<:Int}, - gridspacing::AbstractVector{<:Real}, - boundcond::InputBoundaryConditionParameters -) - # Check dimensionality - N = length(gridsize) - @assert N == length(gridspacing) "Dimensionality mismatch between number of grid points and grid step sizes!" - @assert N > 0 "Dimensionality must positive!" - @assert N <= 3 "Dimensionality must be less than or equal to 3!" - - return InputParametersElastic{N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) -end + function InputParametersElastic( + ntimesteps::Int, + dt::T, + gridsize::NTuple{N, Int}, + gridspacing::NTuple{N, T}, + boundcond::InputBoundaryConditionParameters + ) where {T,N} + @assert N <= 3 "Dimensionality must be less than or equal to 3!" + new{T,N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) + end + +end \ No newline at end of file diff --git a/src/wrappers.jl b/src/wrappers.jl index cfc422e..2a58c3a 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -13,7 +13,7 @@ Return a vector of snapshots for every shot if snapshotting is enabled. See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments -- `params::InputParameters{N}`: input parameters for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). +- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -27,7 +27,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ function swforward!( - params::InputParameters{N}, + params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; parall::Symbol=:threads, @@ -88,7 +88,7 @@ $(TYPEDSIGNATURES) Return the misfit w.r.t. observed data by running a forward simulation using the given input parameters `params` and material properties `matprop` on multiple shots. # Positional arguments -- `params::InputParameters{N}`: input parameters for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). +- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -104,7 +104,7 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ function swmisfit!( - params::InputParameters{N}, + params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; #<:Pair{<:Sources{<:Real}, <:Receivers{<:Real}}}; parall::Symbol=:threads, @@ -171,7 +171,7 @@ Bigger values speed up computation at the cost of using more memory. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). # Positional arguments -- `params::InputParameters{N}`: input parameters for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). +- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -188,7 +188,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ function swgradient!( - params::InputParameters{N}, + params::InputParameters{T,N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; parall::Symbol=:threads, @@ -260,7 +260,7 @@ $(TYPEDSIGNATURES) Builds a wave similation based on the input paramters `params` and keyword arguments `kwargs`. # Positional arguments -- `params::InputParameters{N}`: input parameters for the simulation, where N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). +- `params::InputParameters{T,N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -273,7 +273,7 @@ Builds a wave similation based on the input paramters `params` and keyword argum - `snapevery::Union{<:Integer, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). - `infoevery::Union{<:Integer, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function build_wavesim(params::InputParameters{N}, matprop::MaterialProperties{T, N}; parall::Symbol, kwargs...) where {T, N} +function build_wavesim(params::InputParameters{T, N}, matprop::MaterialProperties{T, N}; parall::Symbol, kwargs...) where {T, N} if parall == :threadpersrc nthr = Threads.nthreads() wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for _ in 1:nthr] @@ -284,12 +284,12 @@ function build_wavesim(params::InputParameters{N}, matprop::MaterialProperties{T end build_concrete_wavesim( - params::InputParametersAcoustic{N}, - ::VpAcousticCDMaterialProperties, + params::InputParametersAcoustic{T,N}, + ::VpAcousticCDMaterialProperties{T,N}, cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... -) where {N} = AcousticCDCPMLWaveSimul( +) where {T,N} = AcousticCDCPMLWaveSimul( params.gridsize, params.gridspacing, params.ntimesteps, @@ -302,12 +302,12 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersAcoustic{N}, + params::InputParametersAcoustic{T,N}, ::VpRhoAcousticVDMaterialProperties, cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... -) where {N} = AcousticVDStaggeredCPMLWaveSimul{N}( +) where {T,N} = AcousticVDStaggeredCPMLWaveSimul{N}( params.gridsize, params.gridspacing, params.ntimesteps, @@ -320,12 +320,12 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersElastic{N}, + params::InputParametersElastic{T,N}, ::ElasticIsoMaterialProperties, cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... -) where {N} = ElasticIsoCPMLWaveSimul{N}( +) where {T,N} = ElasticIsoCPMLWaveSimul{N}( params.gridsize, params.gridspacing, params.ntimesteps, diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index 418ca33..c497157 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -29,7 +29,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do rcoef = 0.0001 f0 = 5.0 # wave simulation - params = InputParametersAcoustic(nt, dt, [nx], [dx], + params = InputParametersAcoustic(nt, dt, (nx,), (dx,), CPMLBoundaryConditionParameters(halo, rcoef, false)) wavesim = build_wavesim(params, matprop; parall=parall) @@ -82,7 +82,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do rcoef = 0.0001 f0 = 5.0 # wave simulation - params = InputParametersAcoustic(nt, dt, [nx], [dx], + params = InputParametersAcoustic(nt, dt, (nx,), (dx,), CPMLBoundaryConditionParameters(halo, rcoef, false)) wavesim = build_wavesim(params, matprop; parall=parall) @@ -139,7 +139,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do rcoef = 0.0001 f0 = 5.0 # wave simulation - params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], + params = InputParametersAcoustic(nt, dt, (nx, ny), (dx, dy), CPMLBoundaryConditionParameters(halo, rcoef, false)) wavesim = build_wavesim(params, matprop; parall=parall) @@ -195,7 +195,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do rcoef = 0.0001 f0 = 5.0 # wave simulation - params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], + params = InputParametersAcoustic(nt, dt, (nx, ny), (dx, dy), CPMLBoundaryConditionParameters(halo, rcoef, false)) wavesim = build_wavesim(params, matprop; parall=parall) diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index d24a404..2be2541 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -26,7 +26,7 @@ function setup_constant_vel_1D_CPML(nt, dt, nx, dx, c0, f0, halo, rcoef) lx = (nx - 1) * dx vel = VpAcousticCDMaterialProperties(c0 .* ones(nx)) # input parameters - params = InputParametersAcoustic(nt, dt, [nx], [dx], + params = InputParametersAcoustic(nt, dt, (nx,), (dx,), CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources t0 = 2 / f0 @@ -49,7 +49,7 @@ function setup_constant_vel_rho_1D_CPML(nt, dt, nx, dx, c0, ρ0, t0, f0, halo, r lx = (nx - 1) * dx matprop = VpRhoAcousticVDMaterialProperties(c0 .* ones(nx), ρ0 .* ones(nx)) # input parameters - params = InputParametersAcoustic(nt, dt, [nx], [dx], + params = InputParametersAcoustic(nt, dt, (nx,), (dx,), CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources times = collect(range(0.0; step=dt, length=nt)) @@ -73,7 +73,7 @@ function setup_constant_vel_2D_CPML(nt, dt, nx, ny, dx, dy, c0, f0, halo, rcoef) ly = (ny - 1) * dy vel = VpAcousticCDMaterialProperties(c0 .* ones(nx, ny)) # input parameters - params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], + params = InputParametersAcoustic(nt, dt, (nx, ny), (dx, dy), CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources t0 = 2 / f0 @@ -97,7 +97,7 @@ function setup_constant_vel_rho_2D_CPML(nt, dt, nx, ny, dx, dy, c0, ρ0, t0, f0, ly = (ny - 1) * dy matprop = VpRhoAcousticVDMaterialProperties(c0 .* ones(nx, ny), ρ0 .* ones(nx, ny)) # input parameters - params = InputParametersAcoustic(nt, dt, [nx, ny], [dx, dy], + params = InputParametersAcoustic(nt, dt, (nx, ny), (dx, dy), CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources times = collect(range(0.0; step=dt, length=nt)) @@ -121,7 +121,7 @@ function setup_constant_vel_3D_CPML(nt, dt, nx, ny, nz, dx, dy, dz, c0, f0, halo lz = (nz - 1) * dz vel = VpAcousticCDMaterialProperties(c0 .* ones(nx, ny, nz)) # input parameters - params = InputParametersAcoustic(nt, dt, [nx, ny, nz], [dx, dy, dz], + params = InputParametersAcoustic(nt, dt, (nx, ny, nz), (dx, dy, dz), CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources t0 = 2 / f0 From 20f7931234c558eec0082d46430e852de8af6937 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 1 Jul 2024 16:51:57 +0200 Subject: [PATCH 046/111] InputBDCParams now depend on data type --- src/abstract_types.jl | 2 +- src/boundarycond.jl | 6 +++--- src/models/acoustic/acou_params.jl | 4 ++-- src/models/elastic/ela_params.jl | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/abstract_types.jl b/src/abstract_types.jl index 1e496f3..b8c5631 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -8,7 +8,7 @@ abstract type WaveSimul{N} end abstract type InputParameters{T, N} end -abstract type InputBoundaryConditionParameters end +abstract type InputBoundaryConditionParameters{T} end abstract type MaterialProperties{T, N} end diff --git a/src/boundarycond.jl b/src/boundarycond.jl index 4d19128..3149996 100644 --- a/src/boundarycond.jl +++ b/src/boundarycond.jl @@ -4,7 +4,7 @@ $(TYPEDEF) Reflective boundary conditions parameters for wave simulations. """ -Base.@kwdef struct ReflectiveBoundaryConditionParameters <: InputBoundaryConditionParameters end +Base.@kwdef struct ReflectiveBoundaryConditionParameters{T, N} <: InputBoundaryConditionParameters{T} end @doc """ $(TYPEDEF) @@ -13,11 +13,11 @@ CPML boundary conditions parameters for wave simulations. $(TYPEDFIELDS) """ -Base.@kwdef struct CPMLBoundaryConditionParameters <: InputBoundaryConditionParameters +Base.@kwdef struct CPMLBoundaryConditionParameters{T} <: InputBoundaryConditionParameters{T} "Number of CPML grid points" halo::Int = 20 "Target reflection coefficient" - rcoef::Real = 0.0001 + rcoef::T = 0.0001 "Free surface boundary condition at the top" freeboundtop::Bool = true end diff --git a/src/models/acoustic/acou_params.jl b/src/models/acoustic/acou_params.jl index 8323206..a699596 100644 --- a/src/models/acoustic/acou_params.jl +++ b/src/models/acoustic/acou_params.jl @@ -16,14 +16,14 @@ struct InputParametersAcoustic{T,N} <: InputParameters{T,N} "Grid spacing in each direction" gridspacing::NTuple{N, T} "Kind of boundary conditions" - boundcond::InputBoundaryConditionParameters + boundcond::InputBoundaryConditionParameters{T} function InputParametersAcoustic( ntimesteps::Int, dt::T, gridsize::NTuple{N, Int}, gridspacing::NTuple{N, T}, - boundcond::InputBoundaryConditionParameters + boundcond::InputBoundaryConditionParameters{T} ) where {T, N} @assert N <= 3 "Dimensionality must be less than or equal to 3!" new{T,N}(ntimesteps, dt, gridsize, gridspacing, boundcond) diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl index 79f7717..6d9ec05 100644 --- a/src/models/elastic/ela_params.jl +++ b/src/models/elastic/ela_params.jl @@ -15,14 +15,14 @@ struct InputParametersElastic{T,N} <: InputParameters{T,N} "Grid spacing in each direction" gridspacing::NTuple{N, T} "Kind of boundary conditions" - boundcond::InputBoundaryConditionParameters + boundcond::InputBoundaryConditionParameters{T} function InputParametersElastic( ntimesteps::Int, dt::T, gridsize::NTuple{N, Int}, gridspacing::NTuple{N, T}, - boundcond::InputBoundaryConditionParameters + boundcond::InputBoundaryConditionParameters{T} ) where {T,N} @assert N <= 3 "Dimensionality must be less than or equal to 3!" new{T,N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) From daff79ebee66edc55662556a74d94896e1d95de7 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 2 Jul 2024 09:42:22 +0200 Subject: [PATCH 047/111] WaveSimul now depends on data type --- ext/CUDABackendExt.jl | 4 +- src/abstract_types.jl | 4 +- src/checks.jl | 30 +++---- src/misfits.jl | 12 +-- src/models/acoustic/acou_abstract_types.jl | 6 +- src/models/acoustic/acou_forward.jl | 7 +- src/models/acoustic/acou_gradient.jl | 8 +- src/models/acoustic/acou_models.jl | 80 +++++++++---------- src/models/backend_selection.jl | 6 +- src/models/cpmlcoeffs.jl | 12 +-- .../backends/Elastic2D_Iso_CPML_Serial.jl | 42 +++++----- src/models/elastic/ela_abstract_types.jl | 4 +- src/models/elastic/ela_forward.jl | 17 ++-- src/models/elastic/ela_models.jl | 64 +++++++-------- src/receivers.jl | 39 ++++----- src/shot.jl | 2 +- src/solve.jl | 12 +-- src/sources.jl | 26 +++--- src/srcrec_interpolation.jl | 4 +- src/utils.jl | 2 +- src/wrappers.jl | 34 ++++---- 21 files changed, 206 insertions(+), 209 deletions(-) diff --git a/ext/CUDABackendExt.jl b/ext/CUDABackendExt.jl index 4aa105c..f7c212f 100644 --- a/ext/CUDABackendExt.jl +++ b/ext/CUDABackendExt.jl @@ -14,7 +14,7 @@ include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU end \ No newline at end of file diff --git a/src/abstract_types.jl b/src/abstract_types.jl index b8c5631..c53cae2 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -4,7 +4,7 @@ $(TYPEDEF) Abstract type for wave simulations. """ -abstract type WaveSimul{N} end +abstract type WaveSimul{T, N} end abstract type InputParameters{T, N} end @@ -16,7 +16,7 @@ abstract type Sources end abstract type Receivers end -abstract type MomentTensor end +abstract type MomentTensor{T} end abstract type InterpolationMethod end diff --git a/src/checks.jl b/src/checks.jl index 7a65758..9509652 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -1,5 +1,5 @@ -function check_sim_consistency(wavsim::WaveSimul{N}, matprop::MaterialProperties, shots::Vector{<:Shot}) where {N} +function check_sim_consistency(wavsim::WaveSimul{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}) where {T, N} tysource = typeof(shots[1].srcs) tyreceiver = typeof(shots[1].recs) @@ -11,20 +11,20 @@ function check_sim_consistency(wavsim::WaveSimul{N}, matprop::MaterialProperties end # Check that the subtypes of WaveSimul, MaterialProperties and Shot are consistent - if wavsim isa AcousticCDCPMLWaveSimul{<:Real, N, <:AbstractArray{<:Real}} && - matprop isa VpAcousticCDMaterialProperties{<:Real, N} && + if wavsim isa AcousticCDCPMLWaveSimul{T, N, <:AbstractArray{T, N}} && + matprop isa VpAcousticCDMaterialProperties{T, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif wavsim isa AcousticVDStaggeredCPMLWaveSimul{N} && - matprop isa VpRhoAcousticVDMaterialProperties{<:Real, N} && + elseif wavsim isa AcousticVDStaggeredCPMLWaveSimul{T, N} && + matprop isa VpRhoAcousticVDMaterialProperties{T, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif wavsim isa ElasticIsoCPMLWaveSimul{2} && # <<<<<---------<<<< - matprop isa ElasticIsoMaterialProperties{<:Real, 2} && + elseif wavsim isa ElasticIsoCPMLWaveSimul{T, 2} && # <<<<<---------<<<< + matprop isa ElasticIsoMaterialProperties{T, 2} && tysource <: MomentTensorSources && tyreceiver <: VectorReceivers return @@ -44,13 +44,13 @@ function check_shot(model::WaveSimul, shot::Shot; kwargs...) return end -check_positions(model::WaveSimul, positions::Matrix{<:Real}) = check_positions(BoundaryConditionTrait(model), model, positions) +check_positions(model, positions) = check_positions(BoundaryConditionTrait(model), model, positions) function check_positions( ::ReflectiveBoundaryCondition, - model::WaveSimul, - positions::Matrix{<:Real} -) + model::WaveSimul{T}, + positions::Matrix{T} +) where {T} ndimwavsim = length(model.gridspacing) @assert size(positions, 2) == ndimwavsim "Positions matrix do not match the dimension of the model!" @@ -65,9 +65,9 @@ end function check_positions( ::CPMLBoundaryCondition, - model::WaveSimul, - positions::Matrix{<:Real} -) + model::WaveSimul{T}, + positions::Matrix{T} +) where {T} check_positions(ReflectiveBoundaryCondition(), model, positions) Ndim = size(positions, 2) for s in axes(positions, 1) @@ -85,4 +85,4 @@ function check_positions( return end -check_invcov_matrix(model::WaveSimul, invcov) = @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" +check_invcov_matrix(model::WaveSimul{T}, invcov::AbstractMatrix{T}) where {T} = @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" diff --git a/src/misfits.jl b/src/misfits.jl index 0c77789..4b0b135 100644 --- a/src/misfits.jl +++ b/src/misfits.jl @@ -39,19 +39,19 @@ function dχ_du(_::L2Misfit, recs::ScalarReceivers) return recs.invcov * residuals end -Base.@kwdef struct ZerothOrderTikhonovRegularization{M <: MaterialProperties} <: AbstractRegularization +Base.@kwdef struct ZerothOrderTikhonovRegularization{T, M <: MaterialProperties{T}} <: AbstractRegularization matprop_prior::M - alpha::Real + alpha::T end -function (regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{T, N}})(matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +function (regularization::ZerothOrderTikhonovRegularization{T, VpAcousticCDMaterialProperties{T, N}})(matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} vp = matprop.vp vp_prior = regularization.matprop_prior.vp vp_norm_sq = norm(vp - vp_prior)^2 return regularization.alpha / 2 * vp_norm_sq end -function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{T, N}})(matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +function (regularization::ZerothOrderTikhonovRegularization{T, VpRhoAcousticVDMaterialProperties{T, N}})(matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp @@ -61,13 +61,13 @@ function (regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMater return regularization.alpha / 2 * (vp_norm_sq + rho_norm_sq) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpAcousticCDMaterialProperties{T, N}}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{T, VpAcousticCDMaterialProperties{T, N}}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} vp = matprop.vp vp_prior = regularization.matprop_prior.vp return regularization.alpha * (vp - vp_prior) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{VpRhoAcousticVDMaterialProperties{T, N}}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{T, VpRhoAcousticVDMaterialProperties{T, N}}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp diff --git a/src/models/acoustic/acou_abstract_types.jl b/src/models/acoustic/acou_abstract_types.jl index 4bba5f9..e2e1658 100644 --- a/src/models/acoustic/acou_abstract_types.jl +++ b/src/models/acoustic/acou_abstract_types.jl @@ -1,6 +1,6 @@ -abstract type AcousticWaveSimul{N} <: WaveSimul{N} end +abstract type AcousticWaveSimul{T,N} <: WaveSimul{T,N} end -abstract type AcousticCDWaveSimul{N} <: AcousticWaveSimul{N} end +abstract type AcousticCDWaveSimul{T,N} <: AcousticWaveSimul{T,N} end -abstract type AcousticVDStaggeredWaveSimul{N} <: AcousticWaveSimul{N} end +abstract type AcousticVDStaggeredWaveSimul{T,N} <: AcousticWaveSimul{T,N} end diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index de00f8f..4c26d7f 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -70,8 +70,7 @@ end ##################################################### # Scaling for AcousticVDStaggeredCPMLWaveSimul -@views function possrcrec_scaletf(wavsim::AcousticVDStaggeredCPMLWaveSimul{N}, - shot::Shot) where {N} +@views function possrcrec_scaletf(wavsim::AcousticVDStaggeredCPMLWaveSimul, shot::Shot) # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) @@ -89,9 +88,9 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::AcousticVDStaggeredCPMLWaveSimul{N}, + wavsim::AcousticVDStaggeredCPMLWaveSimul{T,N}, shot::Shot -) where {N} +) where {T,N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 8ffa8cf..76d56ba 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -3,10 +3,10 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @views function swgradient_1shot!( ::CPMLBoundaryCondition, - model::AcousticCDWaveSimul{N}, + model::AcousticCDWaveSimul{T,N}, shot::Shot, misfit -)::Array{<:Real} where {N} +)::Array{T} where {T,N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) @@ -98,10 +98,10 @@ end @views function swgradient_1shot!( ::CPMLBoundaryCondition, - model::AcousticVDStaggeredCPMLWaveSimul{N}, + model::AcousticVDStaggeredCPMLWaveSimul{T,N}, shot::Shot, misfit -)::Array{<:Real} where {N} +)::Array{T} where {T,N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 9b34d0d..2cb1dcf 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -2,7 +2,7 @@ # Functions for all AcousticWaveSimul subtypes -@views function check_courant_condition(model::AcousticWaveSimul{N}, vp::Array{<:Real, N}) where {N} +@views function check_courant_condition(model::AcousticWaveSimul{T,N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) courant = vel_max * model.dt * tmp @@ -15,7 +15,7 @@ end function check_numerics( model::AcousticWaveSimul, shot::Shot; - min_ppw::Integer=10 + min_ppw::Int=10 ) # Check points per wavelength vel_min = get_minimum_func(model)(model.matprop.vp) @@ -29,7 +29,7 @@ end # Functions for all AcousticCDWaveSimul subtypes -@views function check_matprop(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::AcousticCDWaveSimul{T,N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.ns)" @@ -38,7 +38,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticCDWaveSimul{N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::AcousticCDWaveSimul{T,N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) # Precompute factors @@ -49,7 +49,7 @@ end ########################################################### -struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWaveSimul{N} +struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWaveSimul{T,N} # Numerics nt::Int dt::T @@ -69,7 +69,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave # Logging parameters infoevery::Int # Material properties - matprop::VpAcousticCDMaterialProperties + matprop::VpAcousticCDMaterialProperties{T,N} # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} # Checkpointing setup @@ -208,7 +208,7 @@ end ########################################################### -@views function find_nearest_grid_points(model::AcousticCDCPMLWaveSimul, positions::Matrix{<:Real})::Matrix{<:Int} +@views function find_nearest_grid_points(model::AcousticCDCPMLWaveSimul{T}, positions::Matrix{T})::Matrix{Int} where {T} # source time functions nsrcs = size(positions, 1) # number of sources ncoos = size(positions, 2) # number of coordinates @@ -239,7 +239,7 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() # Functions for all AcousticVDStaggeredWaveSimul subtypes -@views function check_courant_condition(model::AcousticVDStaggeredWaveSimul{N}, vp::Array{<:Real, N}) where {N} +@views function check_courant_condition(model::AcousticVDStaggeredWaveSimul{T,N}, vp::Array{T, N}) where {T,N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil @@ -252,7 +252,7 @@ end function check_numerics( model::AcousticVDStaggeredWaveSimul, shot::Shot; - min_ppw::Integer=10 + min_ppw::Int=10 ) # Check points per wavelength vel_min = get_minimum_func(model)(model.matprop.vp) @@ -262,7 +262,7 @@ function check_numerics( @assert ppw >= min_ppw "Not enough points per wavelengh!" end -@views function check_matprop(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::AcousticVDStaggeredWaveSimul{T,N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == size(matprop.rho) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.ns)" @@ -272,7 +272,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{T,N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) copyto!(model.matprop.rho, matprop.rho) @@ -281,7 +281,7 @@ end precompute_fact!(model) end -@views function precompute_fact!(model::AcousticVDStaggeredWaveSimul{N}) where {N} +@views function precompute_fact!(model::AcousticVDStaggeredWaveSimul{T,N}) where {T,N} # Precompute 1/m0 * dt factor copyto!(model.fact_m0, model.matprop.vp .^ 2 .* model.matprop.rho .* model.dt) # Precompute m1 * dt factor by interpolation @@ -293,31 +293,31 @@ end ########################################################### -struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} +struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N} # Physics - domainextent::NTuple{N, <:Real} + domainextent::NTuple{N, T} # Numerics - ns::NTuple{N, <:Integer} - gridspacing::NTuple{N, <:Real} - nt::Integer - dt::Real + ns::NTuple{N, Int} + gridspacing::NTuple{N, T} + nt::Int + dt::T # BDC and CPML parameters - halo::Integer - rcoef::Real + halo::Int + rcoef::T freetop::Bool # Gradient computation setup gradient::Bool totgrad_size::Union{Vector{Int}, Nothing} - check_freq::Union{<:Integer, Nothing} + check_freq::Union{Int, Nothing} # Snapshots - snapevery::Union{<:Integer, Nothing} + snapevery::Union{Int, Nothing} snapshots::Union{Any, Nothing} # Logging parameters - infoevery::Integer + infoevery::Int # Gradient smoothing parameters - smooth_radius::Integer + smooth_radius::Int # Material properties - matprop::VpRhoAcousticVDMaterialProperties + matprop::VpRhoAcousticVDMaterialProperties{T,N} # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients} # Forward computation arrays @@ -337,7 +337,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} ψ_adj::Any ξ_adj::Any # Checkpointing setup - last_checkpoint::Union{<:Integer, Nothing} + last_checkpoint::Union{Int, Nothing} save_buffer::Any checkpoints::Any checkpoints_v::Any @@ -346,21 +346,21 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} # Backend backend::Module - function AcousticVDStaggeredCPMLWaveSimul{N}( - ns::NTuple{N, <:Integer}, - gridspacing::NTuple{N, <:Real}, - nt::Integer, - dt::Real, - halo::Integer, - rcoef::Real; + function AcousticVDStaggeredCPMLWaveSimul( + ns::NTuple{N, Int}, + gridspacing::NTuple{N, T}, + nt::Int, + dt::T, + halo::Int, + rcoef::T; parall::Symbol=:threads, freetop::Bool=true, gradient::Bool=false, - check_freq::Union{<:Integer, Nothing}=nothing, - snapevery::Union{<:Integer, Nothing}=nothing, - infoevery::Union{<:Integer, Nothing}=nothing, - smooth_radius::Integer=5 - ) where {N} + check_freq::Union{Int, Nothing}=nothing, + snapevery::Union{Int, Nothing}=nothing, + infoevery::Union{Int, Nothing}=nothing, + smooth_radius::Int=5 + ) where {T,N} # Check numerics @assert all(ns .> 0) "All numbers of grid points must be positive!" @assert all(gridspacing .> 0) "All cell sizes must be positive!" @@ -378,7 +378,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} matprop = VpRhoAcousticVDMaterialProperties(zeros(ns...), zeros(ns...)) # Select backend - backend = select_backend(AcousticVDStaggeredCPMLWaveSimul{N}, parall) + backend = select_backend(AcousticVDStaggeredCPMLWaveSimul{T,N}, parall) # Initialize computational arrays fact_m0 = backend.zeros(ns...) @@ -484,7 +484,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{N} <: AcousticVDStaggeredWaveSimul{N} @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - return new( + return new{T,N}( domainextent, ns, gridspacing, diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index e901e4a..0629474 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -32,8 +32,8 @@ select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWave select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial # Backend selections for AcousticVDStaggeredCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads # Backend selections for ElasticIsoWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimul{2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimul{Float64, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 7080b4f..1457198 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -5,7 +5,7 @@ struct CPMLCoefficientsAxis b::Any b_h::Any - function CPMLCoefficientsAxis(halo::Integer, backend::Module, + function CPMLCoefficientsAxis(halo::Int, backend::Module, sizehalfgrdplusone::Bool=false) if sizehalfgrdplusone return new( @@ -29,7 +29,7 @@ function compute_CPML_coefficientsAxis!( cpmlcoeffs::CPMLCoefficientsAxis, vel_max::Real, dt::Real, - halo::Integer, + halo::Int, rcoef::Real, thickness::Real, f0::Real @@ -59,7 +59,7 @@ struct CPMLCoefficients b_hl::Any b_hr::Any - function CPMLCoefficients(halo::Integer, backend::Module, + function CPMLCoefficients(halo::Int, backend::Module, sizehalfgrdplusone::Bool=false) if sizehalfgrdplusone return new( @@ -88,7 +88,7 @@ struct CPMLCoefficients end function calc_Kab_CPML_staggeredgrid( - halo::Integer, + halo::Int, dt::Float64, npower::Float64, d0::Float64, @@ -155,7 +155,7 @@ function compute_CPML_coefficients!( cpmlcoeffs::CPMLCoefficients, vel_max::Real, dt::Real, - halo::Integer, + halo::Int, rcoef::Real, thickness::Real, f0::Real @@ -183,7 +183,7 @@ end ##################################### function calc_Kab_CPML( - halo::Integer, + halo::Int, dt::Float64, npower::Float64, d0::Float64, diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 3707571..c3ee532 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -405,27 +405,27 @@ function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, return end -function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, - srccoeij_bk::Array{<:Integer}, - srccoeval_bk::Array{<:Real}, - reccoeij_bk::Array{<:Integer}, - reccoeval_bk::Array{<:Real}, - srctf_bk::Matrix{<:Real}, - traces_bk::Array{<:Real}, - it::Integer, - Mxx_bk::Vector{<:Real}, - Mzz_bk::Vector{<:Real}, - Mxz_bk::Vector{<:Real}; - save_trace::Bool=true) where {N} - # function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{N}, - # possrcs_bk::Array{<:Integer,2}, - # srctf_bk::Matrix{<:Real}, - # posrecs_bk::Array{<:Integer,2}, - # traces_bk::Array{<:Real}, - # it::Integer, - # Mxx_bk::Vector{<:Real}, - # Mzz_bk::Vector{<:Real}, - # Mxz_bk::Vector{<:Real}; +function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T,N}, + srccoeij_bk::Array{Int}, + srccoeval_bk::Array{T}, + reccoeij_bk::Array{Int}, + reccoeval_bk::Array{T}, + srctf_bk::Matrix{T}, + traces_bk::Array{T}, + it::Int, + Mxx_bk::Vector{T}, + Mzz_bk::Vector{T}, + Mxz_bk::Vector{T}; + save_trace::Bool=true) where {T,N} + # function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T,N}, + # possrcs_bk::Array{Int,2}, + # srctf_bk::Matrix{T}, + # posrecs_bk::Array{Int,2}, + # traces_bk::Array{T}, + # it::Int, + # Mxx_bk::Vector{T}, + # Mzz_bk::Vector{T}, + # Mxz_bk::Vector{T}; # save_trace::Bool=true) where {N} @assert N == 2 diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index 7621d86..33aa944 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -1,7 +1,7 @@ -abstract type ElasticWaveSimul{N} <: WaveSimul{N} end +abstract type ElasticWaveSimul{T,N} <: WaveSimul{T,N} end -abstract type ElasticIsoWaveSimul{N} <: ElasticWaveSimul{N} end +abstract type ElasticIsoWaveSimul{T,N} <: ElasticWaveSimul{T,N} end abstract type ElasticMaterialProperties{T, N} <: MaterialProperties{T, N} end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 126dce0..55a83ed 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -3,13 +3,13 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::ElasticIsoCPMLWaveSimul{N}, + wavsim::ElasticIsoCPMLWaveSimul{T,N}, shot::Shot - # possrcs::Matrix{<:Integer}, - # posrecs::Matrix{<:Integer}, + # possrcs::Matrix{<:Int}, + # posrecs::Matrix{<:Int}, # srctf, # recs -) where {N} +) where {T,N} # scale source time function, etc. # find nearest grid points indexes for both sources and receivers @@ -121,9 +121,12 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC return end -function spreadsrcrecinterp2D(gridspacing::NTuple{N, Real}, gridsize::NTuple{N, Integer}, - positions::Matrix{<:Real}; - nptssinc::Int=4, xstart::Real=0.0, zstart::Real=0.0) where {N} +function spreadsrcrecinterp2D( + gridspacing::NTuple{N, T}, + gridsize::NTuple{N, Int}, + positions::Matrix{T}; + nptssinc::Int=4, xstart::T=0.0, zstart::T=0.0 +) where {T,N} nloc = size(positions, 1) Ndim = size(positions, 2) @assert Ndim == 2 diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index effd001..f2eee22 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,7 +2,7 @@ # Functions for all ElasticIsoWaveSimul subtypes -@views function check_matprop(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperties{N}) where {N} +@views function check_matprop(wavsim::ElasticIsoWaveSimul{T,N}, matprop::ElasticIsoMaterialProperties{T,N}) where {T,N} # Checks vp = sqrt.((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" @@ -26,7 +26,7 @@ end function check_numerics( wavsim::ElasticIsoWaveSimul, shot::Shot; - min_ppw::Integer=10 + min_ppw::Int=10 ) # Check points per wavelengh # min Vs @@ -41,7 +41,7 @@ function check_numerics( return end -@views function update_matprop!(wavsim::ElasticIsoWaveSimul{N}, matprop::ElasticIsoMaterialProperties{N}) where {N} +@views function update_matprop!(wavsim::ElasticIsoWaveSimul{T,N}, matprop::ElasticIsoMaterialProperties{T,N}) where {T,N} # Update material properties wavsim.matprop.λ .= matprop.λ @@ -108,28 +108,28 @@ end ############################################################## -struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} +struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} # Physics - domainextent::NTuple{N, <:Real} + domainextent::NTuple{N, T} # Numerics - gridsize::NTuple{N, <:Integer} - gridspacing::NTuple{N, <:Real} - nt::Integer - dt::Real + gridsize::NTuple{N, Int} + gridspacing::NTuple{N, T} + nt::Int + dt::T # BDC and CPML parameters - halo::Integer - rcoef::Real + halo::Int + rcoef::T freetop::Bool # Gradient computation setup gradient::Bool - check_freq::Union{<:Integer, Nothing} + check_freq::Union{Int, Nothing} # Snapshots - snapevery::Union{<:Integer, Nothing} - snapshots::Union{Vector{<:Array{<:Real}}, Nothing} + snapevery::Union{Int, Nothing} + snapshots::Union{Vector{<:Array{T}}, Nothing} # Logging parameters - infoevery::Integer + infoevery::Int # Material properties - matprop::AbstrElasticIsoMaterialProperties + matprop::AbstrElasticIsoMaterialProperties{T,N} # Forward computation arrays velpartic::Any # 2D: 2 comp, 3D: 3 comp stress::Any # 2D: 3 arrays, 3D: 6 arrays @@ -141,7 +141,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} ψ_adj::Any grad::Any # Checkpointing setup - last_checkpoint::Union{<:Integer, Nothing} + last_checkpoint::Union{Int, Nothing} save_buffer::Any checkpoints::Any checkpoints_ψ::Any @@ -149,20 +149,20 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} backend::Module parall::Symbol - function ElasticIsoCPMLWaveSimul{N}( - gridsize::NTuple{N, <:Integer}, - gridspacing::NTuple{N, <:Real}, - nt::Integer, - dt::Real, - halo::Integer, - rcoef::Real; + function ElasticIsoCPMLWaveSimul( + gridsize::NTuple{N, Int}, + gridspacing::NTuple{N, T}, + nt::Int, + dt::T, + halo::Int, + rcoef::T; parall::Symbol=:serial, freetop::Bool=true, gradient::Bool=false, - check_freq::Union{<:Integer, Nothing}=nothing, - snapevery::Union{<:Integer, Nothing}=nothing, - infoevery::Union{<:Integer, Nothing}=nothing - ) where {N} + check_freq::Union{Int, Nothing}=nothing, + snapevery::Union{Int, Nothing}=nothing, + infoevery::Union{Int, Nothing}=nothing + ) where {T,N} # Check numerics @assert all(gridsize .> 0) "All numbers of grid points must be positive!" @assert all(gridspacing .> 0) "All grid spacings must be positive!" @@ -178,7 +178,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} domainextent = gridspacing .* (gridsize .- 1) # Select backend - backend = select_backend(ElasticIsoCPMLWaveSimul{N}, parall) + backend = select_backend(ElasticIsoCPMLWaveSimul{T,N}, parall) # Initialize material properties if N == 2 @@ -276,7 +276,7 @@ struct ElasticIsoCPMLWaveSimul{N} <: ElasticIsoWaveSimul{N} @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - return new( + return new{T,N}( domainextent, gridsize, gridspacing, @@ -312,7 +312,7 @@ end # Specific functions for ElasticIsoCPMLWaveSimul -@views function reset!(wavsim::ElasticIsoCPMLWaveSimul{N}) where {N} +@views function reset!(wavsim::ElasticIsoCPMLWaveSimul{T,N}) where {T,N} # Reset computational arrays for p in propertynames(wavsim.velpartic) @@ -348,7 +348,7 @@ GridTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = LocalGrid() ########################################################### -struct ElasticIsoReflWaveSimul{N} <: ElasticIsoWaveSimul{N} end # TODO implementation +struct ElasticIsoReflWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} end # TODO implementation ########################################################### diff --git a/src/receivers.jl b/src/receivers.jl index bcee355..6f25999 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -5,9 +5,9 @@ Type representing a multi-receiver configuration for a wave propagation shot. $(TYPEDFIELDS) """ -struct ScalarReceivers{T <: Real} <: Receivers +struct ScalarReceivers{T} <: Receivers "Receiver positions" - positions::Matrix{<:Real} + positions::Matrix{T} "Array holding seismograms (as columns)" seismograms::Matrix{T} "Array holding observed seismograms (as columns)" @@ -19,22 +19,22 @@ struct ScalarReceivers{T <: Real} <: Receivers @doc """ ScalarReceivers{T}( - positions::Matrix{<:Real}, - nt::Integer; + positions::Matrix{T}, + nt::Int; observed::Union{Matrix{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing, windows::Union{Vector{Pair{Int,Int}}, Nothing}=nothing - ) where {T <: Real}$(TYPEDSIGNATURES) + ) where {T}$(TYPEDSIGNATURES) Create a single shot wave propagation receivers configuration from receivers positions. """ - function ScalarReceivers{T}( - positions::Matrix{<:Real}, - nt::Integer; + function ScalarReceivers( + positions::Matrix{T}, + nt::Int; observed::Union{Matrix{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing, windows::Union{Vector{Pair{Int, Int}}, Nothing}=nothing - ) where {T <: Real} + ) where {T} @assert size(positions, 1) > 0 "There must be at least one receiver!" seismograms = zeros(T, nt, size(positions, 1)) if observed !== nothing @@ -54,7 +54,7 @@ struct ScalarReceivers{T <: Real} <: Receivers else windows = [] end - return new(positions, seismograms, observed, invcov, windows) + return new{T}(positions, seismograms, observed, invcov, windows) end end @@ -76,7 +76,7 @@ Type representing a multi-receiver configuration for a wave propagation shot. $(TYPEDFIELDS) """ # What about using the package ComputedFieldTypes.jl? @computed ... -struct VectorReceivers{N, T <: Real} <: Receivers +struct VectorReceivers{T,N} <: Receivers "Receiver positions" positions::Matrix{T} "Array holding seismograms (as columns)" @@ -86,18 +86,13 @@ struct VectorReceivers{N, T <: Real} <: Receivers "Inverse of the covariance matrix" invcov::AbstractMatrix{T} - @doc raw""" - Receivers[{T<:Real = Float64}](positions::Matrix{<:Real}, nt::Int, observed::Union{Matrix{T}, Nothing} = nothing) - - Create a single shot wave propagation receivers configuration from receivers positions. - """ - function VectorReceivers{N, T}( + function VectorReceivers( positions::Matrix{T}, - nt::Integer, - ndim::Integer=2; + nt::Int, + ndim::Int=2; observed::Union{Array{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing - ) where {N, T <: Real} + ) where {T} @assert size(positions, 1) > 0 "There must be at least one receiver!" seismograms = zeros(T, nt, ndim, size(positions, 1)) ## N+1 !!! <<<<<<<<--------------<<<< if observed !== nothing @@ -110,9 +105,9 @@ struct VectorReceivers{N, T <: Real} <: Receivers else invcov = zeros(0, 0) end - return new{ndim, T}(positions, seismograms, observed, invcov) + return new{T, ndim}(positions, seismograms, observed, invcov) end end # Default type constructor -VectorReceivers(positions, nt, ndim; observed=nothing, invcov=nothing) = VectorReceivers{ndim, Float64}(positions, nt, ndim; observed=observed, invcov=invcov) +# VectorReceivers(positions, nt, ndim; observed=nothing, invcov=nothing) = VectorReceivers{ndim, Float64}(positions, nt, ndim; observed=observed, invcov=invcov) diff --git a/src/shot.jl b/src/shot.jl index 08868b0..0814db1 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -22,7 +22,7 @@ function init_shot!(model::WaveSimul, shot::Shot; kwargs...) init_bdc!(model, shot.srcs) end -@views function find_nearest_grid_points(model::WaveSimul, positions::Matrix{<:Real})::Matrix{<:Int} +@views function find_nearest_grid_points(model::WaveSimul{T}, positions::Matrix{T})::Matrix{Int} where {T} # source time functions nsrcs = size(positions, 1) # number of sources ncoos = size(positions, 2) # number of coordinates diff --git a/src/solve.jl b/src/solve.jl index e8305f8..f7014ef 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -1,6 +1,6 @@ ### UPDATE MATERIAL PROPERTIES ## -@views function set_wavesim_matprop!(wavesim::WaveSimul{N}, matprop::MaterialProperties{T, N}) where {T, N} +@views function set_wavesim_matprop!(wavesim::WaveSimul{T,N}, matprop::MaterialProperties{T, N}) where {T, N} @debug "Checking new material properties" check_matprop(wavesim, matprop) @debug "Updating WaveSimul material properties" @@ -11,7 +11,7 @@ end ## single WaveSimul object @views function run_swforward!( - wavsim::WaveSimul{N}, + wavsim::WaveSimul{T,N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; )::Union{Vector{Array}, Nothing} where {T, N} @@ -56,7 +56,7 @@ end ## :threadpersrc, multiple WaveSimul objects @views function run_swforward!( - wavsim::Vector{<:WaveSimul{N}}, + wavsim::Vector{<:WaveSimul{T,N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; )::Union{Vector{Array}, Nothing} where {T, N} @@ -115,7 +115,7 @@ end ## single or multiple WaveSimul objects @views function run_swmisfit!( - wavsim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, + wavsim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; misfit::AbstractMisfit=L2Misfit(nothing) @@ -145,7 +145,7 @@ end ## single WaveSimul object @views function run_swgradient!( - wavsim::WaveSimul{N}, + wavsim::WaveSimul{T,N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; compute_misfit::Bool=false, @@ -188,7 +188,7 @@ end ## :threadpersrc, multiple WaveSimul objects @views function run_swgradient!( - wavsim::Vector{<:WaveSimul{N}}, + wavsim::Vector{<:WaveSimul{T,N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; compute_misfit::Bool=false, diff --git a/src/sources.jl b/src/sources.jl index 1ddae82..a9da25e 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -5,20 +5,20 @@ Type representing a multi-source configuration for a wave propagation shot. $(TYPEDFIELDS) """ -struct ScalarSources{T <: Real} <: Sources +struct ScalarSources{T} <: Sources "Source positions" - positions::Matrix{<:Real} + positions::Matrix{T} "Source time function" tf::Matrix{T} "Dominant frequency" domfreq::T @doc """ - ScalarSources{T}(positions::Matrix{<:Real}, tf::Matrix{T}, domfreq::T) where {T <: Real} + ScalarSources{T}(positions::Matrix{T}, tf::Matrix{T}, domfreq::T) where {T} Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function ScalarSources{T}(positions::Matrix{<:Real}, tf::Matrix{T}, domfreq::T) where {T <: Real} + function ScalarSources{T}(positions::Matrix{T}, tf::Matrix{T}, domfreq::T) where {T} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" return new(positions, tf, domfreq) @@ -39,7 +39,7 @@ ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, do """ Type representing vector components of a 2D moment tensor. """ -Base.@kwdef struct MomentTensor2D{T <: Real} <: MomentTensor +Base.@kwdef struct MomentTensor2D{T} <: MomentTensor{T} Mxx::Vector{T} Mzz::Vector{T} Mxz::Vector{T} @@ -48,7 +48,7 @@ end """ Type representing vector components of a 2D moment tensor. """ -Base.@kwdef struct MomentTensor3D{T <: Real} <: MomentTensor +Base.@kwdef struct MomentTensor3D{T} <: MomentTensor{T} Mxx::Vector{T} Myy::Vector{T} Mzz::Vector{T} @@ -60,23 +60,23 @@ end """ Type representing a multi-source configuration for a wave propagation shot. """ -struct MomentTensorSources{N, T <: Real} <: Sources +struct MomentTensorSources{N, T} <: Sources positions::Matrix{T} tf::Matrix{T} - momtens::MomentTensor + momtens::MomentTensor{T} domfreq::T @doc """ - MomentTensorSources{T<:Real}( - positions::Matrix{<:Real}, - tf::Matrix{<:T}, - momtens::MomentTensor2D + MomentTensorSources{T}( + positions::Matrix{T}, + tf::Matrix{T}, + momtens::MomentTensor domfreq::T ) Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function MomentTensorSources{N, T}(positions::Matrix{T}, tf::Matrix{T}, momtens::MomentTensor, domfreq::T) where {N, T <: Real} + function MomentTensorSources{N, T}(positions::Matrix{T}, tf::Matrix{T}, momtens::MomentTensor{T}, domfreq::T) where {N, T} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" if N == 2 diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl index fce6976..7bbbb53 100644 --- a/src/srcrec_interpolation.jl +++ b/src/srcrec_interpolation.jl @@ -43,7 +43,7 @@ Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or r - `npts` (optional): half-number of grid points for the window - `beta` (optional): 'beta' parameter for the Kaiser windowing function """ -function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::Integer; +function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::Int; npts::Int64=4, beta::Union{Nothing, Real}=nothing) ## Coefficients for sinc interpolation ## in 1D @@ -116,7 +116,7 @@ Compute 2-D coefficients for windowed (Kaiser) sync interpolation of source or r - `beta` (optional): 'beta' parameter for the Kaiser windowing function """ function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter::Real, zcenter::Real, - nx::Integer, nz::Integer, kind::Vector{Symbol}; + nx::Int, nz::Int, kind::Vector{Symbol}; npts::Int64=4, beta::Union{Nothing, Real}=nothing) ## Calculate the 2D array of coefficients diff --git a/src/utils.jl b/src/utils.jl index ce92a45..202b23a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -37,7 +37,7 @@ $(TYPEDSIGNATURES) Compute an optimal distribution of tasks (nsrc) for a given number of workers (threads). Returns a vector of UnitRange object. """ -function distribsrcs(nsrc::Integer, nw::Integer) +function distribsrcs(nsrc::Int, nw::Int) ## calculate how to subdivide the srcs among the workers if nsrc >= nw dis = div(nsrc, nw) diff --git a/src/wrappers.jl b/src/wrappers.jl index 2a58c3a..2b8c34a 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -56,7 +56,7 @@ Return a vector of snapshots for every shot if snapshotting is enabled. See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments -- `wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `wavesim::Union{WaveSimul{T,N},Vector{<:WaveSimul{T,N}}}`: input `WaveSimul` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -69,7 +69,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function swforward!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swforward!(wavesim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() @@ -106,11 +106,11 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). function swmisfit!( params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; #<:Pair{<:Sources{<:Real}, <:Receivers{<:Real}}}; + shots::Vector{<:Shot}; parall::Symbol=:threads, misfit::AbstractMisfit=L2Misfit(nothing), logger::Union{Nothing, AbstractLogger}=nothing -)::Real where {T, N} +)::T where {T, N} if logger === nothing logger = current_logger() end @@ -129,7 +129,7 @@ $(TYPEDSIGNATURES) Return the misfit w.r.t. observed data by running a forward simulation using the given `WaveSimul` object as an input. # Positional arguments -- `wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `wavesim::Union{WaveSimul{T,N},Vector{<:WaveSimul{T,N}}}`: input `WaveSimul` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -144,7 +144,7 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ -function swmisfit!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swmisfit!(wavesim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() @@ -184,7 +184,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `check_freq::Union{Int, Nothing} = nothing`: if specified, enables checkpointing and specifies the checkpointing frequency. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. - `compute_misfit::Bool = false`: if true, also computes and return misfit value. -- `smooth_radius::Integer = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. +- `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ function swgradient!( @@ -196,9 +196,9 @@ function swgradient!( infoevery::Union{Int, Nothing}=nothing, compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing), - smooth_radius::Integer=5, + smooth_radius::Int=5, logger::Union{Nothing, AbstractLogger}=nothing -)::Union{AbstractArray, Tuple{AbstractArray, Real}} where {T, N} +)::Union{AbstractArray, Tuple{AbstractArray, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -225,7 +225,7 @@ Bigger values speed up computation at the cost of using more memory. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). # Positional arguments -- `wavesim::Union{WaveSimul{N},Vector{<:WaveSimul{N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `wavesim::Union{WaveSimul{T,N},Vector{<:WaveSimul{T,N}}}`: input `WaveSimul` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -238,10 +238,10 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `check_freq::Union{Int, Nothing} = nothing`: if specified, enables checkpointing and specifies the checkpointing frequency. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. - `compute_misfit::Bool = false`: if true, also computes and return misfit value. -- `smooth_radius::Integer = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. +- `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ -function swgradient!(wavesim::Union{WaveSimul{N}, Vector{<:WaveSimul{N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swgradient!(wavesim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() @@ -269,9 +269,9 @@ Builds a wave similation based on the input paramters `params` and keyword argum - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` - `gradient::Bool = false`: whether the wave simulation is used for gradients computations. -- `check_freq::Union{<:Integer, Nothing} = nothing`: if `gradient = true` and if specified, enables checkpointing and specifies the checkpointing frequency. -- `snapevery::Union{<:Integer, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). -- `infoevery::Union{<:Integer, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. +- `check_freq::Union{<:Int, Nothing} = nothing`: if `gradient = true` and if specified, enables checkpointing and specifies the checkpointing frequency. +- `snapevery::Union{<:Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). +- `infoevery::Union{<:Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ function build_wavesim(params::InputParameters{T, N}, matprop::MaterialProperties{T, N}; parall::Symbol, kwargs...) where {T, N} if parall == :threadpersrc @@ -307,7 +307,7 @@ build_concrete_wavesim( cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... -) where {T,N} = AcousticVDStaggeredCPMLWaveSimul{N}( +) where {T,N} = AcousticVDStaggeredCPMLWaveSimul( params.gridsize, params.gridspacing, params.ntimesteps, @@ -325,7 +325,7 @@ build_concrete_wavesim( cpmlparams::CPMLBoundaryConditionParameters; parall, kwargs... -) where {T,N} = ElasticIsoCPMLWaveSimul{N}( +) where {T,N} = ElasticIsoCPMLWaveSimul( params.gridsize, params.gridspacing, params.ntimesteps, From 1dc1e823880c8a78db2719c1df6ca20fc5144737 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 2 Jul 2024 10:11:11 +0200 Subject: [PATCH 048/111] Renaming --- src/HMCseiswaves.jl | 2 +- src/SeismicWaves.jl | 2 +- src/abstract_types.jl | 6 +- src/checks.jl | 14 ++--- src/models/acoustic/acou_abstract_types.jl | 2 +- src/models/backend_selection.jl | 4 +- src/models/elastic/ela_abstract_types.jl | 2 +- src/receivers.jl | 19 ++---- src/shot.jl | 4 +- src/solve.jl | 34 +++++------ src/sources.jl | 71 +++++++--------------- src/traits/grid.jl | 4 +- src/traits/shooting.jl | 4 +- src/traits/snappable.jl | 8 +-- src/wrappers.jl | 18 +++--- 15 files changed, 79 insertions(+), 115 deletions(-) diff --git a/src/HMCseiswaves.jl b/src/HMCseiswaves.jl index bd5383e..71b5941 100644 --- a/src/HMCseiswaves.jl +++ b/src/HMCseiswaves.jl @@ -24,7 +24,7 @@ export AcouWavCDProb ## create the problem type for traveltime tomography struct AcouWavCDProb - #wavesim::WaveSimul + #wavesim::WaveSimulation inpars::InputParametersAcoustic shots::Vector{<:Shot} #invCovds::Vector{<:AbstractMatrix{Float64}} parall::Symbol diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 9e9ea96..b458b1f 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -11,7 +11,7 @@ using Logging using DocStringExtensions # main struct for wave simulation -export WaveSimul +export WaveSimulation export build_wavesim # input parameters export InputParametersAcoustic, InputParametersElastic diff --git a/src/abstract_types.jl b/src/abstract_types.jl index c53cae2..b43106b 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -4,7 +4,7 @@ $(TYPEDEF) Abstract type for wave simulations. """ -abstract type WaveSimul{T, N} end +abstract type WaveSimulation{T, N} end abstract type InputParameters{T, N} end @@ -12,9 +12,9 @@ abstract type InputBoundaryConditionParameters{T} end abstract type MaterialProperties{T, N} end -abstract type Sources end +abstract type Sources{T} end -abstract type Receivers end +abstract type Receivers{T} end abstract type MomentTensor{T} end diff --git a/src/checks.jl b/src/checks.jl index 9509652..eb13e92 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -1,5 +1,5 @@ -function check_sim_consistency(wavsim::WaveSimul{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}) where {T, N} +function check_sim_consistency(wavsim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}) where {T, N} tysource = typeof(shots[1].srcs) tyreceiver = typeof(shots[1].recs) @@ -10,7 +10,7 @@ function check_sim_consistency(wavsim::WaveSimul{T, N}, matprop::MaterialPropert end end - # Check that the subtypes of WaveSimul, MaterialProperties and Shot are consistent + # Check that the subtypes of WaveSimulation, MaterialProperties and Shot are consistent if wavsim isa AcousticCDCPMLWaveSimul{T, N, <:AbstractArray{T, N}} && matprop isa VpAcousticCDMaterialProperties{T, N} && tysource <: ScalarSources && @@ -30,11 +30,11 @@ function check_sim_consistency(wavsim::WaveSimul{T, N}, matprop::MaterialPropert return end - return error("Types of WaveSimul, MaterialProperties and Sources/Receivers are inconsistent \ + return error("Types of WaveSimulation, MaterialProperties and Sources/Receivers are inconsistent \ \n $(typeof(wavsim)), \n $(typeof(matprop)), \n $(typeof(shots[1].srcs)), $(typeof(shots[1].recs))") end -function check_shot(model::WaveSimul, shot::Shot; kwargs...) +function check_shot(model::WaveSimulation, shot::Shot; kwargs...) # @debug "Checking model/shot numerics" # check_numerics(model, shot; kwargs...) # @debug "Checking sources positions" @@ -48,7 +48,7 @@ check_positions(model, positions) = check_positions(BoundaryConditionTrait(model function check_positions( ::ReflectiveBoundaryCondition, - model::WaveSimul{T}, + model::WaveSimulation{T}, positions::Matrix{T} ) where {T} ndimwavsim = length(model.gridspacing) @@ -65,7 +65,7 @@ end function check_positions( ::CPMLBoundaryCondition, - model::WaveSimul{T}, + model::WaveSimulation{T}, positions::Matrix{T} ) where {T} check_positions(ReflectiveBoundaryCondition(), model, positions) @@ -85,4 +85,4 @@ function check_positions( return end -check_invcov_matrix(model::WaveSimul{T}, invcov::AbstractMatrix{T}) where {T} = @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" +check_invcov_matrix(model::WaveSimulation{T}, invcov::AbstractMatrix{T}) where {T} = @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" diff --git a/src/models/acoustic/acou_abstract_types.jl b/src/models/acoustic/acou_abstract_types.jl index e2e1658..3156746 100644 --- a/src/models/acoustic/acou_abstract_types.jl +++ b/src/models/acoustic/acou_abstract_types.jl @@ -1,5 +1,5 @@ -abstract type AcousticWaveSimul{T,N} <: WaveSimul{T,N} end +abstract type AcousticWaveSimul{T,N} <: WaveSimulation{T,N} end abstract type AcousticCDWaveSimul{T,N} <: AcousticWaveSimul{T,N} end diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index 0629474..d19adee 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -1,11 +1,11 @@ -select_backend(wavesim_type::Type{<:WaveSimul}, parall::Symbol) = +select_backend(wavesim_type::Type{<:WaveSimulation}, parall::Symbol) = select_backend(BoundaryConditionTrait(wavesim_type), GridTrait(wavesim_type), wavesim_type, Val{parall}) function select_backend( ::BoundaryConditionTrait, ::GridTrait, - wavesim_type::Type{<:WaveSimul}, + wavesim_type::Type{<:WaveSimulation}, ::Type{Val{parall}} ) where {parall} parasym = [:serial, :threads, :GPU, :threadpersrc] diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index 33aa944..7305590 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -1,5 +1,5 @@ -abstract type ElasticWaveSimul{T,N} <: WaveSimul{T,N} end +abstract type ElasticWaveSimul{T,N} <: WaveSimulation{T,N} end abstract type ElasticIsoWaveSimul{T,N} <: ElasticWaveSimul{T,N} end diff --git a/src/receivers.jl b/src/receivers.jl index 6f25999..1b5c2c3 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -5,7 +5,7 @@ Type representing a multi-receiver configuration for a wave propagation shot. $(TYPEDFIELDS) """ -struct ScalarReceivers{T} <: Receivers +struct ScalarReceivers{T} <: Receivers{T} "Receiver positions" positions::Matrix{T} "Array holding seismograms (as columns)" @@ -18,7 +18,7 @@ struct ScalarReceivers{T} <: Receivers windows::Vector{Pair{Int, Int}} @doc """ - ScalarReceivers{T}( + ScalarReceivers( positions::Matrix{T}, nt::Int; observed::Union{Matrix{T}, Nothing}=nothing, @@ -58,15 +58,7 @@ struct ScalarReceivers{T} <: Receivers end end -# Default type constructor -@doc """ -$(SIGNATURES) - -Create a single shot wave propagation receivers configuration from receivers positions. -Default constructor for Float64. -""" -ScalarReceivers(positions, nt; observed=nothing, invcov=nothing, windows=nothing) = - ScalarReceivers{Float64}(positions, nt; observed=observed, invcov=invcov, windows=windows) +############################################################################ @doc """ $(TYPEDEF) @@ -76,7 +68,7 @@ Type representing a multi-receiver configuration for a wave propagation shot. $(TYPEDFIELDS) """ # What about using the package ComputedFieldTypes.jl? @computed ... -struct VectorReceivers{T,N} <: Receivers +struct VectorReceivers{T,N} <: Receivers{T} "Receiver positions" positions::Matrix{T} "Array holding seismograms (as columns)" @@ -108,6 +100,3 @@ struct VectorReceivers{T,N} <: Receivers return new{T, ndim}(positions, seismograms, observed, invcov) end end - -# Default type constructor -# VectorReceivers(positions, nt, ndim; observed=nothing, invcov=nothing) = VectorReceivers{ndim, Float64}(positions, nt, ndim; observed=observed, invcov=invcov) diff --git a/src/shot.jl b/src/shot.jl index 0814db1..8572569 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -15,14 +15,14 @@ end ################################################## -function init_shot!(model::WaveSimul, shot::Shot; kwargs...) +function init_shot!(model::WaveSimulation, shot::Shot; kwargs...) # Check shot configuration check_shot(model, shot; kwargs...) # Initialize boundary conditions based on current shot init_bdc!(model, shot.srcs) end -@views function find_nearest_grid_points(model::WaveSimul{T}, positions::Matrix{T})::Matrix{Int} where {T} +@views function find_nearest_grid_points(model::WaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} # source time functions nsrcs = size(positions, 1) # number of sources ncoos = size(positions, 2) # number of coordinates diff --git a/src/solve.jl b/src/solve.jl index f7014ef..5a6b2c4 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -1,17 +1,17 @@ ### UPDATE MATERIAL PROPERTIES ## -@views function set_wavesim_matprop!(wavesim::WaveSimul{T,N}, matprop::MaterialProperties{T, N}) where {T, N} +@views function set_wavesim_matprop!(wavesim::WaveSimulation{T,N}, matprop::MaterialProperties{T, N}) where {T, N} @debug "Checking new material properties" check_matprop(wavesim, matprop) - @debug "Updating WaveSimul material properties" + @debug "Updating WaveSimulation material properties" update_matprop!(wavesim, matprop) end ### FORWARDS ### -## single WaveSimul object +## single WaveSimulation object @views function run_swforward!( - wavsim::WaveSimul{T,N}, + wavsim::WaveSimulation{T,N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; )::Union{Vector{Array}, Nothing} where {T, N} @@ -54,9 +54,9 @@ end return nothing end -## :threadpersrc, multiple WaveSimul objects +## :threadpersrc, multiple WaveSimulation objects @views function run_swforward!( - wavsim::Vector{<:WaveSimul{T,N}}, + wavsim::Vector{<:WaveSimulation{T,N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; )::Union{Vector{Array}, Nothing} where {T, N} @@ -85,9 +85,9 @@ end # Shots loop nshots = length(shots) grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange - # loop on the set of WaveSimul + # loop on the set of WaveSimulation Threads.@threads for w in 1:nwsim - # loop on the subset of shots per each WaveSimul + # loop on the subset of shots per each WaveSimulation for s in grpshots[w] @info "Shot #$s" singleshot = shots[s] @@ -113,9 +113,9 @@ end ### MISFITS ### -## single or multiple WaveSimul objects +## single or multiple WaveSimulation objects @views function run_swmisfit!( - wavsim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, + wavsim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; misfit::AbstractMisfit=L2Misfit(nothing) @@ -128,7 +128,7 @@ end totmisfitval = 0 for singleshot in shots @debug "Checking invcov matrix" - if typeof(wavsim) <: Vector{<:WaveSimul} + if typeof(wavsim) <: Vector{<:WaveSimulation} for i in eachindex(wavsim) check_invcov_matrix(wavsim[i], singleshot.recs.invcov) end @@ -143,9 +143,9 @@ end ### GRADIENTS ### -## single WaveSimul object +## single WaveSimulation object @views function run_swgradient!( - wavsim::WaveSimul{T,N}, + wavsim::WaveSimulation{T,N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; compute_misfit::Bool=false, @@ -186,9 +186,9 @@ end return compute_misfit ? (totgrad, totmisfitval) : totgrad end -## :threadpersrc, multiple WaveSimul objects +## :threadpersrc, multiple WaveSimulation objects @views function run_swgradient!( - wavsim::Vector{<:WaveSimul{T,N}}, + wavsim::Vector{<:WaveSimulation{T,N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; compute_misfit::Bool=false, @@ -220,9 +220,9 @@ end # Shots loop grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange - # loop on the set of WaveSimul + # loop on the set of WaveSimulation Threads.@threads for w in 1:nwsim - # loop on the subset of shots per each WaveSimul + # loop on the subset of shots per each WaveSimulation for s in grpshots[w] singleshot = shots[s] @info "Shot #$s" diff --git a/src/sources.jl b/src/sources.jl index a9da25e..0c27e54 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -5,7 +5,7 @@ Type representing a multi-source configuration for a wave propagation shot. $(TYPEDFIELDS) """ -struct ScalarSources{T} <: Sources +struct ScalarSources{T} <: Sources{T} "Source positions" positions::Matrix{T} "Source time function" @@ -14,90 +14,65 @@ struct ScalarSources{T} <: Sources domfreq::T @doc """ - ScalarSources{T}(positions::Matrix{T}, tf::Matrix{T}, domfreq::T) where {T} + ScalarSources(positions::Matrix{T}, tf::Matrix{T}, domfreq::T) where {T} Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function ScalarSources{T}(positions::Matrix{T}, tf::Matrix{T}, domfreq::T) where {T} + function ScalarSources(positions::Matrix{T}, tf::Matrix{T}, domfreq::T) where {T} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" - return new(positions, tf, domfreq) + return new{T}(positions, tf, domfreq) end end -# Default type constructor {Float64} -@doc """ -$(SIGNATURES) - -Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. -Default type constructor for Float64. -""" -ScalarSources(positions, tf, domfreq) = ScalarSources{Float64}(positions, tf, domfreq) - #################################################### """ -Type representing vector components of a 2D moment tensor. +Type representing components of a 2D moment tensor. """ Base.@kwdef struct MomentTensor2D{T} <: MomentTensor{T} - Mxx::Vector{T} - Mzz::Vector{T} - Mxz::Vector{T} + Mxx::T + Mzz::T + Mxz::T end """ -Type representing vector components of a 2D moment tensor. +Type representing components of a 3D moment tensor. """ Base.@kwdef struct MomentTensor3D{T} <: MomentTensor{T} - Mxx::Vector{T} - Myy::Vector{T} - Mzz::Vector{T} - Mxy::Vector{T} - Mxz::Vector{T} - Myz::Vector{T} + Mxx::T + Myy::T + Mzz::T + Mxy::T + Mxz::T + Myz::T end """ Type representing a multi-source configuration for a wave propagation shot. """ -struct MomentTensorSources{N, T} <: Sources +struct MomentTensorSources{T, M <: MomentTensor{T}} <: Sources{T} positions::Matrix{T} tf::Matrix{T} - momtens::MomentTensor{T} + momtens::Vector{M} domfreq::T @doc """ - MomentTensorSources{T}( + MomentTensorSources( positions::Matrix{T}, tf::Matrix{T}, - momtens::MomentTensor + momtens::Vector{M} domfreq::T - ) + ) where {T, M <: MomentTensor{T}} Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function MomentTensorSources{N, T}(positions::Matrix{T}, tf::Matrix{T}, momtens::MomentTensor{T}, domfreq::T) where {N, T} + function MomentTensorSources(positions::Matrix{T}, tf::Matrix{T}, momtens::Vector{M}, domfreq::T) where {T, M <: MomentTensor{T}} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" - if N == 2 - @assert typeof(momtens) <: MomentTensor2D - elseif N == 3 - @assert typeof(momtens) <: MomentTensor3D - else - error("MomentTensorSources: Moment tensor neither 2D nor 3D.") - end - return new{N, T}(positions, tf, momtens, domfreq) - end -end - -# Default type constructor {Float64} -MomentTensorSources(positions, tf, momtens, domfreq) = begin - if typeof(momtens) <: MomentTensor2D - ndim = 2 - elseif typeof(momtens) <: MomentTensor3D - ndim = 3 + @assert length(momtens) == size(positions, 1) + return new{T, M}(positions, tf, momtens, domfreq) end - MomentTensorSources{ndim, Float64}(positions, tf, momtens, domfreq) end #################################################### diff --git a/src/traits/grid.jl b/src/traits/grid.jl index dc215b1..eeeb317 100644 --- a/src/traits/grid.jl +++ b/src/traits/grid.jl @@ -21,10 +21,10 @@ GridTrait(::Type) = error("GridTrait not implemented for type $(x)") # Reduce functions -get_maximum_func(model::WaveSimul) = get_maximum_func(GridTrait(model)) +get_maximum_func(model::WaveSimulation) = get_maximum_func(GridTrait(model)) get_maximum_func(::LocalGrid) = Base.maximum # get_maximum_func(::GlobalGrid) = (x -> (max_l = maximum(x); MPI.Allreduce(max_l, MPI.MAX, MPI.COMM_WORLD))) -get_minimum_func(model::WaveSimul) = get_minimum_func(GridTrait(model)) +get_minimum_func(model::WaveSimulation) = get_minimum_func(GridTrait(model)) get_minimum_func(::LocalGrid) = Base.minimum # get_minimum_func(::GlobalGrid) = (x -> (min_l = minimum(x); MPI.Allreduce(min_l, MPI.MIN, MPI.COMM_WORLD))) diff --git a/src/traits/shooting.jl b/src/traits/shooting.jl index e0effce..467d1fb 100644 --- a/src/traits/shooting.jl +++ b/src/traits/shooting.jl @@ -17,5 +17,5 @@ struct DistributedShooting <: ShootingTrait end ShootingTrait(x) = ShootingTrait(typeof(x)) ShootingTrait(::Type) = error("ShootingTrait not implemented for type $(x)") -# Default constructor for a WaveSimul -ShootingTrait(::Type{<:WaveSimul}) = SequentialShooting() +# Default constructor for a WaveSimulation +ShootingTrait(::Type{<:WaveSimulation}) = SequentialShooting() diff --git a/src/traits/snappable.jl b/src/traits/snappable.jl index 8f4de1c..88a4777 100644 --- a/src/traits/snappable.jl +++ b/src/traits/snappable.jl @@ -16,12 +16,12 @@ struct UnSnappable <: IsSnappableTrait end IsSnappableTrait(x) = IsSnappableTrait(typeof(x)) IsSnappableTrait(::Type) = error("IsSnappableTrait not implemented for type $(x)") -# Default behaviour for a WaveSimul is UnSnappable -IsSnappableTrait(::Type{<:WaveSimul}) = UnSnappable() +# Default behaviour for a WaveSimulation is UnSnappable +IsSnappableTrait(::Type{<:WaveSimulation}) = UnSnappable() """ - snapenabled(model::WaveSimul) + snapenabled(model::WaveSimulation) Check if a model has snapping enabled. """ -snapenabled(model::WaveSimul) = isa(IsSnappableTrait(model), Snappable) && model.snapevery !== nothing +snapenabled(model::WaveSimulation) = isa(IsSnappableTrait(model), Snappable) && model.snapevery !== nothing diff --git a/src/wrappers.jl b/src/wrappers.jl index 2b8c34a..cc95782 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -50,13 +50,13 @@ end $(TYPEDSIGNATURES) -Compute forward simulation using a previously constructed `WaveSimul` object. +Compute forward simulation using a previously constructed `WaveSimulation` object. Return a vector of snapshots for every shot if snapshotting is enabled. See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments -- `wavesim::Union{WaveSimul{T,N},Vector{<:WaveSimul{T,N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -69,7 +69,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function swforward!(wavesim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() @@ -126,10 +126,10 @@ end $(TYPEDSIGNATURES) -Return the misfit w.r.t. observed data by running a forward simulation using the given `WaveSimul` object as an input. +Return the misfit w.r.t. observed data by running a forward simulation using the given `WaveSimulation` object as an input. # Positional arguments -- `wavesim::Union{WaveSimul{T,N},Vector{<:WaveSimul{T,N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -144,7 +144,7 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ -function swmisfit!(wavesim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() @@ -214,7 +214,7 @@ end $(TYPEDSIGNATURES) -Compute gradients w.r.t. model parameters using the *previously* built `WaveSimul`. This avoids re-initializing and re-allocating several arrays in case of multiple gradient calculations. +Compute gradients w.r.t. model parameters using the *previously* built `WaveSimulation`. This avoids re-initializing and re-allocating several arrays in case of multiple gradient calculations. The `check_freq` parameter controls the checkpoiting frequency for adjoint computation. If `nothing`, no checkpointing is performed. @@ -225,7 +225,7 @@ Bigger values speed up computation at the cost of using more memory. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). # Positional arguments -- `wavesim::Union{WaveSimul{T,N},Vector{<:WaveSimul{T,N}}}`: input `WaveSimul` object containing all required information to run the simulation. +- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). - `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). @@ -241,7 +241,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ -function swgradient!(wavesim::Union{WaveSimul{T,N}, Vector{<:WaveSimul{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} if logger === nothing logger = current_logger() From 4313d52ca94a437715413122c3d237f03369cc55 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 2 Jul 2024 14:13:03 +0200 Subject: [PATCH 049/111] Add support for different data types (not yet tested) swgradient!() now returns a dictionary with gradients for every material property (could be better but for now it is ok) --- .../constant_density/gradient_check_fd.jl | 2 +- .../variable_density/gradient_check_fd.jl | 2 +- src/SeismicWaves.jl | 5 +- src/models/acoustic/acou_gradient.jl | 19 +-- src/models/acoustic/acou_grid.jl | 53 ------- src/models/acoustic/acou_models.jl | 126 ++++++++------- .../backends/Acoustic1D_CD_CPML_GPU.jl | 2 +- .../backends/Acoustic1D_CD_CPML_Serial.jl | 2 +- .../backends/Acoustic1D_CD_CPML_Threads.jl | 2 +- .../backends/Acoustic1D_VD_CPML_GPU.jl | 2 +- .../backends/Acoustic1D_VD_CPML_Threads.jl | 2 +- .../backends/Acoustic2D_CD_CPML_GPU.jl | 3 +- .../backends/Acoustic2D_CD_CPML_Serial.jl | 2 +- .../backends/Acoustic2D_CD_CPML_Threads.jl | 3 +- .../backends/Acoustic2D_VD_CPML_GPU.jl | 2 +- .../backends/Acoustic2D_VD_CPML_Threads.jl | 2 +- .../backends/Acoustic3D_CD_CPML_GPU.jl | 3 +- .../backends/Acoustic3D_CD_CPML_Serial.jl | 2 +- .../backends/Acoustic3D_CD_CPML_Threads.jl | 3 +- .../acoustic/backends/shared/standard_xPU.jl | 12 +- src/models/cpmlcoeffs.jl | 146 +++++++++--------- src/models/elastic/ela_forward.jl | 2 +- src/models/elastic/ela_models.jl | 57 +++---- src/receivers.jl | 8 +- src/solve.jl | 21 ++- src/srcrec_interpolation.jl | 4 +- src/wrappers.jl | 40 ++--- ...test_gradient_acoustic_constant_density.jl | 20 +-- ...test_gradient_acoustic_variable_density.jl | 18 ++- 29 files changed, 259 insertions(+), 306 deletions(-) delete mode 100644 src/models/acoustic/acou_grid.jl diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index 23e5fe1..b8293c2 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -94,7 +94,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss; compute swgradient!(wavesim, matprop_const, shots_obs; compute_misfit=true) end # save current gradient into file - serialize("adjgrad.dat", gradient) + serialize("adjgrad.dat", gradient["vp"]) println("Initial misfit: $misfit") diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index 5b3995e..7a9de42 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -109,7 +109,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) swgradient!(wavesim, matprop_const, shots_obs; compute_misfit=true) end # save gradient - serialize("grad.dat", gradient) + serialize("grad.dat", reshape(hcat(gradient["vp"], gradient["rho"]), nx, ny, 2)) println("Initial misfit: $misfit") diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index b458b1f..f33e942 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -53,10 +53,9 @@ include("grids/checkpointers.jl") # Acoustic include("models/acoustic/acou_abstract_types.jl") -include("models/acoustic/acou_grid.jl") include("models/acoustic/acou_material_properties.jl") -include("models/acoustic/acou_models.jl") include("models/acoustic/acou_params.jl") +include("models/acoustic/acou_models.jl") include("models/acoustic/acou_forward.jl") include("models/acoustic/acou_gradient.jl") include("models/acoustic/acou_init_bc.jl") @@ -64,8 +63,8 @@ include("models/acoustic/acou_init_bc.jl") # Elastic include("models/elastic/ela_abstract_types.jl") include("models/elastic/ela_material_properties.jl") -include("models/elastic/ela_models.jl") include("models/elastic/ela_params.jl") +include("models/elastic/ela_models.jl") include("models/elastic/ela_forward.jl") #include("models/elastic/ela_gradient.jl") include("models/elastic/ela_init_bc.jl") diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 76d56ba..d34362c 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -6,7 +6,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = model::AcousticCDWaveSimul{T,N}, shot::Shot, misfit -)::Array{T} where {T,N} +)::Dict{String, Array{T,N}} where {T,N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) @@ -93,7 +93,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = if misfit.regularization !== nothing gradient .+= dχ_dm(misfit.regularization, model.matprop) end - return gradient + return Dict("vp" => gradient) end @views function swgradient_1shot!( @@ -101,7 +101,7 @@ end model::AcousticVDStaggeredCPMLWaveSimul{T,N}, shot::Shot, misfit -)::Array{T} where {T,N} +)::Dict{String, Array{T,N}} where {T,N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) @@ -224,8 +224,8 @@ end model.backend.correlate_gradient_m1!(model.curgrad_m1_stag, adjvcur, pcur_corr, model.gridspacing) end # Allocate gradients - gradient_m0 = zeros(model.ns...) - gradient_m1 = zeros(model.ns...) + gradient_m0 = zeros(T, model.ns...) + gradient_m1 = zeros(T, model.ns...) # Get gradients copyto!(gradient_m0, model.curgrad_m0) for i in eachindex(model.curgrad_m1_stag) @@ -238,11 +238,8 @@ end # compute regularization if needed dχ_dvp, dχ_drho = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) # Rescale gradients with respect to material properties (chain rule) - return reshape( - hcat( - .-2.0 .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp - .-gradient_m0 ./ (model.matprop.vp .^ 2 .* model.matprop.rho .^ 2) .- gradient_m1 ./ model.matprop.rho .+ dχ_drho # grad wrt rho - ), - model.totgrad_size... + return Dict( + "vp" => .-2.0 .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp + "rho" => .-gradient_m0 ./ (model.matprop.vp .^ 2 .* model.matprop.rho .^ 2) .- gradient_m1 ./ model.matprop.rho .+ dχ_drho # grad wrt rho ) end diff --git a/src/models/acoustic/acou_grid.jl b/src/models/acoustic/acou_grid.jl deleted file mode 100644 index d25d173..0000000 --- a/src/models/acoustic/acou_grid.jl +++ /dev/null @@ -1,53 +0,0 @@ -# struct AcousticCDCheckpointing{N, T, A <: AbstractArray{T,N}} -# check_freq::Union{Int, Nothing} -# last_checkpoint::Int -# save_buffer::Vector{A} -# checkpoints::Dict{Int, A} -# checkpoints_ψ::Dict{Int, Vector{A}} -# checkpoints_ξ::Dict{Int, Vector{A}} - -# function AcousticCDCheckpointing( -# check_freq::Union{Int, Nothing}, -# nt::Int, -# ns::NTuple{N, Int}, -# grid::UniformFiniteDifferenceGrid{N,T}, -# backend::Module -# ) where {N,T,A} -# if check_freq !== nothing -# @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" -# @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" -# # Time step of last checkpoint -# last_checkpoint = floor(Int, nt / check_freq) * check_freq -# # Checkpointing arrays -# save_buffer = [backend.zeros(ns...) for _ in 1:(check_freq + 2)] # pressure window buffer -# checkpoints = Dict{Int, A}() # pressure checkpoints -# checkpoints_ψ = Dict{Int, Vector{A}}() # ψ arrays checkpoints -# checkpoints_ξ = Dict{Int, Vector{A}}() # ξ arrays checkpoints -# # Save initial conditions as first checkpoint -# checkpoints[-1] = copy(grid.fields["pold"]) -# checkpoints[0] = copy(grid.fields["pcur"]) -# checkpoints_ψ[0] = copy.(forward_grid.ψ) -# checkpoints_ξ[0] = copy.(forward_grid.ξ) -# # Preallocate future checkpoints -# for it in 1:(nt+1) -# if it % check_freq == 0 -# checkpoints[it] = backend.zeros(ns...) -# checkpoints[it-1] = backend.zeros(ns...) -# checkpoints_ψ[it] = copy.(forward_grid.ψ) -# checkpoints_ξ[it] = copy.(forward_grid.ξ) -# end -# end -# else # no checkpointing -# last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) -# save_buffer = [backend.zeros(ns...) for _ in 1:(nt + 2)] # save all timesteps (from -1 to nt+1 so nt+2) -# checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) -# checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) -# checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) -# end -# # Save first 2 timesteps in save buffer -# copyto!(save_buffer[1], forward_grid.pold) -# copyto!(save_buffer[2], forward_grid.pcur) - -# new{N,T,A}(check_freq, last_checkpoint, save_buffer, checkpoints, checkpoints_ψ, checkpoints_ξ) -# end -# end \ No newline at end of file diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 2cb1dcf..7be7e5b 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -47,9 +47,20 @@ end @views precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) +@views function init_gradient(model::AcousticCDWaveSimul{T,N})::Dict{String, Array{T, N}} where {T, N} + return Dict("vp" => zero(model.matprop.vp)) +end + +@views function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimul{T,N}) where {T, N, D <: Dict{String, Array{T, N}}} + totgrad["vp"] .+= curgrad["vp"] +end + ########################################################### -struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWaveSimul{T,N} +struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticCDWaveSimul{T,N} + # Parameters + params::InputParametersAcoustic{T, N} + cpmlparams::CPMLBoundaryConditionParameters{T} # Numerics nt::Int dt::T @@ -61,7 +72,6 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave freetop::Bool # Gradient computation setup gradient::Bool - totgrad_size::Union{Vector{Int}, Nothing} smooth_radius::Int # Snapshots snapevery::Union{Int, Nothing} @@ -71,27 +81,31 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave # Material properties matprop::VpAcousticCDMaterialProperties{T,N} # CPML coefficients - cpmlcoeffs::NTuple{N, CPMLCoefficients} + cpmlcoeffs::NTuple{N, CPMLCoefficients{T, V}} # Checkpointing setup checkpointer::LinearCheckpointer{T} # Parallelization type parall::Symbol function AcousticCDCPMLWaveSimul( - ns::NTuple{N, Int}, - gridspacing::NTuple{N, T}, - nt::Int, - dt::T, - halo::Int, - rcoef::T; + params::InputParametersAcoustic{T, N}, + matprop::VpAcousticCDMaterialProperties{T,N}, + cpmlparams::CPMLBoundaryConditionParameters{T}; parall::Symbol=:threads, - freetop::Bool=true, gradient::Bool=false, check_freq::Union{Int, Nothing}=nothing, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, smooth_radius::Int=5 ) where {T, N} + # Extract params + nt = params.ntimesteps + dt = params.dt + gridspacing = params.gridspacing + ns = params.gridsize + halo = cpmlparams.halo + freetop = cpmlparams.freeboundtop + rcoef = cpmlparams.rcoef # Check numerics @assert nt > 0 "Number of timesteps must be positive!" @assert dt > 0 "Timestep size must be positive!" @@ -103,25 +117,23 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave # Select backend backend = select_backend(AcousticCDCPMLWaveSimul{T, N}, parall) - A = backend.Data.Array{N} - V = backend.Data.Array{1} + A = backend.Data.Array{T, N} + V = backend.Data.Array{T, 1} # Initialize computational grid grid = UniformFiniteDifferenceGrid(ns, gridspacing) - # Initialize material properties - matprop = VpAcousticCDMaterialProperties(zeros(ns...)) # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, true) for _ in 1:N]...) + cpmlcoeffs = tuple([CPMLCoefficients{T, V}(halo, backend, true) for _ in 1:N]...) # Populate computational grid - addfield!(grid, "fact" => ScalarVariableField(backend.zeros(ns...))) - addfield!(grid, "pold" => ScalarVariableField(backend.zeros(ns...))) - addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(ns...))) - addfield!(grid, "pnew" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "fact" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "pold" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "pnew" => ScalarVariableField(backend.zeros(T, ns...))) if gradient - addfield!(grid, "grad_vp" => ScalarVariableField(backend.zeros(ns...))) - addfield!(grid, "adjold" => ScalarVariableField(backend.zeros(ns...))) - addfield!(grid, "adjcur" => ScalarVariableField(backend.zeros(ns...))) - addfield!(grid, "adjnew" => ScalarVariableField(backend.zeros(ns...))) + addfield!(grid, "grad_vp" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "adjold" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "adjcur" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "adjnew" => ScalarVariableField(backend.zeros(T, ns...))) end # CPML coefficients addfield!( @@ -140,26 +152,26 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave addfield!( grid, "ψ" => MultiVariableField( - cat([[backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) addfield!( grid, "ξ" => MultiVariableField( - cat([[backend.zeros([j == i ? halo : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) if gradient addfield!( grid, "ψ_adj" => MultiVariableField( - cat([[backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) addfield!( grid, "ξ_adj" => MultiVariableField( - cat([[backend.zeros([j == i ? halo : ns[j] for j in 1:N]...), backend.zeros([j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) end @@ -177,7 +189,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) # Initialize snapshots array - snapshots = (snapevery !== nothing ? [backend.zeros(ns...) for _ in 1:div(nt, snapevery)] : nothing) + snapshots = (snapevery !== nothing ? [backend.zeros(T, ns...) for _ in 1:div(nt, snapevery)] : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -185,7 +197,9 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - new{T, N, A}( + new{T, N, A, V}( + params, + cpmlparams, nt, dt, grid, @@ -193,7 +207,6 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}} <: AcousticCDWave rcoef, freetop, gradient, - gradient ? [ns...] : nothing, smooth_radius, snapevery, snapshots, @@ -227,6 +240,7 @@ end reset!(model.grid; except=["fact", "a_pml", "b_pml"]) reset!(model.checkpointer) end + ########################################################### # Traits for AcousticCDCPMLWaveSimul @@ -291,6 +305,15 @@ end end end +@views function init_gradient(model::AcousticVDStaggeredWaveSimul{T,N})::Dict{String, Array{T, N}} where {T, N} + return Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) +end + +@views function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimul{T,N}) where {T, N, D <: Dict{String, Array{T, N}}} + totgrad["vp"] .+= curgrad["vp"] + totgrad["rho"] .+= curgrad["rho"] +end + ########################################################### struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N} @@ -307,7 +330,6 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N freetop::Bool # Gradient computation setup gradient::Bool - totgrad_size::Union{Vector{Int}, Nothing} check_freq::Union{Int, Nothing} # Snapshots snapevery::Union{Int, Nothing} @@ -319,7 +341,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N # Material properties matprop::VpRhoAcousticVDMaterialProperties{T,N} # CPML coefficients - cpmlcoeffs::NTuple{N, CPMLCoefficients} + cpmlcoeffs::NTuple{N, CPMLCoefficients{T}} # Forward computation arrays fact_m0::Any fact_m1_stag::Any @@ -351,6 +373,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N gridspacing::NTuple{N, T}, nt::Int, dt::T, + matprop::VpRhoAcousticVDMaterialProperties{T,N}, halo::Int, rcoef::T; parall::Symbol=:threads, @@ -374,22 +397,21 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N # Compute model sizes domainextent = gridspacing .* (ns .- 1) - # Initialize material properties - matprop = VpRhoAcousticVDMaterialProperties(zeros(ns...), zeros(ns...)) # Select backend backend = select_backend(AcousticVDStaggeredCPMLWaveSimul{T,N}, parall) + V = backend.Data.Array{T, 1} # Initialize computational arrays - fact_m0 = backend.zeros(ns...) + fact_m0 = backend.zeros(T, ns...) fact_m1_stag = [] - pcur = backend.zeros(ns...) + pcur = backend.zeros(T, ns...) vcur = [] for i in 1:N stag_ns = [ns...] stag_ns[i] -= 1 - push!(fact_m1_stag, backend.zeros(stag_ns...)) - push!(vcur, backend.zeros(stag_ns...)) + push!(fact_m1_stag, backend.zeros(T, stag_ns...)) + push!(vcur, backend.zeros(T, stag_ns...)) end # Initialize CPML arrays ψ = [] @@ -399,11 +421,11 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N ξ_ns = [ns...] ψ_ns[i] = halo + 1 ξ_ns[i] = halo - append!(ψ, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + append!(ψ, [backend.zeros(T, ψ_ns...), backend.zeros(T, ψ_ns...)]) + append!(ξ, [backend.zeros(T, ξ_ns...), backend.zeros(T, ξ_ns...)]) end # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients(halo, backend, true) for _ in 1:N]...) + cpmlcoeffs = tuple([CPMLCoefficients{T, V}(halo, backend, true) for _ in 1:N]...) # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) a_coeffs = [] b_coeffs = [] @@ -413,18 +435,17 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N end # Initialize gradient arrays if needed if gradient - totgrad_size = [ns..., 2] # Current gradient arrays - curgrad_m0 = backend.zeros(ns...) + curgrad_m0 = backend.zeros(T, ns...) curgrad_m1_stag = [] # Adjoint arrays - adjpcur = backend.zeros(ns...) + adjpcur = backend.zeros(T, ns...) adjvcur = [] for i in 1:N stag_ns = [ns...] stag_ns[i] -= 1 - push!(adjvcur, backend.zeros(stag_ns...)) - push!(curgrad_m1_stag, backend.zeros(stag_ns...)) + push!(adjvcur, backend.zeros(T, stag_ns...)) + push!(curgrad_m1_stag, backend.zeros(T, stag_ns...)) end # Initialize CPML arrays ψ_adj = [] @@ -434,8 +455,8 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N ξ_ns = [ns...] ψ_ns[i] = halo + 1 ξ_ns[i] = halo - append!(ψ_adj, [backend.zeros(ψ_ns...), backend.zeros(ψ_ns...)]) - append!(ξ_adj, [backend.zeros(ξ_ns...), backend.zeros(ξ_ns...)]) + append!(ψ_adj, [backend.zeros(T, ψ_ns...), backend.zeros(T, ψ_ns...)]) + append!(ξ_adj, [backend.zeros(T, ξ_ns...), backend.zeros(T, ξ_ns...)]) end # Checkpointing setup if check_freq !== nothing @@ -444,7 +465,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N # Time step of last checkpoint last_checkpoint = floor(Int, nt / check_freq) * check_freq # Checkpointing arrays - save_buffer = backend.zeros(ns..., check_freq + 1) # pressure window buffer + save_buffer = backend.zeros(T, ns..., check_freq + 1) # pressure window buffer checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints checkpoints_v = Dict{Int, Vector{backend.Data.Array}}() # velocities checkpoints checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints @@ -457,7 +478,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N # Preallocate future checkpoints for it in 1:(nt+1) if it % check_freq == 0 - checkpoints[it] = backend.zeros(ns...) + checkpoints[it] = backend.zeros(T, ns...) checkpoints_v[it] = copy.(vcur) checkpoints_ψ[it] = copy.(ψ) checkpoints_ξ[it] = copy.(ξ) @@ -465,7 +486,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N end else # no checkpointing last_checkpoint = 0 # simulate a checkpoint at time step 0 - save_buffer = backend.zeros(ns..., nt + 1) # save all timesteps (from 0 to nt so nt+1) + save_buffer = backend.zeros(T, ns..., nt + 1) # save all timesteps (from 0 to nt so nt+1) checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) checkpoints_v = Dict{Int, Vector{backend.Data.Array}}() # velocities checkpoints (will remain empty) checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) @@ -476,7 +497,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N end # Initialize snapshots array - snapshots = (snapevery !== nothing ? backend.zeros(ns..., div(nt, snapevery)) : nothing) + snapshots = (snapevery !== nothing ? backend.zeros(T, ns..., div(nt, snapevery)) : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -494,7 +515,6 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N rcoef, freetop, gradient, - gradient ? totgrad_size : nothing, gradient ? check_freq : nothing, snapevery, snapshots, diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl index bccc9f4..3a27ef9 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl @@ -3,7 +3,7 @@ module Acoustic1D_CD_CPML_GPU using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences1D -@init_parallel_stencil(CUDA, Float64, 1) +@init_parallel_stencil(package=CUDA, ndims=1, inbound=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index f321622..0de4203 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -4,7 +4,7 @@ include("shared/smooth_gradient_1D.jl") # Dummy data module module Data -Array = Base.Array{Float64} +Array = Base.Array end ##### diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl index e16ca68..5344be0 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl @@ -2,7 +2,7 @@ module Acoustic1D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences1D -@init_parallel_stencil(Threads, Float64, 1) +@init_parallel_stencil(package=Threads, ndims=1, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl index 70d2ca6..dd63b89 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl @@ -5,7 +5,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences1D include("shared/fourth_order_FiniteDifferences1D.jl") -@init_parallel_stencil(CUDA, Float64, 1) +@init_parallel_stencil(package=CUDA, ndims=1, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl index 9ceea97..b7ed790 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl @@ -4,7 +4,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences1D include("shared/fourth_order_FiniteDifferences1D.jl") -@init_parallel_stencil(Threads, Float64, 1) +@init_parallel_stencil(package=Threads, ndims=1, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl index 4407276..80b46cc 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl @@ -3,7 +3,8 @@ module Acoustic2D_CD_CPML_GPU using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences2D -@init_parallel_stencil(CUDA, Float64, 2) + +@init_parallel_stencil(package=CUDA, ndims=2, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl index 365f0af..aeb7491 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl @@ -5,7 +5,7 @@ include("shared/smooth_gradient_2D.jl") # Dummy data module module Data -Array = Base.Array{Float64} +Array = Base.Array end # the backend needs these diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl index 72af6d0..01d6aa0 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl @@ -2,7 +2,8 @@ module Acoustic2D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences2D -@init_parallel_stencil(Threads, Float64, 2) + +@init_parallel_stencil(package=Threads, ndims=2, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl index ae50a5f..48b06b5 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl @@ -5,7 +5,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences2D include("shared/fourth_order_FiniteDifferences2D.jl") -@init_parallel_stencil(CUDA, Float64, 2) +@init_parallel_stencil(package=CUDA, ndims=2, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl index 66ec2d3..ffe5c37 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl @@ -4,7 +4,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences2D include("shared/fourth_order_FiniteDifferences2D.jl") -@init_parallel_stencil(Threads, Float64, 2) +@init_parallel_stencil(package=Threads, ndims=2, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl index a966036..d01df2b 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl @@ -3,7 +3,8 @@ module Acoustic3D_CD_CPML_GPU using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences3D -@init_parallel_stencil(CUDA, Float64, 3) + +@init_parallel_stencil(package=CUDA, ndims=3, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl index 6ca6ecd..24e22be 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl @@ -5,7 +5,7 @@ include("shared/smooth_gradient_3D.jl") # Dummy data module module Data -Array = Base.Array{Float64} +Array = Base.Array end # the backend needs these diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl index 86ed794..824159c 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl @@ -2,7 +2,8 @@ module Acoustic3D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences3D -@init_parallel_stencil(Threads, Float64, 3) + +@init_parallel_stencil(package=Threads, ndims=3, inbounds=true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/shared/standard_xPU.jl b/src/models/acoustic/backends/shared/standard_xPU.jl index 225cd00..3aede7c 100644 --- a/src/models/acoustic/backends/shared/standard_xPU.jl +++ b/src/models/acoustic/backends/shared/standard_xPU.jl @@ -1,8 +1,4 @@ -zeros(x) = @zeros(x) -ones(x) = @ones(x) -zeros(x, y) = @zeros(x, y) -ones(x, y) = @ones(x, y) -zeros(x, y, z) = @zeros(x, y, z) -ones(x, y, z) = @ones(x, y, z) -zeros(x, y, z, t) = @zeros(x, y, z, t) -ones(x, y, z, t) = @ones(x, y, z, t) +zeros(T, x...) = @zeros(x..., eltype=T) +ones(T, x...) = @ones(x..., eltype=T) +rand(T, x...) = @rand(x..., eltype=T) +fill(T, x...) = @rand(x..., eltype=T) \ No newline at end of file diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 1457198..724d0d6 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -1,39 +1,38 @@ -struct CPMLCoefficientsAxis - a::Any - a_h::Any - b::Any - b_h::Any - - function CPMLCoefficientsAxis(halo::Int, backend::Module, - sizehalfgrdplusone::Bool=false) +struct CPMLCoefficientsAxis{T, V <: AbstractVector{T}} + a::V + a_h::V + b::V + b_h::V + + function CPMLCoefficientsAxis{T, V}(halo::Int, backend::Module, sizehalfgrdplusone::Bool=false) where {T, V <: AbstractVector{T}} if sizehalfgrdplusone - return new( - backend.zeros(2 * halo), - backend.zeros(2 * (halo + 1) + 1), - backend.zeros(2 * halo), - backend.zeros(2 * (halo + 1) + 1) + return new{T, V}( + backend.zeros(T, 2 * halo), + backend.zeros(T, 2 * (halo + 1) + 1), + backend.zeros(T, 2 * halo), + backend.zeros(T, 2 * (halo + 1) + 1) ) else - return new( - backend.zeros(2 * halo), - backend.zeros(2 * (halo + 1)), - backend.zeros(2 * halo), - backend.zeros(2 * (halo + 1)) + return new{T, V}( + backend.zeros(T, 2 * halo), + backend.zeros(T, 2 * (halo + 1)), + backend.zeros(T, 2 * halo), + backend.zeros(T, 2 * (halo + 1)) ) end end end function compute_CPML_coefficientsAxis!( - cpmlcoeffs::CPMLCoefficientsAxis, - vel_max::Real, - dt::Real, + cpmlcoeffs::CPMLCoefficientsAxis{T, V}, + vel_max::T, + dt::T, halo::Int, - rcoef::Real, - thickness::Real, - f0::Real -) + rcoef::T, + thickness::T, + f0::T +) where {T, V <: AbstractVector{T}} # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) npower = 2.0 # CPML power coefficient @@ -49,39 +48,38 @@ end ################################################################# -struct CPMLCoefficients - a_l::Any - a_r::Any - a_hl::Any - a_hr::Any - b_l::Any - b_r::Any - b_hl::Any - b_hr::Any - - function CPMLCoefficients(halo::Int, backend::Module, - sizehalfgrdplusone::Bool=false) +struct CPMLCoefficients{T, V <: AbstractVector{T}} + a_l::V + a_r::V + a_hl::V + a_hr::V + b_l::V + b_r::V + b_hl::V + b_hr::V + + function CPMLCoefficients{T, V}(halo::Int, backend::Module, sizehalfgrdplusone::Bool=false) where {T, V <: AbstractVector{T}} if sizehalfgrdplusone - return new( - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo + 1), - backend.zeros(halo + 1), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo + 1), - backend.zeros(halo + 1) + return new{T, V}( + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo + 1), + backend.zeros(T, halo + 1), + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo + 1), + backend.zeros(T, halo + 1) ) else - return new( - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo), - backend.zeros(halo) + return new{T, V}( + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo), + backend.zeros(T, halo) ) end end @@ -89,13 +87,13 @@ end function calc_Kab_CPML_staggeredgrid( halo::Int, - dt::Float64, - npower::Float64, - d0::Float64, - alpha_max_pml::Float64, + dt::T, + npower::T, + d0::T, + alpha_max_pml::T, onwhere::Symbol; - K_max_pml::Union{Float64, Nothing}=nothing -)::Tuple{Array{<:Real}, Array{<:Real}, Array{<:Real}, Array{<:Real}} + K_max_pml::Union{T, Nothing}=nothing +)::Tuple{Array{T}, Array{T}, Array{T}, Array{T}} where {T} @assert halo >= 0.0 Kab_size = halo @@ -152,14 +150,14 @@ end ##################################### function compute_CPML_coefficients!( - cpmlcoeffs::CPMLCoefficients, - vel_max::Real, - dt::Real, + cpmlcoeffs::CPMLCoefficients{T, V}, + vel_max::T, + dt::T, halo::Int, - rcoef::Real, - thickness::Real, - f0::Real -) + rcoef::T, + thickness::T, + f0::T +) where {T, V <: AbstractVector{T}} # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) npower = 2.0 # CPML power coefficient @@ -184,13 +182,13 @@ end function calc_Kab_CPML( halo::Int, - dt::Float64, - npower::Float64, - d0::Float64, - alpha_max_pml::Float64, + dt::T, + npower::T, + d0::T, + alpha_max_pml::T, onwhere::String; - K_max_pml::Union{Float64, Nothing}=nothing -)::Tuple{Array{<:Real}, Array{<:Real}, Array{<:Real}, Array{<:Real}} + K_max_pml::Union{T, Nothing}=nothing +)::Tuple{Array{T}, Array{T}, Array{T}, Array{T}} where {T} @assert halo >= 0.0 Kab_size = halo diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 55a83ed..beb3f80 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -138,7 +138,7 @@ function spreadsrcrecinterp2D( maxnumcoeff = nloc * (2 * nptssinc + 1)^Ndim coeij_tmp = zeros(Int, maxnumcoeff, Ndim + 1) - coeval_tmp = zeros(maxnumcoeff) + coeval_tmp = zeros(T, maxnumcoeff) l = 0 for p in 1:nloc # extract x and z position for source or receiver p diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index f2eee22..23b63cb 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -74,14 +74,14 @@ struct Elasticψdomain2D{T <: AbstractFloat} gs1[1] = 2 * halo gs2[2] = 2 * halo - ψ_∂σxx∂x = backend.zeros(gs1...) - ψ_∂σxz∂z = backend.zeros(gs2...) - ψ_∂σxz∂x = backend.zeros(gs1...) - ψ_∂σzz∂z = backend.zeros(gs2...) - ψ_∂vx∂x = backend.zeros(gs1...) - ψ_∂vz∂z = backend.zeros(gs2...) - ψ_∂vz∂x = backend.zeros(gs1...) - ψ_∂vx∂z = backend.zeros(gs2...) + ψ_∂σxx∂x = backend.zeros(T, gs1...) + ψ_∂σxz∂z = backend.zeros(T, gs2...) + ψ_∂σxz∂x = backend.zeros(T, gs1...) + ψ_∂σzz∂z = backend.zeros(T, gs2...) + ψ_∂vx∂x = backend.zeros(T, gs1...) + ψ_∂vz∂z = backend.zeros(T, gs2...) + ψ_∂vz∂x = backend.zeros(T, gs1...) + ψ_∂vx∂z = backend.zeros(T, gs2...) T = eltype(ψ_∂σxx∂x) return new{T}(ψ_∂σxx∂x, @@ -154,6 +154,7 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} gridspacing::NTuple{N, T}, nt::Int, dt::T, + matprop::ElasticIsoMaterialProperties{T, N}, halo::Int, rcoef::T; parall::Symbol=:serial, @@ -179,26 +180,12 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} # Select backend backend = select_backend(ElasticIsoCPMLWaveSimul{T,N}, parall) - - # Initialize material properties - if N == 2 - matprop = ElasticIsoMaterialProperties2D(; λ=backend.zeros(gridsize...), - μ=backend.zeros(gridsize...), - ρ=backend.zeros(gridsize...), - λ_ihalf=backend.zeros((gridsize .- [1, 0])...), - μ_ihalf=backend.zeros((gridsize .- [1, 0])...), - μ_jhalf=backend.zeros((gridsize .- [0, 1])...), - ρ_ihalf_jhalf=backend.zeros((gridsize .- 1)...) - ) - - else - error("Only elastic 2D is currently implemented.") - end + V = backend.Data.Array{T, 1} # Initialize computational arrays if N == 2 - velpartic = Velpartic2D([backend.zeros(gridsize...) for _ in 1:N]...) # vx, vy[, vz] - stress = Stress2D([backend.zeros(gridsize...) for _ in 1:(N-1)*3]...) # vx, vy[, vz] + velpartic = Velpartic2D([backend.zeros(T, gridsize...) for _ in 1:N]...) # vx, vy[, vz] + stress = Stress2D([backend.zeros(T, gridsize...) for _ in 1:(N-1)*3]...) # vx, vy[, vz] end ## @@ -209,16 +196,16 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} end # Initialize CPML coefficients - cpmlcoeffs = [CPMLCoefficientsAxis(halo, backend) for _ in 1:N] + cpmlcoeffs = [CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N] # Initialize gradient arrays if needed if gradient error("Gradient for elastic calculations not yet implemented!") # # Current gradient array - # curgrad = backend.zeros(gridsize...) + # curgrad = backend.zeros(T, gridsize...) # # Adjoint arrays - # adj = backend.zeros(gridsize...) + # adj = backend.zeros(T, gridsize...) # # Initialize CPML arrays # ψ_adj = [] # ξ_adj = [] @@ -227,8 +214,8 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} # ξ_gridsize = [gridsize...] # ψ_gridsize[i] = halo + 1 # ξ_gridsize[i] = halo - # append!(ψ_adj, [backend.zeros(ψ_gridsize...), backend.zeros(ψ_gridsize...)]) - # append!(ξ_adj, [backend.zeros(ξ_gridsize...), backend.zeros(ξ_gridsize...)]) + # append!(ψ_adj, [backend.zeros(T, ψ_gridsize...), backend.zeros(T, ψ_gridsize...)]) + # append!(ξ_adj, [backend.zeros(T, ξ_gridsize...), backend.zeros(T, ξ_gridsize...)]) # end # # Checkpointing setup # if check_freq !== nothing @@ -237,7 +224,7 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} # # Time step of last checkpoint # last_checkpoint = floor(Int, nt / check_freq) * check_freq # # Checkpointing arrays - # save_buffer = backend.zeros(gridsize..., check_freq + 2) # pressure window buffer + # save_buffer = backend.zeros(T, gridsize..., check_freq + 2) # pressure window buffer # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints @@ -249,15 +236,15 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} # # Preallocate future checkpoints # for it in 1:(nt+1) # if it % check_freq == 0 - # checkpoints[it] = backend.zeros(gridsize...) - # checkpoints[it-1] = backend.zeros(gridsize...) + # checkpoints[it] = backend.zeros(T, gridsize...) + # checkpoints[it-1] = backend.zeros(T, gridsize...) # checkpoints_ψ[it] = copy.(ψ) # checkpoints_ξ[it] = copy.(ξ) # end # end # else # no checkpointing # last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) - # save_buffer = backend.zeros(gridsize..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) + # save_buffer = backend.zeros(T, gridsize..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) @@ -268,7 +255,7 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} end # Initialize snapshots array - snapshots = (snapevery !== nothing ? [zeros(gridsize..., div(nt, snapevery)) for _ in 1:N] : nothing) + snapshots = (snapevery !== nothing ? [zeros(T, gridsize..., div(nt, snapevery)) for _ in 1:N] : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it diff --git a/src/receivers.jl b/src/receivers.jl index 1b5c2c3..9d23c4e 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -40,12 +40,12 @@ struct ScalarReceivers{T} <: Receivers{T} if observed !== nothing @assert size(seismograms) == size(observed) "Size of observed data is not (# timesteps, # receivers)!" else - observed = zeros(0, 0) + observed = zeros(T, 0, 0) end if invcov !== nothing @assert size(invcov) == (nt, nt) "Size of invcov is not (# timesteps, # timesteps)!" else - invcov = zeros(0, 0) + invcov = zeros(T, 0, 0) end if windows !== nothing for wnd in windows @@ -90,12 +90,12 @@ struct VectorReceivers{T,N} <: Receivers{T} if observed !== nothing @assert size(seismograms) == size(observed) "Size of observed data is not (# timesteps, # receivers)!" else - observed = zeros(0, 0, 0) # (nt,ndim,npos) + observed = zeros(T, 0, 0, 0) # (nt,ndim,npos) end if invcov !== nothing @assert size(invcov) == (nt, nt) "Size of invcov is not (# timesteps, # timesteps)!" else - invcov = zeros(0, 0) + invcov = zeros(T, 0, 0) end return new{T, ndim}(positions, seismograms, observed, invcov) end diff --git a/src/solve.jl b/src/solve.jl index 5a6b2c4..d4e0a99 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -150,7 +150,8 @@ end shots::Vector{<:Shot}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) -)::Union{Array{T}, Tuple{Array{T}, T}} where {T, N} +)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -161,7 +162,7 @@ end set_wavesim_matprop!(wavsim, matprop) # Initialize total gradient and total misfit - totgrad = zeros(wavsim.totgrad_size...) + totgrad = init_gradient(wavsim) totmisfitval = 0 # Shots loop for (s, singleshot) in enumerate(shots) @@ -175,7 +176,7 @@ end @info "Computing gradient solver" curgrad = swgradient_1shot!(wavsim, singleshot, misfit) # Accumulate gradient - totgrad .+= curgrad + accumulate_gradient!(totgrad, curgrad, wavsim) # Compute misfit if needed if compute_misfit @info "Computing misfit" @@ -193,7 +194,8 @@ end shots::Vector{<:Shot}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) -)::Union{Array{T}, Tuple{Array{T}, T}} where {T, N} +)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} nwsim = length(wavsim) nthr = Threads.nthreads() # make sure the number of threads has not changed! @@ -211,10 +213,10 @@ end # Initialize total gradient and total misfit nshots = length(shots) - allgrad = [zeros(wavsim[i].totgrad_size...) for i in nshots] + allgrad = Vector{Dict{String, Array{T, N}}}(undef, nshots) if compute_misfit - allmisfitval = zeros(nshots) + allmisfitval = zeros(T, nshots) totmisfitval = 0 end @@ -237,7 +239,7 @@ end wavsim[w], singleshot, misfit ) # Save gradient - allgrad[s] .= curgrad + allgrad[s] = curgrad # Compute misfit if needed if compute_misfit @info "Computing misfit" @@ -247,7 +249,10 @@ end end # Accumulate gradient and misfit - totgrad = sum(allgrad) + totgrad = init_gradient(wavsim) + for curgrad in allgrad + accumulate_gradient!(wavsim, totgrad, curgrad) + end if compute_misfit totmisfitval = sum(allmisfitval) end diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl index 7bbbb53..4f28b40 100644 --- a/src/srcrec_interpolation.jl +++ b/src/srcrec_interpolation.jl @@ -11,13 +11,13 @@ Kaiser windowing function. - `b`: 'b' coefficient - `r`: cut-off radius """ -function kaiser(x::Vector, x0::Real, b::Real, r::Real) +function kaiser(x::Vector, x0::T, b::T, r::T) where {T} # Kaiser window function # r is window half with # Rule of thumb for finite diff.: # b=4.14 b=6.31 # r = 4.0*dx - w = zeros(length(x)) + w = zeros(T, length(x)) for i in 1:length(x) xcur = x[i] - x0 if -r <= xcur <= r diff --git a/src/wrappers.jl b/src/wrappers.jl index cc95782..497b8e7 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -70,7 +70,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T, N}}, Nothing} where {T, N} if logger === nothing logger = current_logger() end @@ -145,7 +145,7 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::T where {T, N} if logger === nothing logger = current_logger() end @@ -198,7 +198,8 @@ function swgradient!( misfit::AbstractMisfit=L2Misfit(nothing), smooth_radius::Int=5, logger::Union{Nothing, AbstractLogger}=nothing -)::Union{AbstractArray, Tuple{AbstractArray, T}} where {T, N} +)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -242,7 +243,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...) where {T, N} + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -276,64 +278,56 @@ Builds a wave similation based on the input paramters `params` and keyword argum function build_wavesim(params::InputParameters{T, N}, matprop::MaterialProperties{T, N}; parall::Symbol, kwargs...) where {T, N} if parall == :threadpersrc nthr = Threads.nthreads() - wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) for _ in 1:nthr] + wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall=parall, kwargs...) for _ in 1:nthr] else - wsim = build_concrete_wavesim(params, matprop, params.boundcond; parall, kwargs...) + wsim = build_concrete_wavesim(params, matprop, params.boundcond; parall=parall, kwargs...) end return wsim end build_concrete_wavesim( params::InputParametersAcoustic{T,N}, - ::VpAcousticCDMaterialProperties{T,N}, - cpmlparams::CPMLBoundaryConditionParameters; - parall, + matprop::VpAcousticCDMaterialProperties{T,N}, + cpmlparams::CPMLBoundaryConditionParameters{T}; kwargs... ) where {T,N} = AcousticCDCPMLWaveSimul( - params.gridsize, - params.gridspacing, - params.ntimesteps, - params.dt, - cpmlparams.halo, - cpmlparams.rcoef; - freetop=cpmlparams.freeboundtop, - parall=parall, + params, + matprop, + cpmlparams; kwargs... ) build_concrete_wavesim( params::InputParametersAcoustic{T,N}, - ::VpRhoAcousticVDMaterialProperties, + matprop::VpRhoAcousticVDMaterialProperties{T,N}, cpmlparams::CPMLBoundaryConditionParameters; - parall, kwargs... ) where {T,N} = AcousticVDStaggeredCPMLWaveSimul( params.gridsize, params.gridspacing, params.ntimesteps, params.dt, + matprop, cpmlparams.halo, cpmlparams.rcoef; freetop=cpmlparams.freeboundtop, - parall, kwargs... ) build_concrete_wavesim( params::InputParametersElastic{T,N}, - ::ElasticIsoMaterialProperties, + matprop::ElasticIsoMaterialProperties{T,N}, cpmlparams::CPMLBoundaryConditionParameters; - parall, kwargs... ) where {T,N} = ElasticIsoCPMLWaveSimul( params.gridsize, params.gridspacing, params.ntimesteps, params.dt, + matprop, cpmlparams.halo, cpmlparams.rcoef; freetop=cpmlparams.freeboundtop, - parall, kwargs... ) diff --git a/test/test_gradient_acoustic_constant_density.jl b/test/test_gradient_acoustic_constant_density.jl index 87b903c..bc48cc3 100644 --- a/test/test_gradient_acoustic_constant_density.jl +++ b/test/test_gradient_acoustic_constant_density.jl @@ -38,7 +38,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do misfit_check = swmisfit!(params, vel, shots; parall=parall) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) # Check that misfits are non zero @test !(misfit ≈ 0.0) @test !(misfit_check ≈ 0.0) @@ -73,7 +73,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do misfit_check = swmisfit!(params, vel, shots; parall=parall) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) # Check that misfits are non zero @test !(misfit ≈ 0.0) @test !(misfit_check ≈ 0.0) @@ -107,7 +107,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do misfit_check = swmisfit!(params, vel, shots; parall=parall) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) # Check that misfits are non zero @test !(misfit ≈ 0.0) @test !(misfit_check ≈ 0.0) @@ -141,7 +141,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do misfit_check = swmisfit!(params, vel, shots; parall=parall) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) # Check that misfits are non zero @test !(misfit ≈ 0.0) @test !(misfit_check ≈ 0.0) @@ -180,9 +180,9 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) # Check that computations are equivalent - @test grad ≈ grad_check + @test grad["vp"] ≈ grad_check["vp"] end @testset "Test 2D $(parall) swgradient! checkpointing" begin @@ -216,9 +216,9 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) # Check that computations are equivalent - @test grad ≈ grad_check + @test grad["vp"] ≈ grad_check["vp"] end @testset "Test 3D $(parall) swgradient! checkpointing" begin @@ -252,9 +252,9 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) # Check that computations are equivalent - @test grad ≈ grad_check + @test grad["vp"] ≈ grad_check["vp"] end end end diff --git a/test/test_gradient_acoustic_variable_density.jl b/test/test_gradient_acoustic_variable_density.jl index 2a30071..6b90bb9 100644 --- a/test/test_gradient_acoustic_variable_density.jl +++ b/test/test_gradient_acoustic_variable_density.jl @@ -40,7 +40,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do misfit_check = swmisfit!(params, matprop, shots; parall=parall) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) + @test !all(g -> g == 0.0, grad["rho"]) # Check that misfits are non zero @test !(misfit ≈ 0.0) @test !(misfit_check ≈ 0.0) @@ -76,7 +77,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do misfit_check = swmisfit!(params, matprop, shots; parall=parall) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) + @test !all(g -> g == 0.0, grad["rho"]) # Check that misfits are non zero @test !(misfit ≈ 0.0) @test !(misfit_check ≈ 0.0) @@ -117,9 +119,11 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) + @test !all(g -> g == 0.0, grad["rho"]) # Check that computations are equivalent - @test grad ≈ grad_check + @test grad["vp"] ≈ grad_check["vp"] + @test grad["rho"] ≈ grad_check["rho"] end @testset "Test 2D $(parall) swgradient! checkpointing" begin @@ -155,9 +159,11 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # Check that gradient is non zero - @test !all(g -> g == 0.0, grad) + @test !all(g -> g == 0.0, grad["vp"]) + @test !all(g -> g == 0.0, grad["rho"]) # Check that computations are equivalent - @test grad ≈ grad_check + @test grad["vp"] ≈ grad_check["vp"] + @test grad["rho"] ≈ grad_check["rho"] end end end From e93532cabeabe0c0461374061be1f8de0c3fd7e0 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 2 Jul 2024 16:01:34 +0200 Subject: [PATCH 050/111] Fix snapshot return types --- src/wrappers.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wrappers.jl b/src/wrappers.jl index 497b8e7..45a3307 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -34,7 +34,7 @@ function swforward!( snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, logger::Union{Nothing, AbstractLogger}=nothing -)::Union{Vector{Array{T, N}}, Nothing} where {T, N} +)::Union{Vector{Array{T}}, Nothing} where {T, N} if logger === nothing logger = current_logger() end @@ -70,7 +70,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T, N}}, Nothing} where {T, N} + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T}}, Nothing} where {T, N} if logger === nothing logger = current_logger() end From 0cb47420a3fb4756f000d6d34ef1984911c12039 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 2 Jul 2024 16:18:16 +0200 Subject: [PATCH 051/111] Symplify adjoint for CD --- src/models/acoustic/acou_gradient.jl | 5 +---- src/models/acoustic/acou_models.jl | 4 +++- .../acoustic/backends/Acoustic1D_CD_CPML_Serial.jl | 8 +------- .../acoustic/backends/Acoustic2D_CD_CPML_Serial.jl | 9 +-------- .../acoustic/backends/Acoustic3D_CD_CPML_Serial.jl | 9 +-------- src/models/acoustic/backends/shared/acoustic1D_xPU.jl | 8 +------- src/models/acoustic/backends/shared/acoustic2D_xPU.jl | 9 +-------- src/models/acoustic/backends/shared/acoustic3D_xPU.jl | 9 +-------- src/solve.jl | 4 ++-- 9 files changed, 12 insertions(+), 53 deletions(-) diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index d34362c..385f703 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -52,10 +52,7 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step - backend.adjoint_onestep_CPML!( - grid, posrecs_bk, residuals_bk, nothing, nothing, it; # adjoint sources positions are receivers - save_trace=false - ) + backend.adjoint_onestep_CPML!(grid, posrecs_bk, residuals_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Backward iteration: %d", it) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 7be7e5b..c482d00 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -75,7 +75,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVect smooth_radius::Int # Snapshots snapevery::Union{Int, Nothing} - snapshots::Union{Vector{A}, Nothing} + snapshots::Union{Array{T}, Nothing} # Logging parameters infoevery::Int # Material properties @@ -187,6 +187,8 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVect # Save first two timesteps savecheckpoint!(checkpointer, "pcur" => grid.fields["pold"], -1) savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) + savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], 0) + savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) # Initialize snapshots array snapshots = (snapevery !== nothing ? [backend.zeros(T, ns...) for _ in 1:div(nt, snapevery)] : nothing) diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index 0de4203..5397987 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -134,10 +134,7 @@ end return nothing end -@views function adjoint_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; - save_trace=true -) +@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid nx = grid.ns[1] dx = grid.gridspacing[1] @@ -162,9 +159,6 @@ end a_x_l, a_x_r, b_x_l, b_x_r) inject_sources!(pnew, dt2srctf, possrcs, it) - if save_trace - record_receivers!(pnew, traces, posrecs, it) - end # Exchange pressures in grid grid.fields["adjold"] = grid.fields["adjcur"] diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl index aeb7491..1132b9e 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl @@ -156,10 +156,7 @@ function forward_onestep_CPML!( return nothing end -function adjoint_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; - save_trace=true -) +function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid nx, ny = grid.ns dx, dy = grid.gridspacing @@ -191,10 +188,6 @@ function adjoint_onestep_CPML!( # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) - # record receivers - if save_trace - record_receivers!(pnew, traces, posrecs, it) - end # Exchange pressures in grid grid.fields["adjold"] = grid.fields["adjcur"] diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl index 24e22be..416988a 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl @@ -209,10 +209,7 @@ function forward_onestep_CPML!( return nothing end -function adjoint_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; - save_trace=true -) +function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid nx, ny, nz = grid.ns dx, dy, dz = grid.gridspacing @@ -251,10 +248,6 @@ function adjoint_onestep_CPML!( # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) - # record receivers - if save_trace - record_receivers!(pnew, traces, posrecs, it) - end # Exchange pressures in grid grid.fields["adjold"] = grid.fields["adjcur"] diff --git a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl index 92561bc..4f9b5a2 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl @@ -133,10 +133,7 @@ end return nothing end -@views function adjoint_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; - save_trace=true -) +@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid nx = grid.ns[1] dx = grid.gridspacing[1] @@ -161,9 +158,6 @@ end a_x_l, a_x_r, b_x_l, b_x_r) @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) - if save_trace - @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) - end # Exchange pressures in grid grid.fields["adjold"] = grid.fields["adjcur"] diff --git a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl index 0ac6c7e..22682fb 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl @@ -156,10 +156,7 @@ end return nothing end -@views function adjoint_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; - save_trace=true -) +@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid nx, ny = grid.ns dx, dy = grid.gridspacing @@ -197,10 +194,6 @@ end # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) - # record receivers - if save_trace - @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) - end # Exchange pressures in grid grid.fields["adjold"] = grid.fields["adjcur"] diff --git a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl index fd8909c..164e974 100644 --- a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl @@ -213,10 +213,7 @@ end return nothing end -@views function adjoint_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; - save_trace=true -) +@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid nx, ny, nz = grid.ns dx, dy, dz = grid.gridspacing @@ -272,10 +269,6 @@ end # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) - # record receivers - if save_trace - @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) - end # Exchange pressures in grid grid.fields["adjold"] = grid.fields["adjcur"] diff --git a/src/solve.jl b/src/solve.jl index d4e0a99..216339e 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -14,7 +14,7 @@ end wavsim::WaveSimulation{T,N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; -)::Union{Vector{Array}, Nothing} where {T, N} +)::Union{Vector{Array{T}}, Nothing} where {T, N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -59,7 +59,7 @@ end wavsim::Vector{<:WaveSimulation{T,N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; -)::Union{Vector{Array}, Nothing} where {T, N} +)::Union{Vector{Array{T}}, Nothing} where {T, N} nwsim = length(wavsim) nthr = Threads.nthreads() # make sure the number of threads has not changed! From 87f02985c0cc2a576c202ad417d2ee0df6a484d7 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 10:05:52 +0200 Subject: [PATCH 052/111] Rewrite VD acoustic Also formatting and Shot now depends on data type --- examples/forward_example.jl | 2 +- examples/geometries.jl | 2 +- .../constant_density/gradient_check_fd.jl | 2 +- .../variable_density/gradient_check_fd.jl | 2 +- examples/simple_example_acoustic.jl | 4 +- examples/simple_example_elastic.jl | 4 +- examples/simple_example_wavesim.jl | 4 +- src/HMCseiswaves.jl | 4 +- src/checks.jl | 5 +- src/models/acoustic/acou_abstract_types.jl | 6 +- src/models/acoustic/acou_forward.jl | 44 +-- src/models/acoustic/acou_gradient.jl | 142 +++---- src/models/acoustic/acou_init_bc.jl | 28 +- src/models/acoustic/acou_models.jl | 346 +++++++----------- src/models/acoustic/acou_params.jl | 4 +- .../backends/Acoustic1D_CD_CPML_GPU.jl | 2 +- .../backends/Acoustic1D_CD_CPML_Threads.jl | 2 +- .../backends/Acoustic1D_VD_CPML_GPU.jl | 2 +- .../backends/Acoustic1D_VD_CPML_Threads.jl | 2 +- .../backends/Acoustic2D_CD_CPML_GPU.jl | 2 +- .../backends/Acoustic2D_CD_CPML_Threads.jl | 2 +- .../backends/Acoustic2D_VD_CPML_GPU.jl | 2 +- .../backends/Acoustic2D_VD_CPML_Threads.jl | 2 +- .../backends/Acoustic3D_CD_CPML_GPU.jl | 2 +- .../backends/Acoustic3D_CD_CPML_Threads.jl | 2 +- .../backends/shared/acoustic1D_VD_xPU.jl | 40 +- .../backends/shared/acoustic2D_VD_xPU.jl | 48 ++- .../acoustic/backends/shared/standard_xPU.jl | 8 +- .../backends/Elastic2D_Iso_CPML_Serial.jl | 4 +- src/models/elastic/ela_abstract_types.jl | 4 +- src/models/elastic/ela_forward.jl | 6 +- src/models/elastic/ela_models.jl | 18 +- src/models/elastic/ela_params.jl | 7 +- src/receivers.jl | 2 +- src/shot.jl | 8 +- src/solve.jl | 26 +- src/wrappers.jl | 57 ++- 37 files changed, 351 insertions(+), 496 deletions(-) diff --git a/examples/forward_example.jl b/examples/forward_example.jl index 4b8373b..5409088 100644 --- a/examples/forward_example.jl +++ b/examples/forward_example.jl @@ -21,7 +21,7 @@ function forward_example() ##======================================== # shots definition nshots = 6 - shots = Vector{Shot}() #Pair{Sources, Receivers}}() + shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() # sources x-position (in grid points) (different for every shot) ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) for i in 1:nshots diff --git a/examples/geometries.jl b/examples/geometries.jl index db93e87..f4bdefe 100644 --- a/examples/geometries.jl +++ b/examples/geometries.jl @@ -4,7 +4,7 @@ include("plotting_utils.jl") function linear_2D_geometry(nshots, model, f0, nt, srctf, dd, lx, ly, dx, dy, halo; plot_geometry=false, save_file=nothing) # shots definition - shots = Vector{Shot}() #Pair{ScalarSources, ScalarReceivers}}() + shots = Vector{Shot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() # straight line positions xs = (lx / 2) .- dd .* ((nshots + 1) / 2 .- collect(1:nshots)) ysrc = (halo + 10) * dy diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index b8293c2..16d0a89 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -74,7 +74,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss; compute end # new receivers with observed seismograms - shots_obs = Vector{Shot}() #Pair{ScalarSources, ScalarReceivers}}() + shots_obs = Vector{Shot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() for i in eachindex(shots) # receivers definition recs = ScalarReceivers( diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index 7a9de42..f4374c9 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -89,7 +89,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) end # new receivers with observed seismograms - shots_obs = Vector{Shot}() #Pair{ScalarSources, ScalarReceivers}}() + shots_obs = Vector{Shot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() for i in eachindex(shots) # receivers definition recs = ScalarReceivers( diff --git a/examples/simple_example_acoustic.jl b/examples/simple_example_acoustic.jl index 00d7a9b..5c0318e 100644 --- a/examples/simple_example_acoustic.jl +++ b/examples/simple_example_acoustic.jl @@ -44,7 +44,7 @@ function exacouprob(parall=:serial) ##======================================== # shots definition nshots = 6 - shots = Vector{Shot}() #Pair{Sources, Receivers}}() + shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() # sources x-position (in grid points) (different for every shot) ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) for i in 1:nshots @@ -102,7 +102,7 @@ function exacouprob(parall=:serial) ##=============================================== ## compute the gradient - shots_grad = Vector{Shot}() + shots_grad = Vector{Shot{Float64}}() for i in 1:nshots seis = shots[i].recs.seismograms nt = size(seis, 1) diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index 998aa82..8e54a44 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -52,7 +52,7 @@ function exelaprob() ##======================================== # shots definition nshots = 1 - shots = Vector{Shot}() #Pair{Sources, Receivers}}() + shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() for i in 1:nshots # sources definition @@ -133,7 +133,7 @@ function exelaprob() # ##=============================================== # ## compute the gradient - # shots_grad = Vector{Shot}() + # shots_grad = Vector{Shot{Float64}}() # for i in 1:nshots # seis = shots[i].recs.seismograms # nt = size(seis,1) diff --git a/examples/simple_example_wavesim.jl b/examples/simple_example_wavesim.jl index 9049253..9c7c8c5 100644 --- a/examples/simple_example_wavesim.jl +++ b/examples/simple_example_wavesim.jl @@ -47,7 +47,7 @@ function exacouprob_wavsim(parall=:serial) # shots definition nshots = 6 @show nshots - shots = Vector{Shot}() #Pair{Sources, Receivers}}() + shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() # sources x-position (in grid points) (different for every shot) ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) for i in 1:nshots @@ -126,7 +126,7 @@ function exacouprob_wavsim(parall=:serial) ##=============================================== ## compute the gradient - shots_grad = Vector{Shot}() + shots_grad = Vector{Shot{Float64}}() for i in 1:nshots seis = shots[i].recs.seismograms nt = size(seis, 1) diff --git a/src/HMCseiswaves.jl b/src/HMCseiswaves.jl index 71b5941..243321c 100644 --- a/src/HMCseiswaves.jl +++ b/src/HMCseiswaves.jl @@ -26,12 +26,12 @@ export AcouWavCDProb struct AcouWavCDProb #wavesim::WaveSimulation inpars::InputParametersAcoustic - shots::Vector{<:Shot} #invCovds::Vector{<:AbstractMatrix{Float64}} + shots::Vector{Shot{Float64}} #invCovds::Vector{<:AbstractMatrix{Float64}} parall::Symbol #firsttime::Base.RefValue{Bool} function AcouWavCDProb(inpars::InputParametersAcoustic, - shots::Vector{<:Shot}, + shots::Vector{Shot{Float64}}, parall::Symbol) # nt = inpars.ntimesteps diff --git a/src/checks.jl b/src/checks.jl index eb13e92..d9e1874 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -1,5 +1,5 @@ -function check_sim_consistency(wavsim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}) where {T, N} +function check_sim_consistency(wavsim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}) where {T, N} tysource = typeof(shots[1].srcs) tyreceiver = typeof(shots[1].recs) @@ -85,4 +85,5 @@ function check_positions( return end -check_invcov_matrix(model::WaveSimulation{T}, invcov::AbstractMatrix{T}) where {T} = @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" +check_invcov_matrix(model::WaveSimulation{T}, invcov::AbstractMatrix{T}) where {T} = + @assert size(invcov) == (model.nt, model.nt) "Inverse of covariance matrix has not size equal to ($(model.nt) x $(model.nt))!" diff --git a/src/models/acoustic/acou_abstract_types.jl b/src/models/acoustic/acou_abstract_types.jl index 3156746..684753f 100644 --- a/src/models/acoustic/acou_abstract_types.jl +++ b/src/models/acoustic/acou_abstract_types.jl @@ -1,6 +1,6 @@ -abstract type AcousticWaveSimul{T,N} <: WaveSimulation{T,N} end +abstract type AcousticWaveSimul{T, N} <: WaveSimulation{T, N} end -abstract type AcousticCDWaveSimul{T,N} <: AcousticWaveSimul{T,N} end +abstract type AcousticCDWaveSimul{T, N} <: AcousticWaveSimul{T, N} end -abstract type AcousticVDStaggeredWaveSimul{T,N} <: AcousticWaveSimul{T,N} end +abstract type AcousticVDStaggeredWaveSimul{T, N} <: AcousticWaveSimul{T, N} end diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 4c26d7f..263ba0d 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -3,8 +3,7 @@ swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) # Scaling for AcousticCDWaveSimul -@views function possrcrec_scaletf(wavsim::AcousticCDCPMLWaveSimul{T,N}, - shot::Shot) where {T,N} +@views function possrcrec_scaletf(wavsim::AcousticWaveSimul, shot::Shot) # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) @@ -22,13 +21,14 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::AcousticCDCPMLWaveSimul{T,N}, + wavsim::AcousticCDCPMLWaveSimul{T, N}, shot::Shot -) where {T,N} +) where {T, N} - # scale source time function, etc. + # Scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) + # Get computational grid and backend grid = wavsim.grid backend = select_backend(typeof(wavsim), wavsim.parall) @@ -77,7 +77,7 @@ end # source time function # scale with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(wavsim.gridspacing) .* (wavsim.dt) + scal_srctf = shot.srcs.tf ./ prod(wavsim.grid.gridspacing) .* (wavsim.dt) # scale with velocity squared times density at each source position (its like dividing by m0) for s in axes(scal_srctf, 2) scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 .* wavsim.matprop.rho[possrcs[s, :]...] @@ -88,49 +88,45 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::AcousticVDStaggeredCPMLWaveSimul{T,N}, + wavsim::AcousticVDStaggeredCPMLWaveSimul{T, N}, shot::Shot -) where {T,N} +) where {T, N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) - # Pressure and velocity arrays - pcur = wavsim.pcur - vcur = wavsim.vcur + # Get computational grid and backend + grid = wavsim.grid + backend = select_backend(typeof(wavsim), wavsim.parall) + # Numerics nt = wavsim.nt # Wrap sources and receivers arrays - possrcs_bk = wavsim.backend.Data.Array(possrcs) - posrecs_bk = wavsim.backend.Data.Array(posrecs) - srctf_bk = wavsim.backend.Data.Array(scal_srctf) - traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) + possrcs_bk = backend.Data.Array(possrcs) + posrecs_bk = backend.Data.Array(posrecs) + srctf_bk = backend.Data.Array(scal_srctf) + traces_bk = backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(wavsim) # Time loop for it in 1:nt # Compute one forward step - wavsim.backend.forward_onestep_CPML!( - pcur, vcur..., wavsim.fact_m0, wavsim.fact_m1_stag..., - wavsim.gridspacing..., wavsim.halo, - wavsim.ψ..., wavsim.ξ..., wavsim.a_coeffs..., wavsim.b_coeffs..., - possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it - ) + backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % wavsim.infoevery == 0 @info @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, wavsim.dt * (it - 1), - maximum(abs.(Array(pcur))) + maximum(abs.(Array(grid.fields["pcur"].value))) ) end # Save snapshot if snapenabled(wavsim) && it % wavsim.snapevery == 0 - @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) - copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], pcur) + @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(grid.fields["pcur"].value)))) + copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], grid.fields["pcur"].value) end end diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 385f703..593cf83 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -3,14 +3,15 @@ swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = @views function swgradient_1shot!( ::CPMLBoundaryCondition, - model::AcousticCDWaveSimul{T,N}, + model::AcousticCDWaveSimul{T, N}, shot::Shot, misfit -)::Dict{String, Array{T,N}} where {T,N} +)::Dict{String, Array{T, N}} where {T, N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) + # Get computational grid, checkpointer and backend grid = model.grid checkpointer = model.checkpointer backend = select_backend(typeof(model), model.parall) @@ -95,148 +96,103 @@ end @views function swgradient_1shot!( ::CPMLBoundaryCondition, - model::AcousticVDStaggeredCPMLWaveSimul{T,N}, + model::AcousticVDStaggeredCPMLWaveSimul{T, N}, shot::Shot, misfit -)::Dict{String, Array{T,N}} where {T,N} +)::Dict{String, Array{T, N}} where {T, N} # scale source time function, etc. possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) + # Get computational grid, checkpointer and backend + grid = model.grid + checkpointer = model.checkpointer + backend = select_backend(typeof(model), model.parall) + # Numerics nt = model.nt - # Initialize pressure and velocities arrays - pcur = model.pcur - vcur = model.vcur - # Initialize adjoint arrays - adjpcur = model.adjpcur - adjvcur = model.adjvcur # Wrap sources and receivers arrays - possrcs_bk = model.backend.Data.Array(possrcs) - posrecs_bk = model.backend.Data.Array(posrecs) - srctf_bk = model.backend.Data.Array(scal_srctf) - traces_bk = model.backend.Data.Array(shot.recs.seismograms) + possrcs_bk = backend.Data.Array(possrcs) + posrecs_bk = backend.Data.Array(posrecs) + srctf_bk = backend.Data.Array(scal_srctf) + traces_bk = backend.Data.Array(shot.recs.seismograms) # Reset wavesim reset!(model) # Forward time loop for it in 1:nt # Compute one forward step - model.backend.forward_onestep_CPML!( - pcur, vcur..., model.fact_m0, model.fact_m1_stag..., - model.gridspacing..., model.halo, - model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it - ) + backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 - @info @sprintf("Forward iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, model.dt * it, maximum(abs.(Array(pcur)))) + @info @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) end # Save checkpoint - if model.check_freq !== nothing && it % model.check_freq == 0 - @debug @sprintf("Saving checkpoint at iteration: %d", it) - # Save current pressure and velocities - copyto!(model.checkpoints[it], pcur) - for i in eachindex(vcur) - copyto!(model.checkpoints_v[it][i], vcur[i]) - end - # Also save CPML arrays - for i in eachindex(model.ψ) - copyto!(model.checkpoints_ψ[it][i], model.ψ[i]) - end - for i in eachindex(model.ξ) - copyto!(model.checkpoints_ξ[it][i], model.ξ[i]) - end - end - # Start populating save buffer at last checkpoint - if it >= model.last_checkpoint - copyto!(model.save_buffer[fill(Colon(), N)..., it-model.last_checkpoint+1], pcur) - end + savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], it) + savecheckpoint!(checkpointer, "vcur" => grid.fields["vcur"], it) + savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], it) + savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], it) end @info "Saving seismograms" copyto!(shot.recs.seismograms, traces_bk) @debug "Computing residuals" - residuals_bk = model.backend.Data.Array(dχ_du(misfit, shot.recs)) + residuals_bk = backend.Data.Array(dχ_du(misfit, shot.recs)) # Prescale residuals (fact = vel^2 * rho * dt) - model.backend.prescale_residuals!(residuals_bk, posrecs_bk, model.fact_m0) + backend.prescale_residuals!(residuals_bk, posrecs_bk, grid.fields["fact_m0"].value) @debug "Computing gradients" - # Current checkpoint - curr_checkpoint = model.last_checkpoint # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step - model.backend.backward_onestep_CPML!( - adjpcur, adjvcur..., model.fact_m0, model.fact_m1_stag..., - model.gridspacing..., model.halo, - model.ψ_adj..., model.ξ_adj..., model.a_coeffs..., model.b_coeffs..., - posrecs_bk, residuals_bk, it; # adjoint sources positions are receivers - ) + backend.adjoint_onestep_CPML!(grid, posrecs_bk, residuals_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Backward iteration: %d", it) end # Check if out of save buffer - if (it - 1) < curr_checkpoint + if !issaved(checkpointer, "pcur", it - 1) @debug @sprintf("Out of save buffer at iteration: %d", it) - # Shift last checkpoint - old_checkpoint = curr_checkpoint - curr_checkpoint -= model.check_freq - # Shift start of save buffer - copyto!(model.save_buffer[fill(Colon(), N)..., 1], model.checkpoints[curr_checkpoint]) - # Shift end of save save_buffer - copyto!(model.save_buffer[fill(Colon(), N)..., end], model.checkpoints[old_checkpoint]) - # Recover pressure, velocities and CPML arrays from current checkpoint - copyto!(pcur, model.checkpoints[curr_checkpoint]) - for i in eachindex(model.checkpoints_v[curr_checkpoint]) - copyto!(vcur[i], model.checkpoints_v[curr_checkpoint][i]) - end - for i in eachindex(model.checkpoints_ψ[curr_checkpoint]) - copyto!(model.ψ[i], model.checkpoints_ψ[curr_checkpoint][i]) - end - for i in eachindex(model.checkpoints_ξ[curr_checkpoint]) - copyto!(model.ξ[i], model.checkpoints_ξ[curr_checkpoint][i]) - end - # Forward recovery time loop - for recit in (curr_checkpoint+1):(old_checkpoint-1) - model.backend.forward_onestep_CPML!( - pcur, vcur..., model.fact_m0, model.fact_m1_stag..., - model.gridspacing..., model.halo, - model.ψ..., model.ξ..., model.a_coeffs..., model.b_coeffs..., - possrcs_bk, srctf_bk, nothing, nothing, recit; - save_trace=false - ) - # Save recovered pressure in save buffer - copyto!(model.save_buffer[fill(Colon(), N)..., recit-(curr_checkpoint+1)+2], pcur) - end + initrecover!(checkpointer) + copyto!(grid.fields["pcur"], getsaved(checkpointer, "pcur", checkpointer.curr_checkpoint)) + copyto!(grid.fields["vcur"], getsaved(checkpointer, "vcur", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ"], getsaved(checkpointer, "ψ", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ξ"], getsaved(checkpointer, "ξ", checkpointer.curr_checkpoint)) + recover!( + checkpointer, + recit -> begin + backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false) + return ["pcur" => grid.fields["pcur"]] + end + ) end # Get pressure fields from saved buffer - pcur_corr = model.save_buffer[fill(Colon(), N)..., (it-curr_checkpoint)+1] - pcur_old = model.save_buffer[fill(Colon(), N)..., (it-curr_checkpoint)] + pcur_corr = getsaved(checkpointer, "pcur", it).value + pcur_old = getsaved(checkpointer, "pcur", it - 1).value # Correlate for gradient computation - model.backend.correlate_gradient_m0!(model.curgrad_m0, adjpcur, pcur_corr, pcur_old, model.dt) - model.backend.correlate_gradient_m1!(model.curgrad_m1_stag, adjvcur, pcur_corr, model.gridspacing) + backend.correlate_gradient_m0!(grid.fields["grad_m0"].value, grid.fields["adjpcur"].value, pcur_corr, pcur_old, model.dt) + backend.correlate_gradient_m1!(grid.fields["grad_m1_stag"].value, grid.fields["adjvcur"].value, pcur_corr, grid.gridspacing) end # Allocate gradients - gradient_m0 = zeros(T, model.ns...) - gradient_m1 = zeros(T, model.ns...) + gradient_m0 = zeros(T, grid.ns...) + gradient_m1 = zeros(T, grid.ns...) # Get gradients - copyto!(gradient_m0, model.curgrad_m0) - for i in eachindex(model.curgrad_m1_stag) + copyto!(gradient_m0, grid.fields["grad_m0"].value) + for i in eachindex(grid.fields["grad_m1_stag"].value) # Accumulate and interpolate staggered gradients - gradient_m1[CartesianIndices(Tuple(j == i ? (2:model.ns[j]-1) : (1:model.ns[j]) for j in 1:N))] .+= interp(model.matprop.interp_method, Array(model.curgrad_m1_stag[i]), i) + gradient_m1[CartesianIndices(Tuple(j == i ? (2:grid.ns[j]-1) : (1:grid.ns[j]) for j in 1:N))] .+= + interp(model.matprop.interp_method, Array(grid.fields["grad_m1_stag"].value[i]), i) end # Smooth gradients - model.backend.smooth_gradient!(gradient_m0, possrcs, model.smooth_radius) - model.backend.smooth_gradient!(gradient_m1, possrcs, model.smooth_radius) + backend.smooth_gradient!(gradient_m0, possrcs, model.smooth_radius) + backend.smooth_gradient!(gradient_m1, possrcs, model.smooth_radius) # compute regularization if needed dχ_dvp, dχ_drho = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) # Rescale gradients with respect to material properties (chain rule) return Dict( - "vp" => .-2.0 .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp + "vp" => .-2.0 .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp "rho" => .-gradient_m0 ./ (model.matprop.vp .^ 2 .* model.matprop.rho .^ 2) .- gradient_m1 ./ model.matprop.rho .+ dχ_drho # grad wrt rho ) end diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index e738138..72b1f07 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -8,32 +8,6 @@ init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimul, srcs::Sources ::CPMLBoundaryCondition, model::AcousticWaveSimul, srcs::Sources -) - N = length(model.cpmlcoeffs) - for n in 1:N - compute_CPML_coefficients!( - model.cpmlcoeffs[n], - get_maximum_func(model)(model.matprop.vp), - model.dt, - model.halo, - model.rcoef, - model.gridspacing[n] * model.halo, - srcs.domfreq - ) - end - - if model.freetop && N >= 1 - model.cpmlcoeffs[N].a_l .= 0.0 - model.cpmlcoeffs[N].a_hl .= 0.0 - model.cpmlcoeffs[N].b_l .= 1.0 - model.cpmlcoeffs[N].b_hl .= 1.0 - end -end - -@views function init_bdc!( - ::CPMLBoundaryCondition, - model::AcousticCDCPMLWaveSimul, - srcs::Sources ) N = length(model.cpmlcoeffs) for n in 1:N @@ -54,4 +28,4 @@ end model.cpmlcoeffs[N].b_l .= 1.0 model.cpmlcoeffs[N].b_hl .= 1.0 end -end \ No newline at end of file +end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index c482d00..ed5ddf5 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -2,7 +2,7 @@ # Functions for all AcousticWaveSimul subtypes -@views function check_courant_condition(model::AcousticWaveSimul{T,N}, vp::Array{T, N}) where {T, N} +@views function check_courant_condition(model::AcousticWaveSimul{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) courant = vel_max * model.dt * tmp @@ -29,7 +29,7 @@ end # Functions for all AcousticCDWaveSimul subtypes -@views function check_matprop(model::AcousticCDWaveSimul{T,N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::AcousticCDWaveSimul{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.ns)" @@ -38,7 +38,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticCDWaveSimul{T,N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::AcousticCDWaveSimul{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) # Precompute factors @@ -47,17 +47,13 @@ end @views precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) -@views function init_gradient(model::AcousticCDWaveSimul{T,N})::Dict{String, Array{T, N}} where {T, N} - return Dict("vp" => zero(model.matprop.vp)) -end +@views init_gradient(model::AcousticCDWaveSimul{T, N})::Dict{String, Array{T, N}} where {T, N} = Dict("vp" => zero(model.matprop.vp)) -@views function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimul{T,N}) where {T, N, D <: Dict{String, Array{T, N}}} - totgrad["vp"] .+= curgrad["vp"] -end +@views accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} = totgrad["vp"] .+= curgrad["vp"] ########################################################### -struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticCDWaveSimul{T,N} +struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticCDWaveSimul{T, N} # Parameters params::InputParametersAcoustic{T, N} cpmlparams::CPMLBoundaryConditionParameters{T} @@ -79,7 +75,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVect # Logging parameters infoevery::Int # Material properties - matprop::VpAcousticCDMaterialProperties{T,N} + matprop::VpAcousticCDMaterialProperties{T, N} # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients{T, V}} # Checkpointing setup @@ -89,7 +85,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVect function AcousticCDCPMLWaveSimul( params::InputParametersAcoustic{T, N}, - matprop::VpAcousticCDMaterialProperties{T,N}, + matprop::VpAcousticCDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters{T}; parall::Symbol=:threads, gradient::Bool=false, @@ -191,7 +187,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVect savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) # Initialize snapshots array - snapshots = (snapevery !== nothing ? [backend.zeros(T, ns...) for _ in 1:div(nt, snapevery)] : nothing) + snapshots = (snapevery !== nothing ? backend.zeros(T, ns..., div(nt, snapevery)) : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -255,9 +251,9 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() # Functions for all AcousticVDStaggeredWaveSimul subtypes -@views function check_courant_condition(model::AcousticVDStaggeredWaveSimul{T,N}, vp::Array{T, N}) where {T,N} +@views function check_courant_condition(model::AcousticVDStaggeredWaveSimul{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) - tmp = sqrt(sum(1 ./ model.gridspacing .^ 2)) + tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil @info "Courant number: $(courant)" if courant > 1 @@ -278,17 +274,17 @@ function check_numerics( @assert ppw >= min_ppw "Not enough points per wavelengh!" end -@views function check_matprop(model::AcousticVDStaggeredWaveSimul{T,N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::AcousticVDStaggeredWaveSimul{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(matprop.vp) == size(matprop.rho) == model.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.ns)" + @assert size(matprop.vp) == size(matprop.rho) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.ns)" @assert all(matprop.vp .> 0) "Pressure velocity material property must be positive!" @assert all(matprop.rho .> 0) "Density material property must be positive!" # Check courant condition check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{T,N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) copyto!(model.matprop.rho, matprop.rho) @@ -297,98 +293,75 @@ end precompute_fact!(model) end -@views function precompute_fact!(model::AcousticVDStaggeredWaveSimul{T,N}) where {T,N} +@views function precompute_fact!(model::AcousticVDStaggeredWaveSimul{T, N}) where {T, N} # Precompute 1/m0 * dt factor - copyto!(model.fact_m0, model.matprop.vp .^ 2 .* model.matprop.rho .* model.dt) + copyto!(model.grid.fields["fact_m0"].value, model.matprop.vp .^ 2 .* model.matprop.rho .* model.dt) # Precompute m1 * dt factor by interpolation m1_stag_interp = interpolate(1 ./ model.matprop.rho, model.matprop.interp_method) for i in 1:N - copyto!(model.fact_m1_stag[i], m1_stag_interp[i] .* model.dt) + copyto!(model.grid.fields["fact_m1_stag"].value[i], m1_stag_interp[i] .* model.dt) end end -@views function init_gradient(model::AcousticVDStaggeredWaveSimul{T,N})::Dict{String, Array{T, N}} where {T, N} - return Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) -end +@views init_gradient(model::AcousticVDStaggeredWaveSimul{T, N})::Dict{String, Array{T, N}} where {T, N} = Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) -@views function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimul{T,N}) where {T, N, D <: Dict{String, Array{T, N}}} +@views function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} totgrad["vp"] .+= curgrad["vp"] totgrad["rho"] .+= curgrad["rho"] end ########################################################### -struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N} - # Physics - domainextent::NTuple{N, T} +struct AcousticVDStaggeredCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticVDStaggeredWaveSimul{T, N} + # Parameters + params::InputParametersAcoustic{T, N} + cpmlparams::CPMLBoundaryConditionParameters{T} # Numerics - ns::NTuple{N, Int} - gridspacing::NTuple{N, T} nt::Int dt::T + # Computational grid + grid::UniformFiniteDifferenceGrid{N, T} # BDC and CPML parameters halo::Int rcoef::T freetop::Bool # Gradient computation setup gradient::Bool - check_freq::Union{Int, Nothing} + smooth_radius::Int # Snapshots snapevery::Union{Int, Nothing} - snapshots::Union{Any, Nothing} + snapshots::Union{Array{T}, Nothing} # Logging parameters infoevery::Int - # Gradient smoothing parameters - smooth_radius::Int # Material properties - matprop::VpRhoAcousticVDMaterialProperties{T,N} + matprop::VpRhoAcousticVDMaterialProperties{T, N} # CPML coefficients - cpmlcoeffs::NTuple{N, CPMLCoefficients{T}} - # Forward computation arrays - fact_m0::Any - fact_m1_stag::Any - pcur::Any - vcur::Any - ψ::Any - ξ::Any - a_coeffs::Any - b_coeffs::Any - # Gradient computation arrays - curgrad_m0::Any - curgrad_m1_stag::Any - adjpcur::Any - adjvcur::Any - ψ_adj::Any - ξ_adj::Any + cpmlcoeffs::NTuple{N, CPMLCoefficients{T, V}} # Checkpointing setup - last_checkpoint::Union{Int, Nothing} - save_buffer::Any - checkpoints::Any - checkpoints_v::Any - checkpoints_ψ::Any - checkpoints_ξ::Any - # Backend - backend::Module + checkpointer::LinearCheckpointer{T} + # Parallelization type + parall::Symbol function AcousticVDStaggeredCPMLWaveSimul( - ns::NTuple{N, Int}, - gridspacing::NTuple{N, T}, - nt::Int, - dt::T, - matprop::VpRhoAcousticVDMaterialProperties{T,N}, - halo::Int, - rcoef::T; + params::InputParametersAcoustic{T, N}, + matprop::VpRhoAcousticVDMaterialProperties{T, N}, + cpmlparams::CPMLBoundaryConditionParameters{T}; parall::Symbol=:threads, - freetop::Bool=true, gradient::Bool=false, check_freq::Union{Int, Nothing}=nothing, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, smooth_radius::Int=5 - ) where {T,N} + ) where {T, N} + # Extract params + nt = params.ntimesteps + dt = params.dt + gridspacing = params.gridspacing + ns = params.gridsize + halo = cpmlparams.halo + freetop = cpmlparams.freeboundtop + rcoef = cpmlparams.rcoef # Check numerics - @assert all(ns .> 0) "All numbers of grid points must be positive!" - @assert all(gridspacing .> 0) "All cell sizes must be positive!" @assert nt > 0 "Number of timesteps must be positive!" @assert dt > 0 "Timestep size must be positive!" @@ -397,107 +370,89 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N ns_cpml = freetop ? ns[1:(end-1)] : ns @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" - # Compute model sizes - domainextent = gridspacing .* (ns .- 1) - # Select backend - backend = select_backend(AcousticVDStaggeredCPMLWaveSimul{T,N}, parall) + backend = select_backend(AcousticCDCPMLWaveSimul{T, N}, parall) + A = backend.Data.Array{T, N} V = backend.Data.Array{T, 1} - - # Initialize computational arrays - fact_m0 = backend.zeros(T, ns...) - fact_m1_stag = [] - pcur = backend.zeros(T, ns...) - vcur = [] - for i in 1:N - stag_ns = [ns...] - stag_ns[i] -= 1 - push!(fact_m1_stag, backend.zeros(T, stag_ns...)) - push!(vcur, backend.zeros(T, stag_ns...)) - end - # Initialize CPML arrays - ψ = [] - ξ = [] - for i in 1:N - ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ, [backend.zeros(T, ψ_ns...), backend.zeros(T, ψ_ns...)]) - append!(ξ, [backend.zeros(T, ξ_ns...), backend.zeros(T, ξ_ns...)]) - end + # Initialize computational grid + grid = UniformFiniteDifferenceGrid(ns, gridspacing) # Initialize CPML coefficients cpmlcoeffs = tuple([CPMLCoefficients{T, V}(halo, backend, true) for _ in 1:N]...) - # Build CPML coefficient arrays for computations (they are just references to cpmlcoeffs) - a_coeffs = [] - b_coeffs = [] - for i in 1:N - append!(a_coeffs, [cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr]) - append!(b_coeffs, [cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr]) + + # Populate computational grid + addfield!(grid, "fact_m0" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "fact_m1_stag" => MultiVariableField( + [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + )) + addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "vcur" => MultiVariableField( + [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + )) + if gradient + addfield!(grid, "grad_m0" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "grad_m1_stag" => MultiVariableField( + [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + )) + addfield!(grid, "adjpcur" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "adjvcur" => MultiVariableField( + [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + )) end - # Initialize gradient arrays if needed + # CPML coefficients + addfield!( + grid, + "a_pml" => MultiVariableField( + cat([[cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr] for i in 1:N]...; dims=1) + ) + ) + addfield!( + grid, + "b_pml" => MultiVariableField( + cat([[cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr] for i in 1:N]...; dims=1) + ) + ) + # CPML memory variables + addfield!( + grid, + "ψ" => MultiVariableField( + cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + ) + ) + addfield!( + grid, + "ξ" => MultiVariableField( + cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + ) + ) if gradient - # Current gradient arrays - curgrad_m0 = backend.zeros(T, ns...) - curgrad_m1_stag = [] - # Adjoint arrays - adjpcur = backend.zeros(T, ns...) - adjvcur = [] - for i in 1:N - stag_ns = [ns...] - stag_ns[i] -= 1 - push!(adjvcur, backend.zeros(T, stag_ns...)) - push!(curgrad_m1_stag, backend.zeros(T, stag_ns...)) - end - # Initialize CPML arrays - ψ_adj = [] - ξ_adj = [] - for i in 1:N - ψ_ns = [ns...] - ξ_ns = [ns...] - ψ_ns[i] = halo + 1 - ξ_ns[i] = halo - append!(ψ_adj, [backend.zeros(T, ψ_ns...), backend.zeros(T, ψ_ns...)]) - append!(ξ_adj, [backend.zeros(T, ξ_ns...), backend.zeros(T, ξ_ns...)]) - end - # Checkpointing setup - if check_freq !== nothing - @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" - @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" - # Time step of last checkpoint - last_checkpoint = floor(Int, nt / check_freq) * check_freq - # Checkpointing arrays - save_buffer = backend.zeros(T, ns..., check_freq + 1) # pressure window buffer - checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints - checkpoints_v = Dict{Int, Vector{backend.Data.Array}}() # velocities checkpoints - checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints - checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints - # Save initial conditions as first checkpoint - checkpoints[0] = copy(pcur) - checkpoints_v[0] = copy.(vcur) - checkpoints_ψ[0] = copy.(ψ) - checkpoints_ξ[0] = copy.(ξ) - # Preallocate future checkpoints - for it in 1:(nt+1) - if it % check_freq == 0 - checkpoints[it] = backend.zeros(T, ns...) - checkpoints_v[it] = copy.(vcur) - checkpoints_ψ[it] = copy.(ψ) - checkpoints_ξ[it] = copy.(ξ) - end - end - else # no checkpointing - last_checkpoint = 0 # simulate a checkpoint at time step 0 - save_buffer = backend.zeros(T, ns..., nt + 1) # save all timesteps (from 0 to nt so nt+1) - checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) - checkpoints_v = Dict{Int, Vector{backend.Data.Array}}() # velocities checkpoints (will remain empty) - checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) - checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) - end - # Save timestep 0 in save buffer - copyto!(save_buffer[fill(Colon(), N)..., 1], pcur) + addfield!( + grid, + "ψ_adj" => MultiVariableField( + cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + ) + ) + addfield!( + grid, + "ξ_adj" => MultiVariableField( + cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + ) + ) end + # Initialize checkpointer + checkpointer = LinearCheckpointer( + nt, + check_freq === nothing ? 1 : check_freq, + filter(p -> p.first in ["pcur", "vcur", "ψ", "ξ"], grid.fields), + ["pcur"]; + widths=Dict("pcur" => 1) + ) + # Save first two timesteps + savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) + savecheckpoint!(checkpointer, "vcur" => grid.fields["vcur"], 0) + savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], 0) + savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) + # Initialize snapshots array snapshots = (snapevery !== nothing ? backend.zeros(T, ns..., div(nt, snapevery)) : nothing) # Check infoevery @@ -507,44 +462,24 @@ struct AcousticVDStaggeredCPMLWaveSimul{T,N} <: AcousticVDStaggeredWaveSimul{T,N @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - return new{T,N}( - domainextent, - ns, - gridspacing, + return new{T, N, A, V}( + params, + cpmlparams, nt, dt, + grid, halo, rcoef, freetop, gradient, - gradient ? check_freq : nothing, + smooth_radius, snapevery, snapshots, infoevery, - smooth_radius, matprop, cpmlcoeffs, - fact_m0, - fact_m1_stag, - pcur, - vcur, - ψ, - ξ, - a_coeffs, - b_coeffs, - gradient ? curgrad_m0 : nothing, - gradient ? curgrad_m1_stag : nothing, - gradient ? adjpcur : nothing, - gradient ? adjvcur : nothing, - gradient ? ψ_adj : nothing, - gradient ? ξ_adj : nothing, - gradient ? last_checkpoint : nothing, - gradient ? save_buffer : nothing, - gradient ? checkpoints : nothing, - gradient ? checkpoints_v : nothing, - gradient ? checkpoints_ψ : nothing, - gradient ? checkpoints_ξ : nothing, - backend + checkpointer, + parall ) end end @@ -555,33 +490,8 @@ end @views function reset!(model::AcousticVDStaggeredCPMLWaveSimul) # Reset computational arrays - model.pcur .= 0.0 - for i in eachindex(model.vcur) - model.vcur[i] .= 0.0 - end - for i in eachindex(model.ψ) - model.ψ[i] .= 0.0 - end - for i in eachindex(model.ξ) - model.ξ[i] .= 0.0 - end - # Reset gradient arrays - if model.gradient - model.curgrad_m0 .= 0.0 - for i in eachindex(model.curgrad_m1_stag) - model.curgrad_m1_stag[i] .= 0.0 - end - model.adjpcur .= 0.0 - for i in eachindex(model.adjvcur) - model.adjvcur[i] .= 0.0 - end - for i in eachindex(model.ψ_adj) - model.ψ_adj[i] .= 0.0 - end - for i in eachindex(model.ξ_adj) - model.ξ_adj[i] .= 0.0 - end - end + reset!(model.grid; except=["fact_m0", "fact_m1_stag", "a_pml", "b_pml"]) + reset!(model.checkpointer) end ########################################################### diff --git a/src/models/acoustic/acou_params.jl b/src/models/acoustic/acou_params.jl index a699596..cb8a2b3 100644 --- a/src/models/acoustic/acou_params.jl +++ b/src/models/acoustic/acou_params.jl @@ -6,7 +6,7 @@ Parameters for acoustic wave simulations. $(TYPEDFIELDS) """ -struct InputParametersAcoustic{T,N} <: InputParameters{T,N} +struct InputParametersAcoustic{T, N} <: InputParameters{T, N} "Number of time steps" ntimesteps::Int "Time step" @@ -26,6 +26,6 @@ struct InputParametersAcoustic{T,N} <: InputParameters{T,N} boundcond::InputBoundaryConditionParameters{T} ) where {T, N} @assert N <= 3 "Dimensionality must be less than or equal to 3!" - new{T,N}(ntimesteps, dt, gridsize, gridspacing, boundcond) + new{T, N}(ntimesteps, dt, gridsize, gridspacing, boundcond) end end diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl index 3a27ef9..9fa0249 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl @@ -3,7 +3,7 @@ module Acoustic1D_CD_CPML_GPU using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences1D -@init_parallel_stencil(package=CUDA, ndims=1, inbound=true) +@init_parallel_stencil(package = CUDA, ndims = 1, inbound = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl index 5344be0..f855b3a 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl @@ -2,7 +2,7 @@ module Acoustic1D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences1D -@init_parallel_stencil(package=Threads, ndims=1, inbounds=true) +@init_parallel_stencil(package = Threads, ndims = 1, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl index dd63b89..07f296a 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl @@ -5,7 +5,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences1D include("shared/fourth_order_FiniteDifferences1D.jl") -@init_parallel_stencil(package=CUDA, ndims=1, inbounds=true) +@init_parallel_stencil(package = CUDA, ndims = 1, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl index b7ed790..cca1f40 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl @@ -4,7 +4,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences1D include("shared/fourth_order_FiniteDifferences1D.jl") -@init_parallel_stencil(package=Threads, ndims=1, inbounds=true) +@init_parallel_stencil(package = Threads, ndims = 1, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl index 80b46cc..c158a46 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl @@ -4,7 +4,7 @@ using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences2D -@init_parallel_stencil(package=CUDA, ndims=2, inbounds=true) +@init_parallel_stencil(package = CUDA, ndims = 2, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl index 01d6aa0..38569ad 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl @@ -3,7 +3,7 @@ module Acoustic2D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences2D -@init_parallel_stencil(package=Threads, ndims=2, inbounds=true) +@init_parallel_stencil(package = Threads, ndims = 2, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl index 48b06b5..92e5ab8 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl @@ -5,7 +5,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences2D include("shared/fourth_order_FiniteDifferences2D.jl") -@init_parallel_stencil(package=CUDA, ndims=2, inbounds=true) +@init_parallel_stencil(package = CUDA, ndims = 2, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl index ffe5c37..f441a62 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl @@ -4,7 +4,7 @@ using ParallelStencil using ParallelStencil.FiniteDifferences2D include("shared/fourth_order_FiniteDifferences2D.jl") -@init_parallel_stencil(package=Threads, ndims=2, inbounds=true) +@init_parallel_stencil(package = Threads, ndims = 2, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl index d01df2b..e8577fc 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl @@ -4,7 +4,7 @@ using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences3D -@init_parallel_stencil(package=CUDA, ndims=3, inbounds=true) +@init_parallel_stencil(package = CUDA, ndims = 3, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl index 824159c..3b32dcc 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl @@ -3,7 +3,7 @@ module Acoustic3D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences3D -@init_parallel_stencil(package=Threads, ndims=3, inbounds=true) +@init_parallel_stencil(package = Threads, ndims = 3, inbounds = true) include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl index 0e235af..ac90e2e 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl @@ -68,14 +68,21 @@ end end @views function forward_onestep_CPML!( - pcur, vx_cur, fact_m0, fact_m1_x, dx, halo, - ψ_l, ψ_r, ξ_l, ξ_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - possrcs, srctf, posrecs, traces, it; + grid, possrcs, srctf, posrecs, traces, it; save_trace=true ) - nx = length(pcur) + # Extract info from grid + nx = grid.ns[1] + dx = grid.gridspacing[1] + pcur, vx_cur = grid.fields["pcur"].value, grid.fields["vcur"].value[1] + fact_m0 = grid.fields["fact_m0"].value + fact_m1_x = grid.fields["fact_m1_stag"].value[1] + ψ_l, ψ_r = grid.fields["ψ"].value + ξ_l, ξ_r = grid.fields["ξ"].value + a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / (dx * 24) @parallel (3:(nx-2)) update_p_CPML!(pcur, vx_cur, halo, fact_m0, nx, _dx, @@ -88,14 +95,21 @@ end end end -@views function backward_onestep_CPML!( - pcur, vx_cur, fact_m0, fact_m1_x, dx, halo, - ψ_l, ψ_r, ξ_l, ξ_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - possrcs, srctf, it +@views function adjoint_onestep_CPML!( + grid, possrcs, srctf, it ) - nx = length(pcur) + # Extract info from grid + nx = grid.ns[1] + dx = grid.gridspacing[1] + pcur, vx_cur = grid.fields["adjpcur"].value, grid.fields["adjvcur"].value[1] + fact_m0 = grid.fields["fact_m0"].value + fact_m1_x = grid.fields["fact_m1_stag"].value[1] + ψ_l, ψ_r = grid.fields["ψ_adj"].value + ξ_l, ξ_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / (dx * 24) @parallel (2:(nx-2)) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, diff --git a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl index abb8719..057237c 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl @@ -104,17 +104,22 @@ end end @views function forward_onestep_CPML!( - pcur, vx_cur, vy_cur, fact_m0, fact_m1_x, fact_m1_y, dx, dy, halo, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - possrcs, srctf, posrecs, traces, it; + grid, possrcs, srctf, posrecs, traces, it; save_trace=true ) - nx, ny = size(pcur) + # Extract info from grid + nx, ny = grid.ns + dx, dy = grid.gridspacing + pcur = grid.fields["pcur"].value + vx_cur, vy_cur = grid.fields["vcur"].value + fact_m0 = grid.fields["fact_m0"].value + fact_m1_x, fact_m1_y = grid.fields["fact_m1_stag"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / (dx * 24) _dy = 1 / (dy * 24) @@ -134,17 +139,22 @@ end end end -@views function backward_onestep_CPML!( - pcur, vx_cur, vy_cur, fact_m0, fact_m1_x, fact_m1_y, dx, dy, halo, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - possrcs, srctf, it +@views function adjoint_onestep_CPML!( + grid, possrcs, srctf, it ) - nx, ny = size(pcur) + # Extract info from grid + nx, ny = grid.ns + dx, dy = grid.gridspacing + pcur = grid.fields["adjpcur"].value + vx_cur, vy_cur = grid.fields["adjvcur"].value + fact_m0 = grid.fields["fact_m0"].value + fact_m1_x, fact_m1_y = grid.fields["fact_m1_stag"].value + ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value + ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ_adj"].value + a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value + b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value + halo = length(a_x_r) + # Precompute divisions _dx = 1 / (dx * 24) _dy = 1 / (dy * 24) diff --git a/src/models/acoustic/backends/shared/standard_xPU.jl b/src/models/acoustic/backends/shared/standard_xPU.jl index 3aede7c..569c7d1 100644 --- a/src/models/acoustic/backends/shared/standard_xPU.jl +++ b/src/models/acoustic/backends/shared/standard_xPU.jl @@ -1,4 +1,4 @@ -zeros(T, x...) = @zeros(x..., eltype=T) -ones(T, x...) = @ones(x..., eltype=T) -rand(T, x...) = @rand(x..., eltype=T) -fill(T, x...) = @rand(x..., eltype=T) \ No newline at end of file +zeros(T, x...) = @zeros(x..., eltype = T) +ones(T, x...) = @ones(x..., eltype = T) +rand(T, x...) = @rand(x..., eltype = T) +fill(T, x...) = @rand(x..., eltype = T) \ No newline at end of file diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index c3ee532..7015aaf 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -405,7 +405,7 @@ function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, return end -function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T,N}, +function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T, N}, srccoeij_bk::Array{Int}, srccoeval_bk::Array{T}, reccoeij_bk::Array{Int}, @@ -416,7 +416,7 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T,N}, Mxx_bk::Vector{T}, Mzz_bk::Vector{T}, Mxz_bk::Vector{T}; - save_trace::Bool=true) where {T,N} + save_trace::Bool=true) where {T, N} # function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T,N}, # possrcs_bk::Array{Int,2}, # srctf_bk::Matrix{T}, diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index 7305590..a047a68 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -1,7 +1,7 @@ -abstract type ElasticWaveSimul{T,N} <: WaveSimulation{T,N} end +abstract type ElasticWaveSimul{T, N} <: WaveSimulation{T, N} end -abstract type ElasticIsoWaveSimul{T,N} <: ElasticWaveSimul{T,N} end +abstract type ElasticIsoWaveSimul{T, N} <: ElasticWaveSimul{T, N} end abstract type ElasticMaterialProperties{T, N} <: MaterialProperties{T, N} end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index beb3f80..7995e1f 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -3,13 +3,13 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::ElasticIsoCPMLWaveSimul{T,N}, + wavsim::ElasticIsoCPMLWaveSimul{T, N}, shot::Shot # possrcs::Matrix{<:Int}, # posrecs::Matrix{<:Int}, # srctf, # recs -) where {T,N} +) where {T, N} # scale source time function, etc. # find nearest grid points indexes for both sources and receivers @@ -126,7 +126,7 @@ function spreadsrcrecinterp2D( gridsize::NTuple{N, Int}, positions::Matrix{T}; nptssinc::Int=4, xstart::T=0.0, zstart::T=0.0 -) where {T,N} +) where {T, N} nloc = size(positions, 1) Ndim = size(positions, 2) @assert Ndim == 2 diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 23b63cb..1a7fb93 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,7 +2,7 @@ # Functions for all ElasticIsoWaveSimul subtypes -@views function check_matprop(wavsim::ElasticIsoWaveSimul{T,N}, matprop::ElasticIsoMaterialProperties{T,N}) where {T,N} +@views function check_matprop(wavsim::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Checks vp = sqrt.((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" @@ -41,7 +41,7 @@ function check_numerics( return end -@views function update_matprop!(wavsim::ElasticIsoWaveSimul{T,N}, matprop::ElasticIsoMaterialProperties{T,N}) where {T,N} +@views function update_matprop!(wavsim::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Update material properties wavsim.matprop.λ .= matprop.λ @@ -108,7 +108,7 @@ end ############################################################## -struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} +struct ElasticIsoCPMLWaveSimul{T, N} <: ElasticIsoWaveSimul{T, N} # Physics domainextent::NTuple{N, T} # Numerics @@ -129,7 +129,7 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} # Logging parameters infoevery::Int # Material properties - matprop::AbstrElasticIsoMaterialProperties{T,N} + matprop::AbstrElasticIsoMaterialProperties{T, N} # Forward computation arrays velpartic::Any # 2D: 2 comp, 3D: 3 comp stress::Any # 2D: 3 arrays, 3D: 6 arrays @@ -163,7 +163,7 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} check_freq::Union{Int, Nothing}=nothing, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing - ) where {T,N} + ) where {T, N} # Check numerics @assert all(gridsize .> 0) "All numbers of grid points must be positive!" @assert all(gridspacing .> 0) "All grid spacings must be positive!" @@ -179,7 +179,7 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} domainextent = gridspacing .* (gridsize .- 1) # Select backend - backend = select_backend(ElasticIsoCPMLWaveSimul{T,N}, parall) + backend = select_backend(ElasticIsoCPMLWaveSimul{T, N}, parall) V = backend.Data.Array{T, 1} # Initialize computational arrays @@ -263,7 +263,7 @@ struct ElasticIsoCPMLWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - return new{T,N}( + return new{T, N}( domainextent, gridsize, gridspacing, @@ -299,7 +299,7 @@ end # Specific functions for ElasticIsoCPMLWaveSimul -@views function reset!(wavsim::ElasticIsoCPMLWaveSimul{T,N}) where {T,N} +@views function reset!(wavsim::ElasticIsoCPMLWaveSimul{T, N}) where {T, N} # Reset computational arrays for p in propertynames(wavsim.velpartic) @@ -335,7 +335,7 @@ GridTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = LocalGrid() ########################################################### -struct ElasticIsoReflWaveSimul{T,N} <: ElasticIsoWaveSimul{T,N} end # TODO implementation +struct ElasticIsoReflWaveSimul{T, N} <: ElasticIsoWaveSimul{T, N} end # TODO implementation ########################################################### diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl index 6d9ec05..84684a5 100644 --- a/src/models/elastic/ela_params.jl +++ b/src/models/elastic/ela_params.jl @@ -5,7 +5,7 @@ Parameters for elastic wave simulations $(TYPEDFIELDS) """ -struct InputParametersElastic{T,N} <: InputParameters{T,N} +struct InputParametersElastic{T, N} <: InputParameters{T, N} "Number of time steps" ntimesteps::Int "Time step" @@ -23,9 +23,8 @@ struct InputParametersElastic{T,N} <: InputParameters{T,N} gridsize::NTuple{N, Int}, gridspacing::NTuple{N, T}, boundcond::InputBoundaryConditionParameters{T} - ) where {T,N} + ) where {T, N} @assert N <= 3 "Dimensionality must be less than or equal to 3!" - new{T,N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) + new{T, N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) end - end \ No newline at end of file diff --git a/src/receivers.jl b/src/receivers.jl index 9d23c4e..522a34f 100644 --- a/src/receivers.jl +++ b/src/receivers.jl @@ -68,7 +68,7 @@ Type representing a multi-receiver configuration for a wave propagation shot. $(TYPEDFIELDS) """ # What about using the package ComputedFieldTypes.jl? @computed ... -struct VectorReceivers{T,N} <: Receivers{T} +struct VectorReceivers{T, N} <: Receivers{T} "Receiver positions" positions::Matrix{T} "Array holding seismograms (as columns)" diff --git a/src/shot.jl b/src/shot.jl index 8572569..07f3e65 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -6,11 +6,11 @@ Type representing a source-receiver pair, i.e., a \"shot\". $(TYPEDFIELDS) """ -Base.@kwdef struct Shot +Base.@kwdef struct Shot{T} "Structure containing the appropriate Sources for a given simulation." - srcs::Sources + srcs::Sources{T} "Structure containing the appropriate Receivers for a given simulation." - recs::Receivers + recs::Receivers{T} end ################################################## @@ -29,7 +29,7 @@ end # find nearest grid point for each source idx_positions = zeros(Int, size(positions)) # sources positions (in grid points) for s in 1:nsrcs - tmp = [positions[s, i] / model.gridspacing[i] + 1 for i in 1:ncoos] + tmp = [positions[s, i] / model.grid.gridspacing[i] + 1 for i in 1:ncoos] idx_positions[s, :] .= round.(Int, tmp, RoundNearestTiesUp) end return idx_positions diff --git a/src/solve.jl b/src/solve.jl index 216339e..6e70495 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -1,6 +1,6 @@ ### UPDATE MATERIAL PROPERTIES ## -@views function set_wavesim_matprop!(wavesim::WaveSimulation{T,N}, matprop::MaterialProperties{T, N}) where {T, N} +@views function set_wavesim_matprop!(wavesim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}) where {T, N} @debug "Checking new material properties" check_matprop(wavesim, matprop) @debug "Updating WaveSimulation material properties" @@ -11,9 +11,9 @@ end ## single WaveSimulation object @views function run_swforward!( - wavsim::WaveSimulation{T,N}, + wavsim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; )::Union{Vector{Array{T}}, Nothing} where {T, N} # Check wavesim consistency @@ -56,9 +56,9 @@ end ## :threadpersrc, multiple WaveSimulation objects @views function run_swforward!( - wavsim::Vector{<:WaveSimulation{T,N}}, + wavsim::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; )::Union{Vector{Array{T}}, Nothing} where {T, N} nwsim = length(wavsim) nthr = Threads.nthreads() @@ -115,9 +115,9 @@ end ## single or multiple WaveSimulation objects @views function run_swmisfit!( - wavsim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, + wavsim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; misfit::AbstractMisfit=L2Misfit(nothing) )::T where {T, N} @@ -145,13 +145,13 @@ end ## single WaveSimulation object @views function run_swgradient!( - wavsim::WaveSimulation{T,N}, + wavsim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) )::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -189,13 +189,13 @@ end ## :threadpersrc, multiple WaveSimulation objects @views function run_swgradient!( - wavsim::Vector{<:WaveSimulation{T,N}}, + wavsim::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) )::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} nwsim = length(wavsim) nthr = Threads.nthreads() # make sure the number of threads has not changed! diff --git a/src/wrappers.jl b/src/wrappers.jl index 45a3307..cf637c4 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -15,7 +15,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -29,7 +29,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). function swforward!( params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; parall::Symbol=:threads, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, @@ -58,7 +58,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -69,7 +69,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swforward!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T}}, Nothing} where {T, N} if logger === nothing logger = current_logger() @@ -90,7 +90,7 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -106,7 +106,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). function swmisfit!( params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; parall::Symbol=:threads, misfit::AbstractMisfit=L2Misfit(nothing), logger::Union{Nothing, AbstractLogger}=nothing @@ -131,7 +131,7 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -144,7 +144,7 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ -function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swmisfit!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::T where {T, N} if logger === nothing logger = current_logger() @@ -173,7 +173,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -188,9 +188,9 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ function swgradient!( - params::InputParameters{T,N}, + params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot}; + shots::Vector{Shot{T}}; parall::Symbol=:threads, check_freq::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, @@ -199,7 +199,7 @@ function swgradient!( smooth_radius::Int=5, logger::Union{Nothing, AbstractLogger}=nothing )::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -228,7 +228,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -242,9 +242,9 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ -function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot}; +function swgradient!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -286,11 +286,11 @@ function build_wavesim(params::InputParameters{T, N}, matprop::MaterialPropertie end build_concrete_wavesim( - params::InputParametersAcoustic{T,N}, - matprop::VpAcousticCDMaterialProperties{T,N}, + params::InputParametersAcoustic{T, N}, + matprop::VpAcousticCDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters{T}; kwargs... -) where {T,N} = AcousticCDCPMLWaveSimul( +) where {T, N} = AcousticCDCPMLWaveSimul( params, matprop, cpmlparams; @@ -298,28 +298,23 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersAcoustic{T,N}, - matprop::VpRhoAcousticVDMaterialProperties{T,N}, + params::InputParametersAcoustic{T, N}, + matprop::VpRhoAcousticVDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters; kwargs... -) where {T,N} = AcousticVDStaggeredCPMLWaveSimul( - params.gridsize, - params.gridspacing, - params.ntimesteps, - params.dt, +) where {T, N} = AcousticVDStaggeredCPMLWaveSimul( + params, matprop, - cpmlparams.halo, - cpmlparams.rcoef; - freetop=cpmlparams.freeboundtop, + cpmlparams; kwargs... ) build_concrete_wavesim( - params::InputParametersElastic{T,N}, - matprop::ElasticIsoMaterialProperties{T,N}, + params::InputParametersElastic{T, N}, + matprop::ElasticIsoMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters; kwargs... -) where {T,N} = ElasticIsoCPMLWaveSimul( +) where {T, N} = ElasticIsoCPMLWaveSimul( params.gridsize, params.gridspacing, params.ntimesteps, From de995c3885c7526f748c8a6c61a8f85ec0e29f76 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 10:19:16 +0200 Subject: [PATCH 053/111] Rename all wavsim to model and fix init_gradient bug --- src/checks.jl | 10 +-- src/models/acoustic/acou_forward.jl | 62 +++++++-------- src/models/acoustic/acou_models.jl | 10 +-- .../backends/Elastic2D_Iso_CPML_Serial.jl | 36 ++++----- src/models/elastic/ela_forward.jl | 52 ++++++------- src/models/elastic/ela_models.jl | 56 ++++++------- src/solve.jl | 78 +++++++++---------- 7 files changed, 152 insertions(+), 152 deletions(-) diff --git a/src/checks.jl b/src/checks.jl index d9e1874..c4bdfb2 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -1,5 +1,5 @@ -function check_sim_consistency(wavsim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}) where {T, N} +function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}) where {T, N} tysource = typeof(shots[1].srcs) tyreceiver = typeof(shots[1].recs) @@ -11,19 +11,19 @@ function check_sim_consistency(wavsim::WaveSimulation{T, N}, matprop::MaterialPr end # Check that the subtypes of WaveSimulation, MaterialProperties and Shot are consistent - if wavsim isa AcousticCDCPMLWaveSimul{T, N, <:AbstractArray{T, N}} && + if model isa AcousticCDCPMLWaveSimul{T, N, <:AbstractArray{T, N}} && matprop isa VpAcousticCDMaterialProperties{T, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif wavsim isa AcousticVDStaggeredCPMLWaveSimul{T, N} && + elseif model isa AcousticVDStaggeredCPMLWaveSimul{T, N} && matprop isa VpRhoAcousticVDMaterialProperties{T, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif wavsim isa ElasticIsoCPMLWaveSimul{T, 2} && # <<<<<---------<<<< + elseif model isa ElasticIsoCPMLWaveSimul{T, 2} && # <<<<<---------<<<< matprop isa ElasticIsoMaterialProperties{T, 2} && tysource <: MomentTensorSources && tyreceiver <: VectorReceivers @@ -31,7 +31,7 @@ function check_sim_consistency(wavsim::WaveSimulation{T, N}, matprop::MaterialPr end return error("Types of WaveSimulation, MaterialProperties and Sources/Receivers are inconsistent \ - \n $(typeof(wavsim)), \n $(typeof(matprop)), \n $(typeof(shots[1].srcs)), $(typeof(shots[1].recs))") + \n $(typeof(model)), \n $(typeof(matprop)), \n $(typeof(shots[1].srcs)), $(typeof(shots[1].recs))") end function check_shot(model::WaveSimulation, shot::Shot; kwargs...) diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 263ba0d..d1ca72a 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -1,19 +1,19 @@ # Generic function -swforward_1shot!(wavsim::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) +swforward_1shot!(model::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) # Scaling for AcousticCDWaveSimul -@views function possrcrec_scaletf(wavsim::AcousticWaveSimul, shot::Shot) +@views function possrcrec_scaletf(model::AcousticWaveSimul, shot::Shot) # find nearest grid points indexes for both sources and receivers - possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) - posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + possrcs = find_nearest_grid_points(model, shot.srcs.positions) + posrecs = find_nearest_grid_points(model, shot.recs.positions) # source time function # scale with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(wavsim.grid.gridspacing) .* (wavsim.dt^2) + scal_srctf = shot.srcs.tf ./ prod(model.grid.gridspacing) .* (model.dt^2) # scale with velocity squared at each source position for s in axes(scal_srctf, 2) - scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 + scal_srctf[:, s] .*= model.matprop.vp[possrcs[s, :]...] .^ 2 end return possrcs, posrecs, scal_srctf @@ -21,45 +21,45 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::AcousticCDCPMLWaveSimul{T, N}, + model::AcousticCDCPMLWaveSimul{T, N}, shot::Shot ) where {T, N} # Scale source time function, etc. - possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) + possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) # Get computational grid and backend - grid = wavsim.grid - backend = select_backend(typeof(wavsim), wavsim.parall) + grid = model.grid + backend = select_backend(typeof(model), model.parall) # Numerics - nt = wavsim.nt + nt = model.nt # Wrap sources and receivers arrays possrcs_bk = backend.Data.Array(possrcs) posrecs_bk = backend.Data.Array(posrecs) srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.Data.Array(shot.recs.seismograms) # Reset wavesim - reset!(wavsim) + reset!(model) # Time loop for it in 1:nt # Compute one forward step backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info - if it % wavsim.infoevery == 0 + if it % model.infoevery == 0 @info @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, - wavsim.dt * (it - 1), + model.dt * (it - 1), maximum(abs.(Array(pcur))) ) end # Save snapshot - if snapenabled(wavsim) && it % wavsim.snapevery == 0 + if snapenabled(model) && it % model.snapevery == 0 @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) - copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], pcur) + copyto!(model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)], pcur) end end @@ -70,17 +70,17 @@ end ##################################################### # Scaling for AcousticVDStaggeredCPMLWaveSimul -@views function possrcrec_scaletf(wavsim::AcousticVDStaggeredCPMLWaveSimul, shot::Shot) +@views function possrcrec_scaletf(model::AcousticVDStaggeredCPMLWaveSimul, shot::Shot) # find nearest grid points indexes for both sources and receivers - possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) - posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + possrcs = find_nearest_grid_points(model, shot.srcs.positions) + posrecs = find_nearest_grid_points(model, shot.recs.positions) # source time function # scale with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(wavsim.grid.gridspacing) .* (wavsim.dt) + scal_srctf = shot.srcs.tf ./ prod(model.grid.gridspacing) .* (model.dt) # scale with velocity squared times density at each source position (its like dividing by m0) for s in axes(scal_srctf, 2) - scal_srctf[:, s] .*= wavsim.matprop.vp[possrcs[s, :]...] .^ 2 .* wavsim.matprop.rho[possrcs[s, :]...] + scal_srctf[:, s] .*= model.matprop.vp[possrcs[s, :]...] .^ 2 .* model.matprop.rho[possrcs[s, :]...] end return possrcs, posrecs, scal_srctf @@ -88,45 +88,45 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::AcousticVDStaggeredCPMLWaveSimul{T, N}, + model::AcousticVDStaggeredCPMLWaveSimul{T, N}, shot::Shot ) where {T, N} # scale source time function, etc. - possrcs, posrecs, scal_srctf = possrcrec_scaletf(wavsim, shot) + possrcs, posrecs, scal_srctf = possrcrec_scaletf(model, shot) # Get computational grid and backend - grid = wavsim.grid - backend = select_backend(typeof(wavsim), wavsim.parall) + grid = model.grid + backend = select_backend(typeof(model), model.parall) # Numerics - nt = wavsim.nt + nt = model.nt # Wrap sources and receivers arrays possrcs_bk = backend.Data.Array(possrcs) posrecs_bk = backend.Data.Array(posrecs) srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.Data.Array(shot.recs.seismograms) # Reset wavesim - reset!(wavsim) + reset!(model) # Time loop for it in 1:nt # Compute one forward step backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info - if it % wavsim.infoevery == 0 + if it % model.infoevery == 0 @info @sprintf( "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", it, - wavsim.dt * (it - 1), + model.dt * (it - 1), maximum(abs.(Array(grid.fields["pcur"].value))) ) end # Save snapshot - if snapenabled(wavsim) && it % wavsim.snapevery == 0 + if snapenabled(model) && it % model.snapevery == 0 @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(grid.fields["pcur"].value)))) - copyto!(wavsim.snapshots[fill(Colon(), N)..., div(it, wavsim.snapevery)], grid.fields["pcur"].value) + copyto!(model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)], grid.fields["pcur"].value) end end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index ed5ddf5..e95b6ef 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -45,11 +45,11 @@ end precompute_fact!(model) end -@views precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) +precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) -@views init_gradient(model::AcousticCDWaveSimul{T, N})::Dict{String, Array{T, N}} where {T, N} = Dict("vp" => zero(model.matprop.vp)) +init_gradient(model::AcousticCDWaveSimul{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp)) -@views accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} = totgrad["vp"] .+= curgrad["vp"] +accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} = totgrad["vp"] .+= curgrad["vp"] ########################################################### @@ -303,9 +303,9 @@ end end end -@views init_gradient(model::AcousticVDStaggeredWaveSimul{T, N})::Dict{String, Array{T, N}} where {T, N} = Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) +init_gradient(model::AcousticVDStaggeredWaveSimul{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) -@views function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} +function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} totgrad["vp"] .+= curgrad["vp"] totgrad["rho"] .+= curgrad["rho"] end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 7015aaf..001c1fb 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -405,7 +405,7 @@ function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, return end -function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T, N}, +function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimul{T, N}, srccoeij_bk::Array{Int}, srccoeval_bk::Array{T}, reccoeij_bk::Array{Int}, @@ -417,7 +417,7 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T, N}, Mzz_bk::Vector{T}, Mxz_bk::Vector{T}; save_trace::Bool=true) where {T, N} - # function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T,N}, + # function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimul{T,N}, # possrcs_bk::Array{Int,2}, # srctf_bk::Matrix{T}, # posrecs_bk::Array{Int,2}, @@ -429,22 +429,22 @@ function forward_onestep_CPML!(wavsim::ElasticIsoCPMLWaveSimul{T, N}, # save_trace::Bool=true) where {N} @assert N == 2 - freetop = wavsim.freetop - cpmlcoeffs = wavsim.cpmlcoeffs - matprop = wavsim.matprop - dx = wavsim.gridspacing[1] - dz = wavsim.gridspacing[2] - dt = wavsim.dt - nx, nz = wavsim.gridsize[1:2] - halo = wavsim.halo - - vx = wavsim.velpartic.vx - vz = wavsim.velpartic.vz - σxx = wavsim.stress.σxx - σzz = wavsim.stress.σzz - σxz = wavsim.stress.σxz - - psi = wavsim.ψ + freetop = model.freetop + cpmlcoeffs = model.cpmlcoeffs + matprop = model.matprop + dx = model.gridspacing[1] + dz = model.gridspacing[2] + dt = model.dt + nx, nz = model.gridsize[1:2] + halo = model.halo + + vx = model.velpartic.vx + vz = model.velpartic.vz + σxx = model.stress.σxx + σzz = model.stress.σzz + σxz = model.stress.σxz + + psi = model.ψ a_x = cpmlcoeffs[1].a a_x_half = cpmlcoeffs[1].a_h diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 7995e1f..d7b15c3 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -1,9 +1,9 @@ -swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(wavsim), wavsim, args...) +swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) @views function swforward_1shot!( ::CPMLBoundaryCondition, - wavsim::ElasticIsoCPMLWaveSimul{T, N}, + model::ElasticIsoCPMLWaveSimul{T, N}, shot::Shot # possrcs::Matrix{<:Int}, # posrecs::Matrix{<:Int}, @@ -13,16 +13,16 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC # scale source time function, etc. # find nearest grid points indexes for both sources and receivers - # possrcs = find_nearest_grid_points(wavsim, shot.srcs.positions) - # posrecs = find_nearest_grid_points(wavsim, shot.recs.positions) + # possrcs = find_nearest_grid_points(model, shot.srcs.positions) + # posrecs = find_nearest_grid_points(model, shot.recs.positions) if N == 2 # interpolation coefficients for sources - srccoeij, srccoeval = spreadsrcrecinterp2D(wavsim.gridspacing, wavsim.gridsize, + srccoeij, srccoeval = spreadsrcrecinterp2D(model.gridspacing, model.gridsize, shot.srcs.positions; nptssinc=4, xstart=0.0, zstart=0.0) # interpolation coefficients for receivers - reccoeij, reccoeval = spreadsrcrecinterp2D(wavsim.gridspacing, wavsim.gridsize, + reccoeij, reccoeval = spreadsrcrecinterp2D(model.gridspacing, model.gridsize, shot.recs.positions; nptssinc=4, xstart=0.0, zstart=0.0) elseif N == 3 @@ -35,32 +35,32 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC momtens = shot.srcs.momtens # Numerics - nt = wavsim.nt + nt = model.nt # Wrap sources and receivers arrays - # possrcs_bk = wavsim.backend.Data.Array(possrcs) - # posrecs_bk = wavsim.backend.Data.Array(posrecs) + # possrcs_bk = model.backend.Data.Array(possrcs) + # posrecs_bk = model.backend.Data.Array(posrecs) - srccoeij_bk = wavsim.backend.Data.Array(srccoeij) - srccoeval_bk = wavsim.backend.Data.Array(srccoeval) - reccoeij_bk = wavsim.backend.Data.Array(reccoeij) - reccoeval_bk = wavsim.backend.Data.Array(reccoeval) + srccoeij_bk = model.backend.Data.Array(srccoeij) + srccoeval_bk = model.backend.Data.Array(srccoeval) + reccoeij_bk = model.backend.Data.Array(reccoeij) + reccoeval_bk = model.backend.Data.Array(reccoeval) - srctf_bk = wavsim.backend.Data.Array(srctf) - traces_bk = wavsim.backend.Data.Array(shot.recs.seismograms) + srctf_bk = model.backend.Data.Array(srctf) + traces_bk = model.backend.Data.Array(shot.recs.seismograms) if N == 2 ## ONLY 2D for now!!! - Mxx_bk = wavsim.backend.Data.Array(momtens.Mxx) - Mzz_bk = wavsim.backend.Data.Array(momtens.Mzz) - Mxz_bk = wavsim.backend.Data.Array(momtens.Mxz) + Mxx_bk = model.backend.Data.Array(momtens.Mxx) + Mzz_bk = model.backend.Data.Array(momtens.Mzz) + Mxz_bk = model.backend.Data.Array(momtens.Mxz) elseif N == 3 error("swforward_1shot!(): Elastic 3D not yet implemented!") end # Reset wavesim - reset!(wavsim) + reset!(model) # Zeros traces (there is a summation in record_receivers2D!() traces_bk .= 0.0 @@ -68,7 +68,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC for it in 1:nt if N == 2 # Compute one forward step - wavsim.backend.forward_onestep_CPML!(wavsim, + model.backend.forward_onestep_CPML!(model, srccoeij_bk, srccoeval_bk, reccoeij_bk, @@ -79,7 +79,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC Mxx_bk, Mzz_bk, Mxz_bk; save_trace=true) # # Compute one forward step - # wavsim.backend.forward_onestep_CPML!(wavsim, + # model.backend.forward_onestep_CPML!(model, # possrcs_bk, # srctf_bk, # posrecs_bk, @@ -92,7 +92,7 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC end # Print timestep info - if it % wavsim.infoevery == 0 + if it % model.infoevery == 0 # Move the cursor to the beginning to overwrite last line # ter = REPL.Terminals.TTYTerminal("", stdin, stdout, stderr) # REPL.Terminals.clear_line(ter) @@ -100,19 +100,19 @@ swforward_1shot!(wavsim::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryC @info @sprintf( "Iteration: %d/%d, simulation time: %g s", it, nt, - wavsim.dt * (it - 1) + model.dt * (it - 1) ) end # Save snapshot - if snapenabled(wavsim) && it % wavsim.snapevery == 0 + if snapenabled(model) && it % model.snapevery == 0 #error("Snapshot for elastic not yet implemented...") @info @sprintf("Snapping iteration: %d", it) dummyidxs = fill(Colon(), N) # Vx - wavsim.snapshots[1][dummyidxs..., div(it, wavsim.snapevery)] .= Array(wavsim.velpartic.vx) + model.snapshots[1][dummyidxs..., div(it, model.snapevery)] .= Array(model.velpartic.vx) # Vz - wavsim.snapshots[2][dummyidxs..., div(it, wavsim.snapevery)] .= Array(wavsim.velpartic.vz) + model.snapshots[2][dummyidxs..., div(it, model.snapevery)] .= Array(model.velpartic.vz) end end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 1a7fb93..d8782ef 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,19 +2,19 @@ # Functions for all ElasticIsoWaveSimul subtypes -@views function check_matprop(wavsim::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Checks vp = sqrt.((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(vp) == wavsim.gridsize "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(wavsim.gridsize)" + @assert size(vp) == model.gridsize "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.gridsize)" @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" @assert all(matprop.ρ .> 0) "Density must be positive!" # Check courant condition - vel_max = get_maximum_func(wavsim)(vp) - tmp = sqrt.(sum(1 ./ wavsim.gridspacing .^ 2)) - courant = vel_max * wavsim.dt * tmp + vel_max = get_maximum_func(model)(vp) + tmp = sqrt.(sum(1 ./ model.gridspacing .^ 2)) + courant = vel_max * model.dt * tmp @info "Courant number: $(courant)" if courant > 1.0 @warn "Courant condition not satisfied! [$(courant)]" @@ -24,14 +24,14 @@ end function check_numerics( - wavsim::ElasticIsoWaveSimul, + model::ElasticIsoWaveSimul, shot::Shot; min_ppw::Int=10 ) # Check points per wavelengh # min Vs - vel_min = get_minimum_func(wavsim)(sqrt.(wavsim.matprop.μ ./ wavsim.matprop.ρ)) - h_max = maximum(wavsim.gridspacing) + vel_min = get_minimum_func(model)(sqrt.(model.matprop.μ ./ model.matprop.ρ)) + h_max = maximum(model.gridspacing) fmax = shot.srcs.domfreq * 2.0 ppw = vel_min / (fmax * h_max) @info "Points per wavelength: $(ppw)" @@ -41,15 +41,15 @@ function check_numerics( return end -@views function update_matprop!(wavsim::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Update material properties - wavsim.matprop.λ .= matprop.λ - wavsim.matprop.μ .= matprop.μ - wavsim.matprop.ρ .= matprop.ρ + model.matprop.λ .= matprop.λ + model.matprop.μ .= matprop.μ + model.matprop.ρ .= matprop.ρ # the following on device? - precomp_elaprop!(wavsim.matprop) + precomp_elaprop!(model.matprop) return end @@ -175,7 +175,7 @@ struct ElasticIsoCPMLWaveSimul{T, N} <: ElasticIsoWaveSimul{T, N} gridsize_cpml = freetop ? gridsize[1:(end-1)] : gridsize @assert all(n -> n >= 2halo + 3, gridsize_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" - # Compute wavsim sizes + # Compute model sizes domainextent = gridspacing .* (gridsize .- 1) # Select backend @@ -299,29 +299,29 @@ end # Specific functions for ElasticIsoCPMLWaveSimul -@views function reset!(wavsim::ElasticIsoCPMLWaveSimul{T, N}) where {T, N} +@views function reset!(model::ElasticIsoCPMLWaveSimul{T, N}) where {T, N} # Reset computational arrays - for p in propertynames(wavsim.velpartic) - getfield(wavsim.velpartic, p) .= 0.0 + for p in propertynames(model.velpartic) + getfield(model.velpartic, p) .= 0.0 end - for p in propertynames(wavsim.stress) - getfield(wavsim.stress, p) .= 0.0 + for p in propertynames(model.stress) + getfield(model.stress, p) .= 0.0 end - for p in propertynames(wavsim.ψ) - getfield(wavsim.ψ, p) .= 0.0 + for p in propertynames(model.ψ) + getfield(model.ψ, p) .= 0.0 end # Reset gradient arrays - if wavsim.gradient - for p in eachindex(wavsim.adj) - wavsim.adj[p][:] .= 0.0 + if model.gradient + for p in eachindex(model.adj) + model.adj[p][:] .= 0.0 end - for p in eachindex(wavsim.grad) - wavsim.grad[p] .= 0.0 + for p in eachindex(model.grad) + model.grad[p] .= 0.0 end - for p in propertynames(wavsim.ψ_adj) - getfield(wavsim.ψ_adj, p) .= 0.0 + for p in propertynames(model.ψ_adj) + getfield(model.ψ_adj, p) .= 0.0 end end end diff --git a/src/solve.jl b/src/solve.jl index 6e70495..f1c7a7e 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -11,23 +11,23 @@ end ## single WaveSimulation object @views function run_swforward!( - wavsim::WaveSimulation{T, N}, + model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; )::Union{Vector{Array{T}}, Nothing} where {T, N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(wavsim, matprop, shots) + check_sim_consistency(model, matprop, shots) # Set wavesim material properties # Remark: matprop in wavesim are mutated @debug "Setting wavesim material properties" - set_wavesim_matprop!(wavsim, matprop) + set_wavesim_matprop!(model, matprop) # Now onwards matprop from "outside" should not be used anymore!!! # Snapshots setup - takesnapshots = snapenabled(wavsim) + takesnapshots = snapenabled(model) if takesnapshots snapshots_per_shot = [] end @@ -37,14 +37,14 @@ end @info "Shot #$s" # Initialize shot @debug "Initializing shot" - init_shot!(wavsim, singleshot) + init_shot!(model, singleshot) # Compute forward solver @info "Computing forward solver" - swforward_1shot!(wavsim, singleshot) + swforward_1shot!(model, singleshot) # Save shot's snapshots if takesnapshots @info "Saving snapshots" - push!(snapshots_per_shot, Array(wavsim.snapshots)) + push!(snapshots_per_shot, Array(model.snapshots)) end end @@ -56,11 +56,11 @@ end ## :threadpersrc, multiple WaveSimulation objects @views function run_swforward!( - wavsim::Vector{<:WaveSimulation{T, N}}, + model::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; )::Union{Vector{Array{T}}, Nothing} where {T, N} - nwsim = length(wavsim) + nwsim = length(model) nthr = Threads.nthreads() # make sure the number of threads has not changed! @assert nthr == nwsim @@ -69,15 +69,15 @@ end for w in 1:nwsim # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(wavsim[w], matprop, shots) + check_sim_consistency(model[w], matprop, shots) # Set wavesim material properties # Remark: matprop in wavesim are mutated @debug "Setting wavesim material properties" - set_wavesim_matprop!(wavsim[w], matprop) + set_wavesim_matprop!(model[w], matprop) # Now onwards matprop from outside should not be used anymore!!! # Snapshots setup - if snapenabled(wavsim[w]) + if snapenabled(model[w]) snapshots_per_shot[w] = [] end end @@ -93,14 +93,14 @@ end singleshot = shots[s] # Initialize shot @debug "Initializing shot" - init_shot!(wavsim[w], singleshot) + init_shot!(model[w], singleshot) # Compute forward solver @info "Computing forward solver" - swforward_1shot!(wavsim[w], singleshot) + swforward_1shot!(model[w], singleshot) # Save shot's snapshots - if snapenabled(wavsim[w]) + if snapenabled(model[w]) @info "Saving snapshots" - push!(snapshots_per_shot[w], copy(wavsim[w].snapshots)) + push!(snapshots_per_shot[w], copy(model[w].snapshots)) end end end @@ -115,25 +115,25 @@ end ## single or multiple WaveSimulation objects @views function run_swmisfit!( - wavsim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, + model::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; misfit::AbstractMisfit=L2Misfit(nothing) )::T where {T, N} # Solve forward model for all shots - run_swforward!(wavsim, matprop, shots) + run_swforward!(model, matprop, shots) # Compute total misfit for all shots @info "Computing misfit" totmisfitval = 0 for singleshot in shots @debug "Checking invcov matrix" - if typeof(wavsim) <: Vector{<:WaveSimulation} - for i in eachindex(wavsim) - check_invcov_matrix(wavsim[i], singleshot.recs.invcov) + if typeof(model) <: Vector{<:WaveSimulation} + for i in eachindex(model) + check_invcov_matrix(model[i], singleshot.recs.invcov) end else - check_invcov_matrix(wavsim, singleshot.recs.invcov) + check_invcov_matrix(model, singleshot.recs.invcov) end totmisfitval += misfit(singleshot.recs, matprop) end @@ -145,7 +145,7 @@ end ## single WaveSimulation object @views function run_swgradient!( - wavsim::WaveSimulation{T, N}, + model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; compute_misfit::Bool=false, @@ -155,28 +155,28 @@ end # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(wavsim, matprop, shots) + check_sim_consistency(model, matprop, shots) # Set wavesim material properties @debug "Setting wavesim material properties" - set_wavesim_matprop!(wavsim, matprop) + set_wavesim_matprop!(model, matprop) # Initialize total gradient and total misfit - totgrad = init_gradient(wavsim) + totgrad = init_gradient(model) totmisfitval = 0 # Shots loop for (s, singleshot) in enumerate(shots) @info "Shot #$s" # Initialize shot @debug "Initializing shot" - init_shot!(wavsim, singleshot) + init_shot!(model, singleshot) @debug "Checking invcov matrix" - check_invcov_matrix(wavsim, singleshot.recs.invcov) + check_invcov_matrix(model, singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" - curgrad = swgradient_1shot!(wavsim, singleshot, misfit) + curgrad = swgradient_1shot!(model, singleshot, misfit) # Accumulate gradient - accumulate_gradient!(totgrad, curgrad, wavsim) + accumulate_gradient!(totgrad, curgrad, model) # Compute misfit if needed if compute_misfit @info "Computing misfit" @@ -189,14 +189,14 @@ end ## :threadpersrc, multiple WaveSimulation objects @views function run_swgradient!( - wavsim::Vector{<:WaveSimulation{T, N}}, + model::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) )::Union{Dict{String, Array{T, N}}, Tuple{Dict{String, Array{T, N}}, T}} where {T, N} - nwsim = length(wavsim) + nwsim = length(model) nthr = Threads.nthreads() # make sure the number of threads has not changed! @assert Threads.nthreads() == nwsim @@ -204,11 +204,11 @@ end for w in 1:nwsim # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(wavsim[w], matprop, shots) + check_sim_consistency(model[w], matprop, shots) # Set wavesim material properties @debug "Setting wavesim material properties" - set_wavesim_matprop!(wavsim[w], matprop) + set_wavesim_matprop!(model[w], matprop) end # Initialize total gradient and total misfit @@ -230,13 +230,13 @@ end @info "Shot #$s" # Initialize shot @debug "Initializing shot" - init_shot!(wavsim[w], singleshot) + init_shot!(model[w], singleshot) @debug "Checking invcov matrix" - check_invcov_matrix(wavsim[w], singleshot.recs.invcov) + check_invcov_matrix(model[w], singleshot.recs.invcov) # Compute forward solver @info "Computing gradient solver" curgrad = swgradient_1shot!( - wavsim[w], singleshot, misfit + model[w], singleshot, misfit ) # Save gradient allgrad[s] = curgrad @@ -249,9 +249,9 @@ end end # Accumulate gradient and misfit - totgrad = init_gradient(wavsim) + totgrad = init_gradient(model) for curgrad in allgrad - accumulate_gradient!(wavsim, totgrad, curgrad) + accumulate_gradient!(model, totgrad, curgrad) end if compute_misfit totmisfitval = sum(allmisfitval) From 6ff62f3d1b27c56c048ba7dbf2ff4f8f1ef2a8a5 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 10:22:14 +0200 Subject: [PATCH 054/111] Rename WaveSimul to WaveSimulation (and subtypes) --- ext/CUDABackendExt.jl | 12 ++-- src/checks.jl | 6 +- src/models/acoustic/acou_abstract_types.jl | 6 +- src/models/acoustic/acou_forward.jl | 14 ++-- src/models/acoustic/acou_gradient.jl | 6 +- src/models/acoustic/acou_init_bc.jl | 6 +- src/models/acoustic/acou_models.jl | 72 +++++++++---------- src/models/backend_selection.jl | 30 ++++---- .../backends/Elastic2D_Iso_CPML_Serial.jl | 6 +- src/models/elastic/ela_abstract_types.jl | 4 +- src/models/elastic/ela_forward.jl | 4 +- src/models/elastic/ela_init_bc.jl | 6 +- src/models/elastic/ela_models.jl | 36 +++++----- src/wrappers.jl | 6 +- 14 files changed, 107 insertions(+), 107 deletions(-) diff --git a/ext/CUDABackendExt.jl b/ext/CUDABackendExt.jl index f7c212f..689859f 100644 --- a/ext/CUDABackendExt.jl +++ b/ext/CUDABackendExt.jl @@ -1,7 +1,7 @@ module CUDABackendExt using SeismicWaves, CUDA -using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimul, AcousticVDStaggeredCPMLWaveSimul +using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimulation, AcousticVDStaggeredCPMLWaveSimulation # Include CUDA backends include("../src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl") @@ -11,10 +11,10 @@ include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") # Overload backend selection -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU end \ No newline at end of file diff --git a/src/checks.jl b/src/checks.jl index c4bdfb2..dfb817b 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -11,19 +11,19 @@ function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialPro end # Check that the subtypes of WaveSimulation, MaterialProperties and Shot are consistent - if model isa AcousticCDCPMLWaveSimul{T, N, <:AbstractArray{T, N}} && + if model isa AcousticCDCPMLWaveSimulation{T, N, <:AbstractArray{T, N}} && matprop isa VpAcousticCDMaterialProperties{T, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif model isa AcousticVDStaggeredCPMLWaveSimul{T, N} && + elseif model isa AcousticVDStaggeredCPMLWaveSimulation{T, N} && matprop isa VpRhoAcousticVDMaterialProperties{T, N} && tysource <: ScalarSources && tyreceiver <: ScalarReceivers return - elseif model isa ElasticIsoCPMLWaveSimul{T, 2} && # <<<<<---------<<<< + elseif model isa ElasticIsoCPMLWaveSimulation{T, 2} && # <<<<<---------<<<< matprop isa ElasticIsoMaterialProperties{T, 2} && tysource <: MomentTensorSources && tyreceiver <: VectorReceivers diff --git a/src/models/acoustic/acou_abstract_types.jl b/src/models/acoustic/acou_abstract_types.jl index 684753f..40699fa 100644 --- a/src/models/acoustic/acou_abstract_types.jl +++ b/src/models/acoustic/acou_abstract_types.jl @@ -1,6 +1,6 @@ -abstract type AcousticWaveSimul{T, N} <: WaveSimulation{T, N} end +abstract type AcousticWaveSimulation{T, N} <: WaveSimulation{T, N} end -abstract type AcousticCDWaveSimul{T, N} <: AcousticWaveSimul{T, N} end +abstract type AcousticCDWaveSimulation{T, N} <: AcousticWaveSimulation{T, N} end -abstract type AcousticVDStaggeredWaveSimul{T, N} <: AcousticWaveSimul{T, N} end +abstract type AcousticVDStaggeredWaveSimulation{T, N} <: AcousticWaveSimulation{T, N} end diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index d1ca72a..d4cf7cf 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -1,9 +1,9 @@ # Generic function -swforward_1shot!(model::AcousticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) +swforward_1shot!(model::AcousticWaveSimulation, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) -# Scaling for AcousticCDWaveSimul -@views function possrcrec_scaletf(model::AcousticWaveSimul, shot::Shot) +# Scaling for AcousticCDWaveSimulation +@views function possrcrec_scaletf(model::AcousticWaveSimulation, shot::Shot) # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(model, shot.srcs.positions) posrecs = find_nearest_grid_points(model, shot.recs.positions) @@ -21,7 +21,7 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - model::AcousticCDCPMLWaveSimul{T, N}, + model::AcousticCDCPMLWaveSimulation{T, N}, shot::Shot ) where {T, N} @@ -69,8 +69,8 @@ end ##################################################### -# Scaling for AcousticVDStaggeredCPMLWaveSimul -@views function possrcrec_scaletf(model::AcousticVDStaggeredCPMLWaveSimul, shot::Shot) +# Scaling for AcousticVDStaggeredCPMLWaveSimulation +@views function possrcrec_scaletf(model::AcousticVDStaggeredCPMLWaveSimulation, shot::Shot) # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(model, shot.srcs.positions) posrecs = find_nearest_grid_points(model, shot.recs.positions) @@ -88,7 +88,7 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, - model::AcousticVDStaggeredCPMLWaveSimul{T, N}, + model::AcousticVDStaggeredCPMLWaveSimulation{T, N}, shot::Shot ) where {T, N} diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 593cf83..d6a35f2 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -1,9 +1,9 @@ -swgradient_1shot!(model::AcousticWaveSimul, args...; kwargs...) = +swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = swgradient_1shot!(BoundaryConditionTrait(model), model, args...; kwargs...) @views function swgradient_1shot!( ::CPMLBoundaryCondition, - model::AcousticCDWaveSimul{T, N}, + model::AcousticCDWaveSimulation{T, N}, shot::Shot, misfit )::Dict{String, Array{T, N}} where {T, N} @@ -96,7 +96,7 @@ end @views function swgradient_1shot!( ::CPMLBoundaryCondition, - model::AcousticVDStaggeredCPMLWaveSimul{T, N}, + model::AcousticVDStaggeredCPMLWaveSimulation{T, N}, shot::Shot, misfit )::Dict{String, Array{T, N}} where {T, N} diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index 72b1f07..684af94 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -1,12 +1,12 @@ -init_bdc!(model::AcousticWaveSimul, srcs::Sources) = +init_bdc!(model::AcousticWaveSimulation, srcs::Sources) = init_bdc!(BoundaryConditionTrait(model), model, srcs) -init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimul, srcs::Sources) = nothing +init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimulation, srcs::Sources) = nothing @views function init_bdc!( ::CPMLBoundaryCondition, - model::AcousticWaveSimul, + model::AcousticWaveSimulation, srcs::Sources ) N = length(model.cpmlcoeffs) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index e95b6ef..a9dfdcd 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -1,8 +1,8 @@ ########################################################### -# Functions for all AcousticWaveSimul subtypes +# Functions for all AcousticWaveSimulation subtypes -@views function check_courant_condition(model::AcousticWaveSimul{T, N}, vp::Array{T, N}) where {T, N} +@views function check_courant_condition(model::AcousticWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) courant = vel_max * model.dt * tmp @@ -13,7 +13,7 @@ end function check_numerics( - model::AcousticWaveSimul, + model::AcousticWaveSimulation, shot::Shot; min_ppw::Int=10 ) @@ -27,9 +27,9 @@ end ########################################################### -# Functions for all AcousticCDWaveSimul subtypes +# Functions for all AcousticCDWaveSimulation subtypes -@views function check_matprop(model::AcousticCDWaveSimul{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::AcousticCDWaveSimulation{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.ns)" @@ -38,22 +38,22 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticCDWaveSimul{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::AcousticCDWaveSimulation{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) # Precompute factors precompute_fact!(model) end -precompute_fact!(model::AcousticCDWaveSimul) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) +precompute_fact!(model::AcousticCDWaveSimulation) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) -init_gradient(model::AcousticCDWaveSimul{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp)) +init_gradient(model::AcousticCDWaveSimulation{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp)) -accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} = totgrad["vp"] .+= curgrad["vp"] +accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimulation{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} = totgrad["vp"] .+= curgrad["vp"] ########################################################### -struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticCDWaveSimul{T, N} +struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticCDWaveSimulation{T, N} # Parameters params::InputParametersAcoustic{T, N} cpmlparams::CPMLBoundaryConditionParameters{T} @@ -83,7 +83,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVect # Parallelization type parall::Symbol - function AcousticCDCPMLWaveSimul( + function AcousticCDCPMLWaveSimulation( params::InputParametersAcoustic{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters{T}; @@ -112,7 +112,7 @@ struct AcousticCDCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVect @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Select backend - backend = select_backend(AcousticCDCPMLWaveSimul{T, N}, parall) + backend = select_backend(AcousticCDCPMLWaveSimulation{T, N}, parall) A = backend.Data.Array{T, N} V = backend.Data.Array{T, 1} # Initialize computational grid @@ -219,7 +219,7 @@ end ########################################################### -@views function find_nearest_grid_points(model::AcousticCDCPMLWaveSimul{T}, positions::Matrix{T})::Matrix{Int} where {T} +@views function find_nearest_grid_points(model::AcousticCDCPMLWaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} # source time functions nsrcs = size(positions, 1) # number of sources ncoos = size(positions, 2) # number of coordinates @@ -232,26 +232,26 @@ end return idx_positions end -# Specific functions for AcousticCDCPMLWaveSimul +# Specific functions for AcousticCDCPMLWaveSimulation -@views function reset!(model::AcousticCDCPMLWaveSimul) +@views function reset!(model::AcousticCDCPMLWaveSimulation) reset!(model.grid; except=["fact", "a_pml", "b_pml"]) reset!(model.checkpointer) end ########################################################### -# Traits for AcousticCDCPMLWaveSimul +# Traits for AcousticCDCPMLWaveSimulation -IsSnappableTrait(::Type{<:AcousticCDCPMLWaveSimul}) = Snappable() -BoundaryConditionTrait(::Type{<:AcousticCDCPMLWaveSimul}) = CPMLBoundaryCondition() -GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() +IsSnappableTrait(::Type{<:AcousticCDCPMLWaveSimulation}) = Snappable() +BoundaryConditionTrait(::Type{<:AcousticCDCPMLWaveSimulation}) = CPMLBoundaryCondition() +GridTrait(::Type{<:AcousticCDCPMLWaveSimulation}) = LocalGrid() ########################################################### -# Functions for all AcousticVDStaggeredWaveSimul subtypes +# Functions for all AcousticVDStaggeredWaveSimulation subtypes -@views function check_courant_condition(model::AcousticVDStaggeredWaveSimul{T, N}, vp::Array{T, N}) where {T, N} +@views function check_courant_condition(model::AcousticVDStaggeredWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil @@ -262,7 +262,7 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimul}) = LocalGrid() end function check_numerics( - model::AcousticVDStaggeredWaveSimul, + model::AcousticVDStaggeredWaveSimulation, shot::Shot; min_ppw::Int=10 ) @@ -274,7 +274,7 @@ function check_numerics( @assert ppw >= min_ppw "Not enough points per wavelengh!" end -@views function check_matprop(model::AcousticVDStaggeredWaveSimul{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::AcousticVDStaggeredWaveSimulation{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == size(matprop.rho) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.ns)" @@ -284,7 +284,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticVDStaggeredWaveSimul{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::AcousticVDStaggeredWaveSimulation{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) copyto!(model.matprop.rho, matprop.rho) @@ -293,7 +293,7 @@ end precompute_fact!(model) end -@views function precompute_fact!(model::AcousticVDStaggeredWaveSimul{T, N}) where {T, N} +@views function precompute_fact!(model::AcousticVDStaggeredWaveSimulation{T, N}) where {T, N} # Precompute 1/m0 * dt factor copyto!(model.grid.fields["fact_m0"].value, model.matprop.vp .^ 2 .* model.matprop.rho .* model.dt) # Precompute m1 * dt factor by interpolation @@ -303,16 +303,16 @@ end end end -init_gradient(model::AcousticVDStaggeredWaveSimul{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) +init_gradient(model::AcousticVDStaggeredWaveSimulation{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) -function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimul{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} +function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimulation{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} totgrad["vp"] .+= curgrad["vp"] totgrad["rho"] .+= curgrad["rho"] end ########################################################### -struct AcousticVDStaggeredCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticVDStaggeredWaveSimul{T, N} +struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: AcousticVDStaggeredWaveSimulation{T, N} # Parameters params::InputParametersAcoustic{T, N} cpmlparams::CPMLBoundaryConditionParameters{T} @@ -342,7 +342,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: Abs # Parallelization type parall::Symbol - function AcousticVDStaggeredCPMLWaveSimul( + function AcousticVDStaggeredCPMLWaveSimulation( params::InputParametersAcoustic{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters{T}; @@ -371,7 +371,7 @@ struct AcousticVDStaggeredCPMLWaveSimul{T, N, A <: AbstractArray{T, N}, V <: Abs @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Select backend - backend = select_backend(AcousticCDCPMLWaveSimul{T, N}, parall) + backend = select_backend(AcousticCDCPMLWaveSimulation{T, N}, parall) A = backend.Data.Array{T, N} V = backend.Data.Array{T, 1} # Initialize computational grid @@ -486,19 +486,19 @@ end ########################################################### -# Specific functions for AcousticVDStaggeredCPMLWaveSimul +# Specific functions for AcousticVDStaggeredCPMLWaveSimulation -@views function reset!(model::AcousticVDStaggeredCPMLWaveSimul) +@views function reset!(model::AcousticVDStaggeredCPMLWaveSimulation) # Reset computational arrays reset!(model.grid; except=["fact_m0", "fact_m1_stag", "a_pml", "b_pml"]) reset!(model.checkpointer) end ########################################################### -# Traits for AcousticVDStaggeredCPMLWaveSimul +# Traits for AcousticVDStaggeredCPMLWaveSimulation -IsSnappableTrait(::Type{<:AcousticVDStaggeredCPMLWaveSimul}) = Snappable() -BoundaryConditionTrait(::Type{<:AcousticVDStaggeredCPMLWaveSimul}) = CPMLBoundaryCondition() -GridTrait(::Type{<:AcousticVDStaggeredCPMLWaveSimul}) = LocalGrid() +IsSnappableTrait(::Type{<:AcousticVDStaggeredCPMLWaveSimulation}) = Snappable() +BoundaryConditionTrait(::Type{<:AcousticVDStaggeredCPMLWaveSimulation}) = CPMLBoundaryCondition() +GridTrait(::Type{<:AcousticVDStaggeredCPMLWaveSimulation}) = LocalGrid() ########################################################### diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index d19adee..ddb5fa4 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -18,22 +18,22 @@ end ## CD = constant density ## VD = variable density -# Backend selections for AcousticCDCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:serial}}) = Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:serial}}) = Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:serial}}) = Acoustic3D_CD_CPML_Serial +# Backend selections for AcousticCDCPMLWaveSimulation +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:serial}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:serial}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:serial}}) = Acoustic3D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:threads}}) = Acoustic3D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:threads}}) = Acoustic3D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 1}}, ::Type{Val{:threadpersrc}}) = Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 2}}, ::Type{Val{:threadpersrc}}) = Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimul{Float64, 3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:threadpersrc}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:threadpersrc}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial -# Backend selections for AcousticVDStaggeredCPMLWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimul{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads +# Backend selections for AcousticVDStaggeredCPMLWaveSimulation +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads -# Backend selections for ElasticIsoWaveSimul -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimul{Float64, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial +# Backend selections for ElasticIsoWaveSimulation +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{Float64, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 001c1fb..5387db4 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -2,7 +2,7 @@ module Elastic2D_Iso_CPML_Serial # To get those structs into this module -using SeismicWaves: ElasticIsoCPMLWaveSimul, ElasticIsoMaterialProperties +using SeismicWaves: ElasticIsoCPMLWaveSimulation, ElasticIsoMaterialProperties # Dummy data module module Data @@ -405,7 +405,7 @@ function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, return end -function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimul{T, N}, +function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, srccoeij_bk::Array{Int}, srccoeval_bk::Array{T}, reccoeij_bk::Array{Int}, @@ -417,7 +417,7 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimul{T, N}, Mzz_bk::Vector{T}, Mxz_bk::Vector{T}; save_trace::Bool=true) where {T, N} - # function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimul{T,N}, + # function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T,N}, # possrcs_bk::Array{Int,2}, # srctf_bk::Matrix{T}, # posrecs_bk::Array{Int,2}, diff --git a/src/models/elastic/ela_abstract_types.jl b/src/models/elastic/ela_abstract_types.jl index a047a68..b2b0348 100644 --- a/src/models/elastic/ela_abstract_types.jl +++ b/src/models/elastic/ela_abstract_types.jl @@ -1,7 +1,7 @@ -abstract type ElasticWaveSimul{T, N} <: WaveSimulation{T, N} end +abstract type ElasticWaveSimulation{T, N} <: WaveSimulation{T, N} end -abstract type ElasticIsoWaveSimul{T, N} <: ElasticWaveSimul{T, N} end +abstract type ElasticIsoWaveSimulation{T, N} <: ElasticWaveSimulation{T, N} end abstract type ElasticMaterialProperties{T, N} <: MaterialProperties{T, N} end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index d7b15c3..7313df5 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -1,9 +1,9 @@ -swforward_1shot!(model::ElasticWaveSimul, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) +swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) @views function swforward_1shot!( ::CPMLBoundaryCondition, - model::ElasticIsoCPMLWaveSimul{T, N}, + model::ElasticIsoCPMLWaveSimulation{T, N}, shot::Shot # possrcs::Matrix{<:Int}, # posrecs::Matrix{<:Int}, diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl index 936a32d..4b8a5f3 100644 --- a/src/models/elastic/ela_init_bc.jl +++ b/src/models/elastic/ela_init_bc.jl @@ -1,12 +1,12 @@ -init_bdc!(model::ElasticWaveSimul, srcs::Sources) = +init_bdc!(model::ElasticWaveSimulation, srcs::Sources) = init_bdc!(BoundaryConditionTrait(model), model, srcs) -init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimul, srcs::Sources) = nothing +init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimulation, srcs::Sources) = nothing @views function init_bdc!( ::CPMLBoundaryCondition, - model::ElasticIsoWaveSimul, + model::ElasticIsoWaveSimulation, srcs::Sources ) N = length(model.cpmlcoeffs) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index d8782ef..c3809af 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -1,8 +1,8 @@ ########################################################### -# Functions for all ElasticIsoWaveSimul subtypes +# Functions for all ElasticIsoWaveSimulation subtypes -@views function check_matprop(model::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} +@views function check_matprop(model::ElasticIsoWaveSimulation{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Checks vp = sqrt.((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" @@ -24,7 +24,7 @@ end function check_numerics( - model::ElasticIsoWaveSimul, + model::ElasticIsoWaveSimulation, shot::Shot; min_ppw::Int=10 ) @@ -41,7 +41,7 @@ function check_numerics( return end -@views function update_matprop!(model::ElasticIsoWaveSimul{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::ElasticIsoWaveSimulation{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Update material properties model.matprop.λ .= matprop.λ @@ -108,7 +108,7 @@ end ############################################################## -struct ElasticIsoCPMLWaveSimul{T, N} <: ElasticIsoWaveSimul{T, N} +struct ElasticIsoCPMLWaveSimulation{T, N} <: ElasticIsoWaveSimulation{T, N} # Physics domainextent::NTuple{N, T} # Numerics @@ -149,7 +149,7 @@ struct ElasticIsoCPMLWaveSimul{T, N} <: ElasticIsoWaveSimul{T, N} backend::Module parall::Symbol - function ElasticIsoCPMLWaveSimul( + function ElasticIsoCPMLWaveSimulation( gridsize::NTuple{N, Int}, gridspacing::NTuple{N, T}, nt::Int, @@ -179,7 +179,7 @@ struct ElasticIsoCPMLWaveSimul{T, N} <: ElasticIsoWaveSimul{T, N} domainextent = gridspacing .* (gridsize .- 1) # Select backend - backend = select_backend(ElasticIsoCPMLWaveSimul{T, N}, parall) + backend = select_backend(ElasticIsoCPMLWaveSimulation{T, N}, parall) V = backend.Data.Array{T, 1} # Initialize computational arrays @@ -297,9 +297,9 @@ end ########################################################### -# Specific functions for ElasticIsoCPMLWaveSimul +# Specific functions for ElasticIsoCPMLWaveSimulation -@views function reset!(model::ElasticIsoCPMLWaveSimul{T, N}) where {T, N} +@views function reset!(model::ElasticIsoCPMLWaveSimulation{T, N}) where {T, N} # Reset computational arrays for p in propertynames(model.velpartic) @@ -327,22 +327,22 @@ end end ########################################################### -# Traits for ElasticIsoCPMLWaveSimul +# Traits for ElasticIsoCPMLWaveSimulation -IsSnappableTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = Snappable() -BoundaryConditionTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = CPMLBoundaryCondition() -GridTrait(::Type{<:ElasticIsoCPMLWaveSimul}) = LocalGrid() +IsSnappableTrait(::Type{<:ElasticIsoCPMLWaveSimulation}) = Snappable() +BoundaryConditionTrait(::Type{<:ElasticIsoCPMLWaveSimulation}) = CPMLBoundaryCondition() +GridTrait(::Type{<:ElasticIsoCPMLWaveSimulation}) = LocalGrid() ########################################################### -struct ElasticIsoReflWaveSimul{T, N} <: ElasticIsoWaveSimul{T, N} end # TODO implementation +struct ElasticIsoReflWaveSimulation{T, N} <: ElasticIsoWaveSimulation{T, N} end # TODO implementation ########################################################### -# Traits for ElasticIsoReflWaveSimul +# Traits for ElasticIsoReflWaveSimulation -IsSnappableTrait(::Type{<:ElasticIsoReflWaveSimul}) = Snappable() -BoundaryConditionTrait(::Type{<:ElasticIsoReflWaveSimul}) = ReflectiveBoundaryCondition() -GridTrait(::Type{<:ElasticIsoReflWaveSimul}) = LocalGrid() +IsSnappableTrait(::Type{<:ElasticIsoReflWaveSimulation}) = Snappable() +BoundaryConditionTrait(::Type{<:ElasticIsoReflWaveSimulation}) = ReflectiveBoundaryCondition() +GridTrait(::Type{<:ElasticIsoReflWaveSimulation}) = LocalGrid() ########################################################### diff --git a/src/wrappers.jl b/src/wrappers.jl index cf637c4..bbdf2da 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -290,7 +290,7 @@ build_concrete_wavesim( matprop::VpAcousticCDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters{T}; kwargs... -) where {T, N} = AcousticCDCPMLWaveSimul( +) where {T, N} = AcousticCDCPMLWaveSimulation( params, matprop, cpmlparams; @@ -302,7 +302,7 @@ build_concrete_wavesim( matprop::VpRhoAcousticVDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters; kwargs... -) where {T, N} = AcousticVDStaggeredCPMLWaveSimul( +) where {T, N} = AcousticVDStaggeredCPMLWaveSimulation( params, matprop, cpmlparams; @@ -314,7 +314,7 @@ build_concrete_wavesim( matprop::ElasticIsoMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters; kwargs... -) where {T, N} = ElasticIsoCPMLWaveSimul( +) where {T, N} = ElasticIsoCPMLWaveSimulation( params.gridsize, params.gridspacing, params.ntimesteps, From c9b60c814d76d80da9df33f143561d88aa616a85 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 10:44:46 +0200 Subject: [PATCH 055/111] Reenable checks and remove redundant fields Also renamed some fields --- src/checks.jl | 34 +++---- src/grids/grids.jl | 16 ++-- src/models/acoustic/acou_forward.jl | 4 +- src/models/acoustic/acou_gradient.jl | 8 +- src/models/acoustic/acou_init_bc.jl | 8 +- src/models/acoustic/acou_models.jl | 92 ++++++++----------- .../backends/Acoustic1D_CD_CPML_Serial.jl | 8 +- .../backends/Acoustic2D_CD_CPML_Serial.jl | 8 +- .../backends/Acoustic3D_CD_CPML_Serial.jl | 8 +- .../backends/shared/acoustic1D_VD_xPU.jl | 8 +- .../backends/shared/acoustic1D_xPU.jl | 8 +- .../backends/shared/acoustic2D_VD_xPU.jl | 8 +- .../backends/shared/acoustic2D_xPU.jl | 8 +- .../backends/shared/acoustic3D_xPU.jl | 8 +- .../backends/Elastic2D_Iso_CPML_Serial.jl | 10 +- src/models/elastic/ela_forward.jl | 4 +- src/models/elastic/ela_init_bc.jl | 8 +- src/models/elastic/ela_models.jl | 12 +-- src/shot.jl | 2 +- 19 files changed, 124 insertions(+), 138 deletions(-) diff --git a/src/checks.jl b/src/checks.jl index dfb817b..3d816d2 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -13,20 +13,20 @@ function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialPro # Check that the subtypes of WaveSimulation, MaterialProperties and Shot are consistent if model isa AcousticCDCPMLWaveSimulation{T, N, <:AbstractArray{T, N}} && matprop isa VpAcousticCDMaterialProperties{T, N} && - tysource <: ScalarSources && - tyreceiver <: ScalarReceivers + tysource <: ScalarSources{T} && + tyreceiver <: ScalarReceivers{T} return elseif model isa AcousticVDStaggeredCPMLWaveSimulation{T, N} && matprop isa VpRhoAcousticVDMaterialProperties{T, N} && - tysource <: ScalarSources && - tyreceiver <: ScalarReceivers + tysource <: ScalarSources{T} && + tyreceiver <: ScalarReceivers{T} return elseif model isa ElasticIsoCPMLWaveSimulation{T, 2} && # <<<<<---------<<<< matprop isa ElasticIsoMaterialProperties{T, 2} && - tysource <: MomentTensorSources && - tyreceiver <: VectorReceivers + tysource <: MomentTensorSources{T, MomentTensor2D{T}} && + tyreceiver <: VectorReceivers{T, N} return end @@ -35,12 +35,12 @@ function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialPro end function check_shot(model::WaveSimulation, shot::Shot; kwargs...) - # @debug "Checking model/shot numerics" - # check_numerics(model, shot; kwargs...) - # @debug "Checking sources positions" - # check_positions(model, shot.srcs.positions) - # @debug "Checking receivers positions" - # check_positions(model, shot.recs.positions) + @debug "Checking model/shot numerics" + check_numerics(model, shot; kwargs...) + @debug "Checking sources positions" + check_positions(model, shot.srcs.positions) + @debug "Checking receivers positions" + check_positions(model, shot.recs.positions) return end @@ -51,13 +51,13 @@ function check_positions( model::WaveSimulation{T}, positions::Matrix{T} ) where {T} - ndimwavsim = length(model.gridspacing) + ndimwavsim = length(model.grid.spacing) @assert size(positions, 2) == ndimwavsim "Positions matrix do not match the dimension of the model!" Ndim = size(positions, 2) for s in axes(positions, 1) for c in 1:Ndim - @assert (0 <= positions[s, c] <= model.domainextent[c]) "Position $(positions[s,:]) is not inside the grid!" + @assert (0 <= positions[s, c] <= model.grid.extent[c]) "Position $(positions[s,:]) is not inside the grid!" end end return @@ -73,11 +73,11 @@ function check_positions( for s in axes(positions, 1) for c in 1:Ndim # Check that positions are outside of the CPML region - if !(c == Ndim && model.freetop) + if !(c == Ndim && model.cpmlparams.freeboundtop) @assert ( - model.gridspacing[c] * model.halo <= + model.grid.spacing[c] * model.cpmlparams.halo <= positions[s, c] <= - model.domainextent[c] - (model.gridspacing[c] * model.halo) + model.grid.extent[c] - (model.grid.spacing[c] * model.cpmlparams.halo) ) "Position $(positions[s,:]) is inside the CPML region!" end end diff --git a/src/grids/grids.jl b/src/grids/grids.jl index 6e28cec..2dd3192 100644 --- a/src/grids/grids.jl +++ b/src/grids/grids.jl @@ -1,18 +1,18 @@ struct UniformFiniteDifferenceGrid{N, T} <: AbstractGrid{N, T} - domainextent::NTuple{N, T} - ns::NTuple{N, Int} - gridspacing::NTuple{N, T} + extent::NTuple{N, T} + size::NTuple{N, Int} + spacing::NTuple{N, T} fields::Dict{String, AbstractField{T}} function UniformFiniteDifferenceGrid( - ns::NTuple{N, Int}, gridspacing::NTuple{N, T} + size::NTuple{N, Int}, spacing::NTuple{N, T} ) where {N, T} # Check numerics - @assert all(ns .> 0) "All numbers of grid points must be positive!" - @assert all(gridspacing .> 0) "All cell sizes must be positive!" + @assert all(size .> 0) "All numbers of grid points must be positive!" + @assert all(spacing .> 0) "All cell sizes must be positive!" # Compute domain extent - domainextent = gridspacing .* (ns .- 1) - new{N, T}(domainextent, ns, gridspacing, Dict()) + extent = spacing .* (size .- 1) + new{N, T}(extent, size, spacing, Dict()) end end diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index d4cf7cf..52bb5c6 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -10,7 +10,7 @@ swforward_1shot!(model::AcousticWaveSimulation, args...) = swforward_1shot!(Boun # source time function # scale with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(model.grid.gridspacing) .* (model.dt^2) + scal_srctf = shot.srcs.tf ./ prod(model.grid.spacing) .* (model.dt^2) # scale with velocity squared at each source position for s in axes(scal_srctf, 2) scal_srctf[:, s] .*= model.matprop.vp[possrcs[s, :]...] .^ 2 @@ -77,7 +77,7 @@ end # source time function # scale with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(model.grid.gridspacing) .* (model.dt) + scal_srctf = shot.srcs.tf ./ prod(model.grid.spacing) .* (model.dt) # scale with velocity squared times density at each source position (its like dividing by m0) for s in axes(scal_srctf, 2) scal_srctf[:, s] .*= model.matprop.vp[possrcs[s, :]...] .^ 2 .* model.matprop.rho[possrcs[s, :]...] diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index d6a35f2..2754f0a 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -173,16 +173,16 @@ end pcur_old = getsaved(checkpointer, "pcur", it - 1).value # Correlate for gradient computation backend.correlate_gradient_m0!(grid.fields["grad_m0"].value, grid.fields["adjpcur"].value, pcur_corr, pcur_old, model.dt) - backend.correlate_gradient_m1!(grid.fields["grad_m1_stag"].value, grid.fields["adjvcur"].value, pcur_corr, grid.gridspacing) + backend.correlate_gradient_m1!(grid.fields["grad_m1_stag"].value, grid.fields["adjvcur"].value, pcur_corr, grid.spacing) end # Allocate gradients - gradient_m0 = zeros(T, grid.ns...) - gradient_m1 = zeros(T, grid.ns...) + gradient_m0 = zeros(T, grid.size...) + gradient_m1 = zeros(T, grid.size...) # Get gradients copyto!(gradient_m0, grid.fields["grad_m0"].value) for i in eachindex(grid.fields["grad_m1_stag"].value) # Accumulate and interpolate staggered gradients - gradient_m1[CartesianIndices(Tuple(j == i ? (2:grid.ns[j]-1) : (1:grid.ns[j]) for j in 1:N))] .+= + gradient_m1[CartesianIndices(Tuple(j == i ? (2:grid.size[j]-1) : (1:grid.size[j]) for j in 1:N))] .+= interp(model.matprop.interp_method, Array(grid.fields["grad_m1_stag"].value[i]), i) end # Smooth gradients diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index 684af94..0c86f17 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -15,14 +15,14 @@ init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimulation, srcs::So model.cpmlcoeffs[n], get_maximum_func(model)(model.matprop.vp), model.dt, - model.halo, - model.rcoef, - model.grid.gridspacing[n] * model.halo, + model.cpmlparams.halo, + model.cpmlparams.rcoef, + model.grid.spacing[n] * model.cpmlparams.halo, srcs.domfreq ) end - if model.freetop && N >= 1 + if model.cpmlparams.freeboundtop && N >= 1 model.cpmlcoeffs[N].a_l .= 0.0 model.cpmlcoeffs[N].a_hl .= 0.0 model.cpmlcoeffs[N].b_l .= 1.0 diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index a9dfdcd..529ef99 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -4,7 +4,7 @@ @views function check_courant_condition(model::AcousticWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) - tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) + tmp = sqrt(sum(1 ./ model.grid.spacing .^ 2)) courant = vel_max * model.dt * tmp @info "Courant number: $(courant)" if courant > 1.0 @@ -19,7 +19,7 @@ function check_numerics( ) # Check points per wavelength vel_min = get_minimum_func(model)(model.matprop.vp) - h_max = maximum(model.grid.gridspacing) + h_max = maximum(model.grid.spacing) ppw = vel_min / shot.srcs.domfreq / h_max @info "Points per wavelength: $(ppw)" @assert ppw >= min_ppw "Not enough points per wavelengh!" @@ -32,7 +32,7 @@ end @views function check_matprop(model::AcousticCDWaveSimulation{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(matprop.vp) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.ns)" + @assert size(matprop.vp) == model.grid.size "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.size)" @assert all(matprop.vp .> 0) "Pressure velocity material property must be positive!" # Check courant condition check_courant_condition(model, matprop.vp) @@ -62,10 +62,6 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac dt::T # Computational grid grid::UniformFiniteDifferenceGrid{N, T} - # BDC and CPML parameters - halo::Int - rcoef::T - freetop::Bool # Gradient computation setup gradient::Bool smooth_radius::Int @@ -98,7 +94,7 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac nt = params.ntimesteps dt = params.dt gridspacing = params.gridspacing - ns = params.gridsize + gridsize = params.gridsize halo = cpmlparams.halo freetop = cpmlparams.freeboundtop rcoef = cpmlparams.rcoef @@ -108,7 +104,7 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac # Check BDC parameters @assert halo >= 0 "CPML halo size must be non-negative!" - ns_cpml = freetop ? ns[1:(end-1)] : ns + ns_cpml = freetop ? gridsize[1:(end-1)] : gridsize @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Select backend @@ -116,20 +112,20 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac A = backend.Data.Array{T, N} V = backend.Data.Array{T, 1} # Initialize computational grid - grid = UniformFiniteDifferenceGrid(ns, gridspacing) + grid = UniformFiniteDifferenceGrid(gridsize, gridspacing) # Initialize CPML coefficients cpmlcoeffs = tuple([CPMLCoefficients{T, V}(halo, backend, true) for _ in 1:N]...) # Populate computational grid - addfield!(grid, "fact" => ScalarVariableField(backend.zeros(T, ns...))) - addfield!(grid, "pold" => ScalarVariableField(backend.zeros(T, ns...))) - addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(T, ns...))) - addfield!(grid, "pnew" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "fact" => ScalarVariableField(backend.zeros(T, gridsize...))) + addfield!(grid, "pold" => ScalarVariableField(backend.zeros(T, gridsize...))) + addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(T, gridsize...))) + addfield!(grid, "pnew" => ScalarVariableField(backend.zeros(T, gridsize...))) if gradient - addfield!(grid, "grad_vp" => ScalarVariableField(backend.zeros(T, ns...))) - addfield!(grid, "adjold" => ScalarVariableField(backend.zeros(T, ns...))) - addfield!(grid, "adjcur" => ScalarVariableField(backend.zeros(T, ns...))) - addfield!(grid, "adjnew" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "grad_vp" => ScalarVariableField(backend.zeros(T, gridsize...))) + addfield!(grid, "adjold" => ScalarVariableField(backend.zeros(T, gridsize...))) + addfield!(grid, "adjcur" => ScalarVariableField(backend.zeros(T, gridsize...))) + addfield!(grid, "adjnew" => ScalarVariableField(backend.zeros(T, gridsize...))) end # CPML coefficients addfield!( @@ -148,26 +144,26 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac addfield!( grid, "ψ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) addfield!( grid, "ξ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) if gradient addfield!( grid, "ψ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) addfield!( grid, "ξ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) end @@ -187,7 +183,7 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) # Initialize snapshots array - snapshots = (snapevery !== nothing ? backend.zeros(T, ns..., div(nt, snapevery)) : nothing) + snapshots = (snapevery !== nothing ? backend.zeros(T, gridsize..., div(nt, snapevery)) : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -201,9 +197,6 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac nt, dt, grid, - halo, - rcoef, - freetop, gradient, smooth_radius, snapevery, @@ -226,7 +219,7 @@ end # find nearest grid point for each source idx_positions = zeros(Int, size(positions)) # sources positions (in grid points) for s in 1:nsrcs - tmp = [positions[s, i] / model.grid.gridspacing[i] + 1 for i in 1:ncoos] + tmp = [positions[s, i] / model.grid.spacing[i] + 1 for i in 1:ncoos] idx_positions[s, :] .= round.(Int, tmp, RoundNearestTiesUp) end return idx_positions @@ -253,7 +246,7 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimulation}) = LocalGrid() @views function check_courant_condition(model::AcousticVDStaggeredWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) - tmp = sqrt(sum(1 ./ model.grid.gridspacing .^ 2)) + tmp = sqrt(sum(1 ./ model.grid.spacing .^ 2)) courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil @info "Courant number: $(courant)" if courant > 1 @@ -268,7 +261,7 @@ function check_numerics( ) # Check points per wavelength vel_min = get_minimum_func(model)(model.matprop.vp) - h_max = maximum(model.gridspacing) + h_max = maximum(model.grid.spacing) ppw = vel_min / shot.srcs.domfreq / h_max @info "Points per wavelength: $(ppw)" @assert ppw >= min_ppw "Not enough points per wavelengh!" @@ -277,7 +270,7 @@ end @views function check_matprop(model::AcousticVDStaggeredWaveSimulation{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(matprop.vp) == size(matprop.rho) == model.grid.ns "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.ns)" + @assert size(matprop.vp) == size(matprop.rho) == model.grid.size "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.grid.size)" @assert all(matprop.vp .> 0) "Pressure velocity material property must be positive!" @assert all(matprop.rho .> 0) "Density material property must be positive!" # Check courant condition @@ -321,10 +314,6 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < dt::T # Computational grid grid::UniformFiniteDifferenceGrid{N, T} - # BDC and CPML parameters - halo::Int - rcoef::T - freetop::Bool # Gradient computation setup gradient::Bool smooth_radius::Int @@ -357,7 +346,7 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < nt = params.ntimesteps dt = params.dt gridspacing = params.gridspacing - ns = params.gridsize + gridsize = params.gridsize halo = cpmlparams.halo freetop = cpmlparams.freeboundtop rcoef = cpmlparams.rcoef @@ -367,7 +356,7 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < # Check BDC parameters @assert halo >= 0 "CPML halo size must be non-negative!" - ns_cpml = freetop ? ns[1:(end-1)] : ns + ns_cpml = freetop ? gridsize[1:(end-1)] : gridsize @assert all(n -> n >= 2halo + 3, ns_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Select backend @@ -375,27 +364,27 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < A = backend.Data.Array{T, N} V = backend.Data.Array{T, 1} # Initialize computational grid - grid = UniformFiniteDifferenceGrid(ns, gridspacing) + grid = UniformFiniteDifferenceGrid(gridsize, gridspacing) # Initialize CPML coefficients cpmlcoeffs = tuple([CPMLCoefficients{T, V}(halo, backend, true) for _ in 1:N]...) # Populate computational grid - addfield!(grid, "fact_m0" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "fact_m0" => ScalarVariableField(backend.zeros(T, gridsize...))) addfield!(grid, "fact_m1_stag" => MultiVariableField( - [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + [backend.zeros(T, (gridsize .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] )) - addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "pcur" => ScalarVariableField(backend.zeros(T, gridsize...))) addfield!(grid, "vcur" => MultiVariableField( - [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + [backend.zeros(T, (gridsize .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] )) if gradient - addfield!(grid, "grad_m0" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "grad_m0" => ScalarVariableField(backend.zeros(T, gridsize...))) addfield!(grid, "grad_m1_stag" => MultiVariableField( - [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + [backend.zeros(T, (gridsize .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] )) - addfield!(grid, "adjpcur" => ScalarVariableField(backend.zeros(T, ns...))) + addfield!(grid, "adjpcur" => ScalarVariableField(backend.zeros(T, gridsize...))) addfield!(grid, "adjvcur" => MultiVariableField( - [backend.zeros(T, (ns .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] + [backend.zeros(T, (gridsize .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] )) end # CPML coefficients @@ -415,26 +404,26 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < addfield!( grid, "ψ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) addfield!( grid, "ξ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) if gradient addfield!( grid, "ψ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) addfield!( grid, "ξ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : ns[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) ) ) end @@ -454,7 +443,7 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) # Initialize snapshots array - snapshots = (snapevery !== nothing ? backend.zeros(T, ns..., div(nt, snapevery)) : nothing) + snapshots = (snapevery !== nothing ? backend.zeros(T, gridsize..., div(nt, snapevery)) : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -468,9 +457,6 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < nt, dt, grid, - halo, - rcoef, - freetop, gradient, smooth_radius, snapevery, diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index 5397987..4581bdf 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -99,8 +99,8 @@ end save_trace=true ) # Extract info from grid - nx = grid.ns[1] - dx = grid.gridspacing[1] + nx = grid.size[1] + dx = grid.spacing[1] pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value ψ_l, ψ_r = grid.fields["ψ"].value @@ -136,8 +136,8 @@ end @views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid - nx = grid.ns[1] - dx = grid.gridspacing[1] + nx = grid.size[1] + dx = grid.spacing[1] pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value ψ_l, ψ_r = grid.fields["ψ_adj"].value diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl index 1132b9e..21909ef 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl @@ -115,8 +115,8 @@ function forward_onestep_CPML!( save_trace=true ) # Extract info from grid - nx, ny = grid.ns - dx, dy = grid.gridspacing + nx, ny = grid.size + dx, dy = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value @@ -158,8 +158,8 @@ end function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid - nx, ny = grid.ns - dx, dy = grid.gridspacing + nx, ny = grid.size + dx, dy = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl index 416988a..4e12c9a 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl @@ -159,8 +159,8 @@ function forward_onestep_CPML!( save_trace=true ) # Extract info from grid - nx, ny, nz = grid.ns - dx, dy, dz = grid.gridspacing + nx, ny, nz = grid.size + dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ"].value @@ -211,8 +211,8 @@ end function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid - nx, ny, nz = grid.ns - dx, dy, dz = grid.gridspacing + nx, ny, nz = grid.size + dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ_adj"].value diff --git a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl index ac90e2e..1c0b35f 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl @@ -72,8 +72,8 @@ end save_trace=true ) # Extract info from grid - nx = grid.ns[1] - dx = grid.gridspacing[1] + nx = grid.size[1] + dx = grid.spacing[1] pcur, vx_cur = grid.fields["pcur"].value, grid.fields["vcur"].value[1] fact_m0 = grid.fields["fact_m0"].value fact_m1_x = grid.fields["fact_m1_stag"].value[1] @@ -99,8 +99,8 @@ end grid, possrcs, srctf, it ) # Extract info from grid - nx = grid.ns[1] - dx = grid.gridspacing[1] + nx = grid.size[1] + dx = grid.spacing[1] pcur, vx_cur = grid.fields["adjpcur"].value, grid.fields["adjvcur"].value[1] fact_m0 = grid.fields["fact_m0"].value fact_m1_x = grid.fields["fact_m1_stag"].value[1] diff --git a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl index 4f9b5a2..f729b0e 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl @@ -99,8 +99,8 @@ end save_trace=true ) # Extract info from grid - nx = grid.ns[1] - dx = grid.gridspacing[1] + nx = grid.size[1] + dx = grid.spacing[1] pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value ψ_l, ψ_r = grid.fields["ψ"].value @@ -135,8 +135,8 @@ end @views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid - nx = grid.ns[1] - dx = grid.gridspacing[1] + nx = grid.size[1] + dx = grid.spacing[1] pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value ψ_l, ψ_r = grid.fields["ψ_adj"].value diff --git a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl index 057237c..eec5186 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl @@ -108,8 +108,8 @@ end save_trace=true ) # Extract info from grid - nx, ny = grid.ns - dx, dy = grid.gridspacing + nx, ny = grid.size + dx, dy = grid.spacing pcur = grid.fields["pcur"].value vx_cur, vy_cur = grid.fields["vcur"].value fact_m0 = grid.fields["fact_m0"].value @@ -143,8 +143,8 @@ end grid, possrcs, srctf, it ) # Extract info from grid - nx, ny = grid.ns - dx, dy = grid.gridspacing + nx, ny = grid.size + dx, dy = grid.spacing pcur = grid.fields["adjpcur"].value vx_cur, vy_cur = grid.fields["adjvcur"].value fact_m0 = grid.fields["fact_m0"].value diff --git a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl index 22682fb..40e2092 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl @@ -109,8 +109,8 @@ end save_trace=true ) # Extract info from grid - nx, ny = grid.ns - dx, dy = grid.gridspacing + nx, ny = grid.size + dx, dy = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value @@ -158,8 +158,8 @@ end @views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid - nx, ny = grid.ns - dx, dy = grid.gridspacing + nx, ny = grid.size + dx, dy = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value diff --git a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl index 164e974..0796aa2 100644 --- a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl @@ -146,8 +146,8 @@ end save_trace=true ) # Extract info from grid - nx, ny, nz = grid.ns - dx, dy, dz = grid.gridspacing + nx, ny, nz = grid.size + dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ"].value @@ -215,8 +215,8 @@ end @views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) # Extract info from grid - nx, ny, nz = grid.ns - dx, dy, dz = grid.gridspacing + nx, ny, nz = grid.size + dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ_adj"].value diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 5387db4..2a19dec 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -429,14 +429,14 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, # save_trace::Bool=true) where {N} @assert N == 2 - freetop = model.freetop + freetop = model.cpmlparams.freeboundtop cpmlcoeffs = model.cpmlcoeffs matprop = model.matprop - dx = model.gridspacing[1] - dz = model.gridspacing[2] + dx = model.grid.spacing[1] + dz = model.grid.spacing[2] dt = model.dt - nx, nz = model.gridsize[1:2] - halo = model.halo + nx, nz = model.grid.size[1:2] + halo = model.cpmlparams.halo vx = model.velpartic.vx vz = model.velpartic.vz diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 7313df5..ca0a19c 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -18,11 +18,11 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound if N == 2 # interpolation coefficients for sources - srccoeij, srccoeval = spreadsrcrecinterp2D(model.gridspacing, model.gridsize, + srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, shot.srcs.positions; nptssinc=4, xstart=0.0, zstart=0.0) # interpolation coefficients for receivers - reccoeij, reccoeval = spreadsrcrecinterp2D(model.gridspacing, model.gridsize, + reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, shot.recs.positions; nptssinc=4, xstart=0.0, zstart=0.0) elseif N == 3 diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl index 4b8a5f3..7d53d0f 100644 --- a/src/models/elastic/ela_init_bc.jl +++ b/src/models/elastic/ela_init_bc.jl @@ -16,14 +16,14 @@ init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimulation, srcs::Sou model.cpmlcoeffs[n], get_maximum_func(model)(sqrt.((model.matprop.λ + 2.0 * model.matprop.μ) ./ model.matprop.ρ)), model.dt, - model.halo, - model.rcoef, - model.gridspacing[n] * model.halo, ## <<-- Check: dx*(n-1)? + model.cpmlparams.halo, + model.cpmlparams.rcoef, + model.grid.spacing[n] * model.cpmlparams.halo, ## <<-- Check: dx*(n-1)? srcs.domfreq ) end - if model.freetop && N >= 1 + if model.cpmlparams.freeboundtop && N >= 1 lastcoe = model.cpmlcoeffs[N] lastcoe.a[1:length(lastcoe.a)÷2] .= 0.0 diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index c3809af..5c15d7c 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -6,14 +6,14 @@ # Checks vp = sqrt.((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(vp) == model.gridsize "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.gridsize)" + @assert size(vp) == model.grid.size "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.size)" @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" @assert all(matprop.ρ .> 0) "Density must be positive!" # Check courant condition vel_max = get_maximum_func(model)(vp) - tmp = sqrt.(sum(1 ./ model.gridspacing .^ 2)) + tmp = sqrt.(sum(1 ./ model.grid.spacing .^ 2)) courant = vel_max * model.dt * tmp @info "Courant number: $(courant)" if courant > 1.0 @@ -31,7 +31,7 @@ function check_numerics( # Check points per wavelengh # min Vs vel_min = get_minimum_func(model)(sqrt.(model.matprop.μ ./ model.matprop.ρ)) - h_max = maximum(model.gridspacing) + h_max = maximum(model.grid.spacing) fmax = shot.srcs.domfreq * 2.0 ppw = vel_min / (fmax * h_max) @info "Points per wavelength: $(ppw)" @@ -110,7 +110,7 @@ end struct ElasticIsoCPMLWaveSimulation{T, N} <: ElasticIsoWaveSimulation{T, N} # Physics - domainextent::NTuple{N, T} + extent::NTuple{N, T} # Numerics gridsize::NTuple{N, Int} gridspacing::NTuple{N, T} @@ -176,7 +176,7 @@ struct ElasticIsoCPMLWaveSimulation{T, N} <: ElasticIsoWaveSimulation{T, N} @assert all(n -> n >= 2halo + 3, gridsize_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Compute model sizes - domainextent = gridspacing .* (gridsize .- 1) + extent = gridspacing .* (gridsize .- 1) # Select backend backend = select_backend(ElasticIsoCPMLWaveSimulation{T, N}, parall) @@ -264,7 +264,7 @@ struct ElasticIsoCPMLWaveSimulation{T, N} <: ElasticIsoWaveSimulation{T, N} end return new{T, N}( - domainextent, + extent, gridsize, gridspacing, nt, diff --git a/src/shot.jl b/src/shot.jl index 07f3e65..89a8057 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -29,7 +29,7 @@ end # find nearest grid point for each source idx_positions = zeros(Int, size(positions)) # sources positions (in grid points) for s in 1:nsrcs - tmp = [positions[s, i] / model.grid.gridspacing[i] + 1 for i in 1:ncoos] + tmp = [positions[s, i] / model.grid.spacing[i] + 1 for i in 1:ncoos] idx_positions[s, :] .= round.(Int, tmp, RoundNearestTiesUp) end return idx_positions From e852bdeed6feafd652b353688a5427c4f94e0ea8 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 11:37:40 +0200 Subject: [PATCH 056/111] Refactor Shot and its subtypes for better typing Also move things around --- examples/forward_example.jl | 4 +- examples/geometries.jl | 4 +- .../constant_density/gradient_check_fd.jl | 4 +- .../variable_density/gradient_check_fd.jl | 4 +- examples/simple_example_acoustic.jl | 8 ++-- examples/simple_example_elastic.jl | 8 ++-- examples/simple_example_wavesim.jl | 8 ++-- src/HMCseiswaves.jl | 4 +- src/SeismicWaves.jl | 15 +++--- src/abstract_types.jl | 4 +- src/checks.jl | 4 +- src/models/acoustic/acou_forward.jl | 8 ++-- src/models/acoustic/acou_gradient.jl | 4 +- src/models/acoustic/acou_models.jl | 12 ++--- src/models/elastic/ela_forward.jl | 6 +-- src/models/elastic/ela_models.jl | 6 +-- src/shot.jl | 30 +++++++++--- src/solve.jl | 10 ++-- src/sources.jl | 12 ++--- src/{grids => utils}/abstract_types.jl | 0 src/{grids => utils}/checkpointers.jl | 0 src/{grids => utils}/fields.jl | 0 src/{grids => utils}/grids.jl | 0 src/{ => utils}/utils.jl | 0 src/wrappers.jl | 48 +++++++++---------- test/test_forward_constant_density.jl | 16 +++---- test/utils/setup_models.jl | 10 ++-- 27 files changed, 123 insertions(+), 106 deletions(-) rename src/{grids => utils}/abstract_types.jl (100%) rename src/{grids => utils}/checkpointers.jl (100%) rename src/{grids => utils}/fields.jl (100%) rename src/{grids => utils}/grids.jl (100%) rename src/{ => utils}/utils.jl (100%) diff --git a/examples/forward_example.jl b/examples/forward_example.jl index 5409088..30dfbbc 100644 --- a/examples/forward_example.jl +++ b/examples/forward_example.jl @@ -21,7 +21,7 @@ function forward_example() ##======================================== # shots definition nshots = 6 - shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() + shots = Vector{ScalarShot{Float64}}() #Pair{Sources, Receivers}}() # sources x-position (in grid points) (different for every shot) ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) for i in 1:nshots @@ -47,7 +47,7 @@ function forward_example() recs = ScalarReceivers(posrecs, nt) # add pair as shot - push!(shots, Shot(; srcs=srcs, recs=recs)) # srcs => recs) + push!(shots, ScalarShot(; srcs=srcs, recs=recs)) # srcs => recs) end ##============================================ ## Input parameters for acoustic simulation diff --git a/examples/geometries.jl b/examples/geometries.jl index f4bdefe..4c2119c 100644 --- a/examples/geometries.jl +++ b/examples/geometries.jl @@ -4,7 +4,7 @@ include("plotting_utils.jl") function linear_2D_geometry(nshots, model, f0, nt, srctf, dd, lx, ly, dx, dy, halo; plot_geometry=false, save_file=nothing) # shots definition - shots = Vector{Shot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() + shots = Vector{ScalarShot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() # straight line positions xs = (lx / 2) .- dd .* ((nshots + 1) / 2 .- collect(1:nshots)) ysrc = (halo + 10) * dy @@ -28,7 +28,7 @@ function linear_2D_geometry(nshots, model, f0, nt, srctf, dd, lx, ly, dx, dy, ha ) # add pair as shot - push!(shots, Shot(; srcs=srcs, recs=recs)) # srcs => recs) + push!(shots, ScalarShot(; srcs=srcs, recs=recs)) # srcs => recs) end if plot_geometry diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index 16d0a89..c499a90 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -74,7 +74,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss; compute end # new receivers with observed seismograms - shots_obs = Vector{Shot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() + shots_obs = Vector{ScalarShot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() for i in eachindex(shots) # receivers definition recs = ScalarReceivers( @@ -84,7 +84,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss; compute invcov=Diagonal(ones(nt)) ) # add pair as shot - push!(shots_obs, Shot(; srcs=shots[i].srcs, recs=recs)) # srcs => recs) + push!(shots_obs, ScalarShot(; srcs=shots[i].srcs, recs=recs)) # srcs => recs) end println("Computing gradients") diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index f4374c9..3eeba1c 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -89,7 +89,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) end # new receivers with observed seismograms - shots_obs = Vector{Shot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() + shots_obs = Vector{ScalarShot{Float64}}() #Pair{ScalarSources, ScalarReceivers}}() for i in eachindex(shots) # receivers definition recs = ScalarReceivers( @@ -99,7 +99,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) invcov=Diagonal(ones(nt)) ) # add pair as shot - push!(shots_obs, Shot(; srcs=shots[i].srcs, recs=recs)) # srcs => recs) + push!(shots_obs, ScalarShot(; srcs=shots[i].srcs, recs=recs)) # srcs => recs) end println("Computing gradients") diff --git a/examples/simple_example_acoustic.jl b/examples/simple_example_acoustic.jl index 5c0318e..f713425 100644 --- a/examples/simple_example_acoustic.jl +++ b/examples/simple_example_acoustic.jl @@ -44,7 +44,7 @@ function exacouprob(parall=:serial) ##======================================== # shots definition nshots = 6 - shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() + shots = Vector{ScalarShot{Float64}}() #Pair{Sources, Receivers}}() # sources x-position (in grid points) (different for every shot) ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) for i in 1:nshots @@ -77,7 +77,7 @@ function exacouprob(parall=:serial) #@show recs.positions # add pair as shot - push!(shots, Shot(; srcs=srcs, recs=recs)) # srcs => recs) + push!(shots, ScalarShot(; srcs=srcs, recs=recs)) # srcs => recs) end ##============================================ @@ -102,13 +102,13 @@ function exacouprob(parall=:serial) ##=============================================== ## compute the gradient - shots_grad = Vector{Shot{Float64}}() + shots_grad = Vector{ScalarShot{Float64}}() for i in 1:nshots seis = shots[i].recs.seismograms nt = size(seis, 1) recs_grad = ScalarReceivers(shots[i].recs.positions, nt; observed=seis, invcov=Diagonal(ones(nt))) - push!(shots_grad, Shot(; srcs=shots[i].srcs, recs=recs_grad)) + push!(shots_grad, ScalarShot(; srcs=shots[i].srcs, recs=recs_grad)) end newvelmod = matprop.vp .- 0.2 diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index 8e54a44..37db57c 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -52,7 +52,7 @@ function exelaprob() ##======================================== # shots definition nshots = 1 - shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() + shots = Vector{ScalarShot{Float64}}() #Pair{Sources, Receivers}}() for i in 1:nshots # sources definition @@ -104,7 +104,7 @@ function exelaprob() #@show recs.positions # add pair as shot - push!(shots, Shot(; srcs=srcs, recs=recs)) # srcs => recs) + push!(shots, MomentTensorShot(; srcs=srcs, recs=recs)) # srcs => recs) end @show shots[1].srcs.positions @@ -133,13 +133,13 @@ function exelaprob() # ##=============================================== # ## compute the gradient - # shots_grad = Vector{Shot{Float64}}() + # shots_grad = Vector{ScalarShot{Float64}}() # for i in 1:nshots # seis = shots[i].recs.seismograms # nt = size(seis,1) # recs_grad = ScalarReceivers(shots[i].recs.positions, nt; observed=seis, # invcov=Diagonal(ones(nt))) - # push!(shots_grad, Shot(; srcs=shots[i].srcs, recs=recs_grad)) + # push!(shots_grad, MomentTensorShot(; srcs=shots[i].srcs, recs=recs_grad)) # end # newvelmod = matprop.vp .- 0.2 diff --git a/examples/simple_example_wavesim.jl b/examples/simple_example_wavesim.jl index 9c7c8c5..b1da963 100644 --- a/examples/simple_example_wavesim.jl +++ b/examples/simple_example_wavesim.jl @@ -47,7 +47,7 @@ function exacouprob_wavsim(parall=:serial) # shots definition nshots = 6 @show nshots - shots = Vector{Shot{Float64}}() #Pair{Sources, Receivers}}() + shots = Vector{ScalarShot{Float64}}() #Pair{Sources, Receivers}}() # sources x-position (in grid points) (different for every shot) ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) for i in 1:nshots @@ -80,7 +80,7 @@ function exacouprob_wavsim(parall=:serial) #@show recs.positions # add pair as shot - push!(shots, Shot(; srcs=srcs, recs=recs)) # srcs => recs) + push!(shots, ScalarShot(; srcs=srcs, recs=recs)) # srcs => recs) end ##============================================ @@ -126,13 +126,13 @@ function exacouprob_wavsim(parall=:serial) ##=============================================== ## compute the gradient - shots_grad = Vector{Shot{Float64}}() + shots_grad = Vector{ScalarShot{Float64}}() for i in 1:nshots seis = shots[i].recs.seismograms nt = size(seis, 1) recs_grad = ScalarReceivers(shots[i].recs.positions, nt; observed=seis, invcov=Diagonal(ones(nt))) - push!(shots_grad, Shot(; srcs=shots[i].srcs, recs=recs_grad)) + push!(shots_grad, ScalarShot(; srcs=shots[i].srcs, recs=recs_grad)) end newvelmod = matprop.vp .- 0.2 diff --git a/src/HMCseiswaves.jl b/src/HMCseiswaves.jl index 243321c..6d67d86 100644 --- a/src/HMCseiswaves.jl +++ b/src/HMCseiswaves.jl @@ -26,12 +26,12 @@ export AcouWavCDProb struct AcouWavCDProb #wavesim::WaveSimulation inpars::InputParametersAcoustic - shots::Vector{Shot{Float64}} #invCovds::Vector{<:AbstractMatrix{Float64}} + shots::Vector{ScalarShot{Float64}} #invCovds::Vector{<:AbstractMatrix{Float64}} parall::Symbol #firsttime::Base.RefValue{Bool} function AcouWavCDProb(inpars::InputParametersAcoustic, - shots::Vector{Shot{Float64}}, + shots::Vector{ScalarShot{Float64}}, parall::Symbol) # nt = inpars.ntimesteps diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index f33e942..0026794 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -21,7 +21,7 @@ export CPMLBoundaryConditionParameters, ReflectiveBoundaryConditionParameters export VpAcousticCDMaterialProperties, VpRhoAcousticVDMaterialProperties export ElasticIsoMaterialProperties # export sources, receivers and shots -export Shot +export ScalarShot, MomentTensorShot export ScalarSources, MomentTensorSources export MomentTensor2D, MomentTensor3D export ScalarReceivers, VectorReceivers @@ -46,10 +46,12 @@ include("srcrec_interpolation.jl") include("models/cpmlcoeffs.jl") -include("grids/abstract_types.jl") -include("grids/fields.jl") -include("grids/grids.jl") -include("grids/checkpointers.jl") +# Utils +include("utils/utils.jl") +include("utils/abstract_types.jl") +include("utils/fields.jl") +include("utils/grids.jl") +include("utils/checkpointers.jl") # Acoustic include("models/acoustic/acou_abstract_types.jl") @@ -95,9 +97,6 @@ include("models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl") # Elastic parallel backends -# Utils -include("utils.jl") - ## HMC stuff include("HMCseiswaves.jl") using .HMCseiswaves diff --git a/src/abstract_types.jl b/src/abstract_types.jl index b43106b..b9257d1 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -12,11 +12,13 @@ abstract type InputBoundaryConditionParameters{T} end abstract type MaterialProperties{T, N} end +abstract type Shot{T} end + abstract type Sources{T} end abstract type Receivers{T} end -abstract type MomentTensor{T} end +abstract type MomentTensor{T, N} end abstract type InterpolationMethod end diff --git a/src/checks.jl b/src/checks.jl index 3d816d2..fbaa3d5 100644 --- a/src/checks.jl +++ b/src/checks.jl @@ -1,5 +1,5 @@ -function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}) where {T, N} +function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}) where {T, N} tysource = typeof(shots[1].srcs) tyreceiver = typeof(shots[1].recs) @@ -34,7 +34,7 @@ function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialPro \n $(typeof(model)), \n $(typeof(matprop)), \n $(typeof(shots[1].srcs)), $(typeof(shots[1].recs))") end -function check_shot(model::WaveSimulation, shot::Shot; kwargs...) +function check_shot(model::WaveSimulation{T}, shot::Shot{T}; kwargs...) where {T} @debug "Checking model/shot numerics" check_numerics(model, shot; kwargs...) @debug "Checking sources positions" diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 52bb5c6..e6be971 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -3,7 +3,7 @@ swforward_1shot!(model::AcousticWaveSimulation, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) # Scaling for AcousticCDWaveSimulation -@views function possrcrec_scaletf(model::AcousticWaveSimulation, shot::Shot) +@views function possrcrec_scaletf(model::AcousticWaveSimulation{T}, shot::ScalarShot{T}) where {T} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(model, shot.srcs.positions) posrecs = find_nearest_grid_points(model, shot.recs.positions) @@ -22,7 +22,7 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, model::AcousticCDCPMLWaveSimulation{T, N}, - shot::Shot + shot::ScalarShot{T} ) where {T, N} # Scale source time function, etc. @@ -70,7 +70,7 @@ end ##################################################### # Scaling for AcousticVDStaggeredCPMLWaveSimulation -@views function possrcrec_scaletf(model::AcousticVDStaggeredCPMLWaveSimulation, shot::Shot) +@views function possrcrec_scaletf(model::AcousticVDStaggeredCPMLWaveSimulation{T}, shot::ScalarShot{T}) where {T} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(model, shot.srcs.positions) posrecs = find_nearest_grid_points(model, shot.recs.positions) @@ -89,7 +89,7 @@ end @views function swforward_1shot!( ::CPMLBoundaryCondition, model::AcousticVDStaggeredCPMLWaveSimulation{T, N}, - shot::Shot + shot::ScalarShot{T} ) where {T, N} # scale source time function, etc. diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 2754f0a..9955eb7 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -4,7 +4,7 @@ swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = @views function swgradient_1shot!( ::CPMLBoundaryCondition, model::AcousticCDWaveSimulation{T, N}, - shot::Shot, + shot::ScalarShot{T}, misfit )::Dict{String, Array{T, N}} where {T, N} @@ -97,7 +97,7 @@ end @views function swgradient_1shot!( ::CPMLBoundaryCondition, model::AcousticVDStaggeredCPMLWaveSimulation{T, N}, - shot::Shot, + shot::ScalarShot{T}, misfit )::Dict{String, Array{T, N}} where {T, N} diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 529ef99..20cf9bc 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -13,10 +13,10 @@ end function check_numerics( - model::AcousticWaveSimulation, - shot::Shot; + model::AcousticWaveSimulation{T}, + shot::ScalarShot{T}; min_ppw::Int=10 -) +) where {T} # Check points per wavelength vel_min = get_minimum_func(model)(model.matprop.vp) h_max = maximum(model.grid.spacing) @@ -255,10 +255,10 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimulation}) = LocalGrid() end function check_numerics( - model::AcousticVDStaggeredWaveSimulation, - shot::Shot; + model::AcousticVDStaggeredWaveSimulation{T}, + shot::ScalarShot{T}; min_ppw::Int=10 -) +) where {T} # Check points per wavelength vel_min = get_minimum_func(model)(model.matprop.vp) h_max = maximum(model.grid.spacing) diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index ca0a19c..56ddf87 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -3,13 +3,13 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound @views function swforward_1shot!( ::CPMLBoundaryCondition, - model::ElasticIsoCPMLWaveSimulation{T, N}, - shot::Shot + model::ElasticIsoCPMLWaveSimulation{T, 2}, + shot::MomentTensorShot{T, 2, MomentTensor2D{T}} # possrcs::Matrix{<:Int}, # posrecs::Matrix{<:Int}, # srctf, # recs -) where {T, N} +) where {T} # scale source time function, etc. # find nearest grid points indexes for both sources and receivers diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 5c15d7c..c6d5a8e 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -24,10 +24,10 @@ end function check_numerics( - model::ElasticIsoWaveSimulation, - shot::Shot; + model::ElasticIsoWaveSimulation{T}, + shot::MomentTensorShot{T}; min_ppw::Int=10 -) +) where {T} # Check points per wavelengh # min Vs vel_min = get_minimum_func(model)(sqrt.(model.matprop.μ ./ model.matprop.ρ)) diff --git a/src/shot.jl b/src/shot.jl index 89a8057..379028a 100644 --- a/src/shot.jl +++ b/src/shot.jl @@ -2,20 +2,36 @@ """ $(TYPEDEF) -Type representing a source-receiver pair, i.e., a \"shot\". +Type representing a shot with scalar sources and receivers. $(TYPEDFIELDS) """ -Base.@kwdef struct Shot{T} - "Structure containing the appropriate Sources for a given simulation." - srcs::Sources{T} - "Structure containing the appropriate Receivers for a given simulation." - recs::Receivers{T} +Base.@kwdef struct ScalarShot{T} <: Shot{T} + "Structure containing the ScalarSources for a given simulation." + srcs::ScalarSources{T} + "Structure containing the ScalarReceivers for a given simulation." + recs::ScalarReceivers{T} end +""" +$(TYPEDEF) + +Type representing a shot with moment tensor sources and multi-component receivers. + +$(TYPEDFIELDS) +""" +Base.@kwdef struct MomentTensorShot{T, N, M <: MomentTensor{T, N}} <: Shot{T} + "Structure containing the MomentTensorSources for a given simulation." + srcs::MomentTensorSources{T, N, M} + "Structure containing the VectorReceivers for a given simulation." + recs::VectorReceivers{T, N} +end + + + ################################################## -function init_shot!(model::WaveSimulation, shot::Shot; kwargs...) +function init_shot!(model::WaveSimulation{T}, shot::Shot{T}; kwargs...) where {T} # Check shot configuration check_shot(model, shot; kwargs...) # Initialize boundary conditions based on current shot diff --git a/src/solve.jl b/src/solve.jl index f1c7a7e..505768b 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -13,7 +13,7 @@ end @views function run_swforward!( model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; )::Union{Vector{Array{T}}, Nothing} where {T, N} # Check wavesim consistency @@ -58,7 +58,7 @@ end @views function run_swforward!( model::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; )::Union{Vector{Array{T}}, Nothing} where {T, N} nwsim = length(model) nthr = Threads.nthreads() @@ -117,7 +117,7 @@ end @views function run_swmisfit!( model::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; misfit::AbstractMisfit=L2Misfit(nothing) )::T where {T, N} @@ -147,7 +147,7 @@ end @views function run_swgradient!( model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) )::Union{Dict{String, Array{T, N}}, @@ -191,7 +191,7 @@ end @views function run_swgradient!( model::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; compute_misfit::Bool=false, misfit::AbstractMisfit=L2Misfit(nothing) )::Union{Dict{String, Array{T, N}}, diff --git a/src/sources.jl b/src/sources.jl index 0c27e54..edcc7ed 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -30,7 +30,7 @@ end """ Type representing components of a 2D moment tensor. """ -Base.@kwdef struct MomentTensor2D{T} <: MomentTensor{T} +Base.@kwdef struct MomentTensor2D{T} <: MomentTensor{T, 2} Mxx::T Mzz::T Mxz::T @@ -39,7 +39,7 @@ end """ Type representing components of a 3D moment tensor. """ -Base.@kwdef struct MomentTensor3D{T} <: MomentTensor{T} +Base.@kwdef struct MomentTensor3D{T} <: MomentTensor{T, 3} Mxx::T Myy::T Mzz::T @@ -51,7 +51,7 @@ end """ Type representing a multi-source configuration for a wave propagation shot. """ -struct MomentTensorSources{T, M <: MomentTensor{T}} <: Sources{T} +struct MomentTensorSources{T, N, M <: MomentTensor{T, N}} <: Sources{T} positions::Matrix{T} tf::Matrix{T} momtens::Vector{M} @@ -63,15 +63,15 @@ struct MomentTensorSources{T, M <: MomentTensor{T}} <: Sources{T} tf::Matrix{T}, momtens::Vector{M} domfreq::T - ) where {T, M <: MomentTensor{T}} + ) where {T, N, M <: MomentTensor{T}} Create a single shot wave propagation source configuration from source positions, time-functions and a dominant frequency. """ - function MomentTensorSources(positions::Matrix{T}, tf::Matrix{T}, momtens::Vector{M}, domfreq::T) where {T, M <: MomentTensor{T}} + function MomentTensorSources(positions::Matrix{T}, tf::Matrix{T}, momtens::Vector{M}, domfreq::T) where {T, N, M <: MomentTensor{T, N}} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" @assert length(momtens) == size(positions, 1) - return new{T, M}(positions, tf, momtens, domfreq) + return new{T, N, M}(positions, tf, momtens, domfreq) end end diff --git a/src/grids/abstract_types.jl b/src/utils/abstract_types.jl similarity index 100% rename from src/grids/abstract_types.jl rename to src/utils/abstract_types.jl diff --git a/src/grids/checkpointers.jl b/src/utils/checkpointers.jl similarity index 100% rename from src/grids/checkpointers.jl rename to src/utils/checkpointers.jl diff --git a/src/grids/fields.jl b/src/utils/fields.jl similarity index 100% rename from src/grids/fields.jl rename to src/utils/fields.jl diff --git a/src/grids/grids.jl b/src/utils/grids.jl similarity index 100% rename from src/grids/grids.jl rename to src/utils/grids.jl diff --git a/src/utils.jl b/src/utils/utils.jl similarity index 100% rename from src/utils.jl rename to src/utils/utils.jl diff --git a/src/wrappers.jl b/src/wrappers.jl index bbdf2da..9e806f6 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -15,7 +15,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -29,7 +29,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). function swforward!( params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; parall::Symbol=:threads, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, @@ -58,7 +58,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -69,7 +69,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function swforward!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; +function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T}}, Nothing} where {T, N} if logger === nothing logger = current_logger() @@ -90,7 +90,7 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -106,7 +106,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). function swmisfit!( params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; parall::Symbol=:threads, misfit::AbstractMisfit=L2Misfit(nothing), logger::Union{Nothing, AbstractLogger}=nothing @@ -131,7 +131,7 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -144,7 +144,7 @@ Receivers traces are stored in the `Receivers` object for each shot. See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). """ -function swmisfit!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; +function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::T where {T, N} if logger === nothing logger = current_logger() @@ -173,7 +173,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -188,9 +188,9 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ function swgradient!( - params::InputParameters{T, N}, + params::InputParameters{T,N}, matprop::MaterialProperties{T, N}, - shots::Vector{Shot{T}}; + shots::Vector{<:Shot{T}}; parall::Symbol=:threads, check_freq::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, @@ -199,7 +199,7 @@ function swgradient!( smooth_radius::Int=5, logger::Union{Nothing, AbstractLogger}=nothing )::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -228,7 +228,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: @@ -242,9 +242,9 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. """ -function swgradient!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{Shot{T}}; +function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -286,11 +286,11 @@ function build_wavesim(params::InputParameters{T, N}, matprop::MaterialPropertie end build_concrete_wavesim( - params::InputParametersAcoustic{T, N}, - matprop::VpAcousticCDMaterialProperties{T, N}, + params::InputParametersAcoustic{T,N}, + matprop::VpAcousticCDMaterialProperties{T,N}, cpmlparams::CPMLBoundaryConditionParameters{T}; kwargs... -) where {T, N} = AcousticCDCPMLWaveSimulation( +) where {T,N} = AcousticCDCPMLWaveSimulation( params, matprop, cpmlparams; @@ -298,11 +298,11 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersAcoustic{T, N}, - matprop::VpRhoAcousticVDMaterialProperties{T, N}, + params::InputParametersAcoustic{T,N}, + matprop::VpRhoAcousticVDMaterialProperties{T,N}, cpmlparams::CPMLBoundaryConditionParameters; kwargs... -) where {T, N} = AcousticVDStaggeredCPMLWaveSimulation( +) where {T,N} = AcousticVDStaggeredCPMLWaveSimulation( params, matprop, cpmlparams; @@ -310,11 +310,11 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersElastic{T, N}, - matprop::ElasticIsoMaterialProperties{T, N}, + params::InputParametersElastic{T,N}, + matprop::ElasticIsoMaterialProperties{T,N}, cpmlparams::CPMLBoundaryConditionParameters; kwargs... -) where {T, N} = ElasticIsoCPMLWaveSimulation( +) where {T,N} = ElasticIsoCPMLWaveSimulation( params.gridsize, params.gridspacing, params.ntimesteps, diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index c497157..7654cf9 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -50,14 +50,14 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # save seismograms res = copy(recs.seismograms) # same receivers, but positions reversed reverse!(recs.positions; dims=1) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # test that seismograms are the same for i in 1:nrecs @@ -105,7 +105,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # save seismograms res = copy(recs.seismograms) @@ -114,7 +114,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do # same receivers, but positions reversed reverse!(recs.positions; dims=1) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # test that seismograms are the same for i in 1:nrecs @@ -163,14 +163,14 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # save seismograms res = copy(recs.seismograms) # same receivers, but positions reversed reverse!(recs.positions; dims=1) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # test that seismograms are the same for i in 1:nrecs @@ -221,7 +221,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do ) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # save seismograms res = copy(recs.seismograms) @@ -230,7 +230,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do # same receivers, but positions reversed reverse!(recs.positions; dims=1) # compute forward - swforward!(wavesim, matprop, [Shot(srcs, recs)]) + swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) # test that seismograms are the same for i in 1:nrecs diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index 2be2541..abf692e 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -40,7 +40,7 @@ function setup_constant_vel_1D_CPML(nt, dt, nx, dx, c0, f0, halo, rcoef) posrecs[1, :] = [lx / 3] srcs = ScalarSources(possrcs, srctf, f0) recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) - shots = [Shot(; srcs=srcs, recs=recs)] + shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, vel end @@ -63,7 +63,7 @@ function setup_constant_vel_rho_1D_CPML(nt, dt, nx, dx, c0, ρ0, t0, f0, halo, r posrecs[1, :] = [lx / 3] srcs = ScalarSources(possrcs, srctf, f0) recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) - shots = [Shot(; srcs=srcs, recs=recs)] + shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, matprop, refsrctf end @@ -87,7 +87,7 @@ function setup_constant_vel_2D_CPML(nt, dt, nx, ny, dx, dy, c0, f0, halo, rcoef) posrecs[1, :] = [lx / 3, ly / 2] srcs = ScalarSources(possrcs, srctf, f0) recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) - shots = [Shot(; srcs=srcs, recs=recs)] + shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, vel end @@ -110,7 +110,7 @@ function setup_constant_vel_rho_2D_CPML(nt, dt, nx, ny, dx, dy, c0, ρ0, t0, f0, posrecs[1, :] = [lx / 3, ly / 2] srcs = ScalarSources(possrcs, srctf, f0) recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) - shots = [Shot(; srcs=srcs, recs=recs)] + shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, matprop end @@ -135,7 +135,7 @@ function setup_constant_vel_3D_CPML(nt, dt, nx, ny, nz, dx, dy, dz, c0, f0, halo posrecs[1, :] = [lx / 3, ly / 2, lz / 2] srcs = ScalarSources(possrcs, srctf, f0) recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) - shots = [Shot(; srcs=srcs, recs=recs)] + shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, vel end From 7843f0fcec4bfe1befede052b186ed024ff9d994 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 12:52:26 +0200 Subject: [PATCH 057/111] Move things around --- src/SeismicWaves.jl | 41 ++- src/abstract_types.jl | 27 -- src/apis/build.jl | 72 ++++ src/apis/forward.jl | 185 ++++++++++ src/apis/gradient.jl | 217 ++++++++++++ src/apis/misfit.jl | 104 ++++++ src/apis/utils.jl | 8 + src/inversion/misfits/L2Misfit.jl | 40 +++ .../ZerothOrderTikhonovRegularization.jl} | 41 --- src/{boundarycond.jl => models/bdc_params.jl} | 0 src/{ => shots}/receivers.jl | 0 src/{ => shots}/shot.jl | 13 - src/{ => shots}/sources.jl | 0 src/solve.jl | 261 -------------- src/srcrec_interpolation.jl | 178 ---------- src/utils/abstract_types.jl | 22 ++ src/{ => utils}/checks.jl | 2 +- src/utils/utils.jl | 192 ++++++++++ src/wrappers.jl | 329 ------------------ 19 files changed, 865 insertions(+), 867 deletions(-) delete mode 100644 src/abstract_types.jl create mode 100644 src/apis/build.jl create mode 100644 src/apis/forward.jl create mode 100644 src/apis/gradient.jl create mode 100644 src/apis/misfit.jl create mode 100644 src/apis/utils.jl create mode 100644 src/inversion/misfits/L2Misfit.jl rename src/{misfits.jl => inversion/regularizations/ZerothOrderTikhonovRegularization.jl} (56%) rename src/{boundarycond.jl => models/bdc_params.jl} (100%) rename src/{ => shots}/receivers.jl (100%) rename src/{ => shots}/shot.jl (62%) rename src/{ => shots}/sources.jl (100%) delete mode 100644 src/solve.jl delete mode 100644 src/srcrec_interpolation.jl rename src/{ => utils}/checks.jl (97%) delete mode 100644 src/wrappers.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 0026794..f2994cd 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -30,29 +30,30 @@ export swforward!, swmisfit!, swgradient! # source time functions export gaussstf, gaussderivstf, rickerstf -include("abstract_types.jl") +include("utils/abstract_types.jl") +# Traits include("traits/boundarycondition.jl") include("traits/shooting.jl") include("traits/snappable.jl") include("traits/grid.jl") -include("sources.jl") -include("receivers.jl") -include("shot.jl") -include("checks.jl") -include("boundarycond.jl") -include("srcrec_interpolation.jl") - -include("models/cpmlcoeffs.jl") - # Utils include("utils/utils.jl") -include("utils/abstract_types.jl") +include("utils/checks.jl") include("utils/fields.jl") include("utils/grids.jl") include("utils/checkpointers.jl") +# Shots +include("shots/sources.jl") +include("shots/receivers.jl") +include("shots/shot.jl") + +# General models +include("models/bdc_params.jl") +include("models/cpmlcoeffs.jl") + # Acoustic include("models/acoustic/acou_abstract_types.jl") include("models/acoustic/acou_material_properties.jl") @@ -73,12 +74,18 @@ include("models/elastic/ela_init_bc.jl") # Backend selection include("models/backend_selection.jl") -# Misfit -include("misfits.jl") -# Generic solve -include("solve.jl") -# Main functions -include("wrappers.jl") + +# Inversion +include("inversion/misfits/L2Misfit.jl") +include("inversion/regularizations/ZerothOrderTikhonovRegularization.jl") + +# APIs +include("apis/build.jl") +include("apis/utils.jl") +include("apis/forward.jl") +include("apis/misfit.jl") +include("apis/gradient.jl") + # Acoustic serial backend include("models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl") diff --git a/src/abstract_types.jl b/src/abstract_types.jl deleted file mode 100644 index b9257d1..0000000 --- a/src/abstract_types.jl +++ /dev/null @@ -1,27 +0,0 @@ - -@doc """ -$(TYPEDEF) - -Abstract type for wave simulations. -""" -abstract type WaveSimulation{T, N} end - -abstract type InputParameters{T, N} end - -abstract type InputBoundaryConditionParameters{T} end - -abstract type MaterialProperties{T, N} end - -abstract type Shot{T} end - -abstract type Sources{T} end - -abstract type Receivers{T} end - -abstract type MomentTensor{T, N} end - -abstract type InterpolationMethod end - -abstract type AbstractMisfit end - -abstract type AbstractRegularization end diff --git a/src/apis/build.jl b/src/apis/build.jl new file mode 100644 index 0000000..2730ddc --- /dev/null +++ b/src/apis/build.jl @@ -0,0 +1,72 @@ +@doc """ + +$(TYPEDSIGNATURES) + +Builds a wave similation based on the input paramters `params` and keyword arguments `kwargs`. + +# Positional arguments +- `params::InputParameters{T,N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). + +# Keyword arguments +- `parall::Symbol = :threads`: controls which backend is used for computation: + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` + - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` + - otherwise the serial version if set to `:serial` +- `gradient::Bool = false`: whether the wave simulation is used for gradients computations. +- `check_freq::Union{<:Int, Nothing} = nothing`: if `gradient = true` and if specified, enables checkpointing and specifies the checkpointing frequency. +- `snapevery::Union{<:Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). +- `infoevery::Union{<:Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. +""" +function build_wavesim(params::InputParameters{T, N}, matprop::MaterialProperties{T, N}; parall::Symbol, kwargs...) where {T, N} + if parall == :threadpersrc + nthr = Threads.nthreads() + wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall=parall, kwargs...) for _ in 1:nthr] + else + wsim = build_concrete_wavesim(params, matprop, params.boundcond; parall=parall, kwargs...) + end + return wsim +end + +build_concrete_wavesim( + params::InputParametersAcoustic{T,N}, + matprop::VpAcousticCDMaterialProperties{T,N}, + cpmlparams::CPMLBoundaryConditionParameters{T}; + kwargs... +) where {T,N} = AcousticCDCPMLWaveSimulation( + params, + matprop, + cpmlparams; + kwargs... +) + +build_concrete_wavesim( + params::InputParametersAcoustic{T,N}, + matprop::VpRhoAcousticVDMaterialProperties{T,N}, + cpmlparams::CPMLBoundaryConditionParameters; + kwargs... +) where {T,N} = AcousticVDStaggeredCPMLWaveSimulation( + params, + matprop, + cpmlparams; + kwargs... +) + +build_concrete_wavesim( + params::InputParametersElastic{T,N}, + matprop::ElasticIsoMaterialProperties{T,N}, + cpmlparams::CPMLBoundaryConditionParameters; + kwargs... +) where {T,N} = ElasticIsoCPMLWaveSimulation( + params.gridsize, + params.gridspacing, + params.ntimesteps, + params.dt, + matprop, + cpmlparams.halo, + cpmlparams.rcoef; + freetop=cpmlparams.freeboundtop, + kwargs... +) + +####################################################### diff --git a/src/apis/forward.jl b/src/apis/forward.jl new file mode 100644 index 0000000..cb0fef1 --- /dev/null +++ b/src/apis/forward.jl @@ -0,0 +1,185 @@ +### FORWARDS ### + +####################################################### + +@doc """ + +$(TYPEDSIGNATURES) + +Compute forward simulation using the given input parameters `params` and material properties `matprop` on multiple shots. +Receivers traces are stored in the `Receivers` object for each shot. See also [`Receivers`](@ref). + +Return a vector of snapshots for every shot if snapshotting is enabled. + +See also [`Sources`](@ref), [`Receivers`](@ref). + +# Positional arguments +- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). + +# Keyword arguments +- `parall::Symbol = :threads`: controls which backend is used for computation: + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` + - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` + - otherwise the serial version if set to `:serial` +- `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. +- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. +""" +function swforward!( + params::InputParameters{T, N}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; + parall::Symbol=:threads, + snapevery::Union{Int, Nothing}=nothing, + infoevery::Union{Int, Nothing}=nothing, + logger::Union{Nothing, AbstractLogger}=nothing +)::Union{Vector{Array{T}}, Nothing} where {T, N} + if logger === nothing + logger = current_logger() + end + return with_logger(logger) do + # Build wavesim + wavesim = build_wavesim(params, matprop; parall=parall, snapevery=snapevery, infoevery=infoevery, gradient=false) + # Solve simulation + run_swforward!(wavesim, matprop, shots) + end +end + +@doc """ + +$(TYPEDSIGNATURES) + +Compute forward simulation using a previously constructed `WaveSimulation` object. +Return a vector of snapshots for every shot if snapshotting is enabled. + +See also [`Sources`](@ref), [`Receivers`](@ref). + +# Positional arguments +- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). + +# Keyword arguments +- `parall::Symbol = :threads`: controls which backend is used for computation: + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` + - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` + - otherwise the serial version if set to `:serial` +- `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. +- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. + """ +function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T}}, Nothing} where {T, N} + if logger === nothing + logger = current_logger() + end + return with_logger(logger) do + run_swforward!(wavesim, matprop, shots; kwargs...) + end +end + +####################################################### + +## single WaveSimulation object +@views function run_swforward!( + model::WaveSimulation{T, N}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; +)::Union{Vector{Array{T}}, Nothing} where {T, N} + + # Check wavesim consistency + @debug "Checking consistency across simulation type, material parameters and source-receiver types" + check_sim_consistency(model, matprop, shots) + + # Set wavesim material properties + # Remark: matprop in wavesim are mutated + @debug "Setting wavesim material properties" + set_wavesim_matprop!(model, matprop) + # Now onwards matprop from "outside" should not be used anymore!!! + + # Snapshots setup + takesnapshots = snapenabled(model) + if takesnapshots + snapshots_per_shot = [] + end + + # Shots loop + for (s, singleshot) in enumerate(shots) + @info "Shot #$s" + # Initialize shot + @debug "Initializing shot" + init_shot!(model, singleshot) + # Compute forward solver + @info "Computing forward solver" + swforward_1shot!(model, singleshot) + # Save shot's snapshots + if takesnapshots + @info "Saving snapshots" + push!(snapshots_per_shot, Array(model.snapshots)) + end + end + + if takesnapshots + return snapshots_per_shot + end + return nothing +end + +## :threadpersrc, multiple WaveSimulation objects +@views function run_swforward!( + model::Vector{<:WaveSimulation{T, N}}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; +)::Union{Vector{Array{T}}, Nothing} where {T, N} + nwsim = length(model) + nthr = Threads.nthreads() + # make sure the number of threads has not changed! + @assert nthr == nwsim + + snapshots_per_shot = Dict{Int, Vector}() + for w in 1:nwsim + # Check wavesim consistency + @debug "Checking consistency across simulation type, material parameters and source-receiver types" + check_sim_consistency(model[w], matprop, shots) + # Set wavesim material properties + # Remark: matprop in wavesim are mutated + @debug "Setting wavesim material properties" + set_wavesim_matprop!(model[w], matprop) + # Now onwards matprop from outside should not be used anymore!!! + + # Snapshots setup + if snapenabled(model[w]) + snapshots_per_shot[w] = [] + end + end + + # Shots loop + nshots = length(shots) + grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange + # loop on the set of WaveSimulation + Threads.@threads for w in 1:nwsim + # loop on the subset of shots per each WaveSimulation + for s in grpshots[w] + @info "Shot #$s" + singleshot = shots[s] + # Initialize shot + @debug "Initializing shot" + init_shot!(model[w], singleshot) + # Compute forward solver + @info "Computing forward solver" + swforward_1shot!(model[w], singleshot) + # Save shot's snapshots + if snapenabled(model[w]) + @info "Saving snapshots" + push!(snapshots_per_shot[w], copy(model[w].snapshots)) + end + end + end + + if takesnapshots + return collect(values(snapshots_per_shot)) + end + return nothing +end \ No newline at end of file diff --git a/src/apis/gradient.jl b/src/apis/gradient.jl new file mode 100644 index 0000000..6142b01 --- /dev/null +++ b/src/apis/gradient.jl @@ -0,0 +1,217 @@ +### GRADIENTS ### + +@doc """ + +$(TYPEDSIGNATURES) + +Compute gradients w.r.t. model parameters using the given input parameters `params` and material parameters `matprop` on multiple shots. + +The `check_freq` parameter controls the checkpoiting frequency for adjoint computation. +If `nothing`, no checkpointing is performed. +If greater than 2, a checkpoint is saved every `check_freq` time step. +The optimal tradeoff value is `check_freq = sqrt(nt)` where `nt` is the number of time steps of the forward simulation. +Bigger values speed up computation at the cost of using more memory. + +See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). + +# Positional arguments +- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). + +# Keyword arguments +- `parall::Symbol = :threads`: controls which backend is used for computation: + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` + - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` + - otherwise the serial version if set to `:serial` +- `check_freq::Union{Int, Nothing} = nothing`: if specified, enables checkpointing and specifies the checkpointing frequency. +- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. +- `compute_misfit::Bool = false`: if true, also computes and return misfit value. +- `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. +- `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. +""" +function swgradient!( + params::InputParameters{T,N}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; + parall::Symbol=:threads, + check_freq::Union{Int, Nothing}=nothing, + infoevery::Union{Int, Nothing}=nothing, + compute_misfit::Bool=false, + misfit::AbstractMisfit=L2Misfit(nothing), + smooth_radius::Int=5, + logger::Union{Nothing, AbstractLogger}=nothing +)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + if logger === nothing + logger = current_logger() + end + return with_logger(logger) do + # Build wavesim + wavesim = build_wavesim(params, matprop; parall=parall, infoevery=infoevery, gradient=true, check_freq=check_freq, smooth_radius=smooth_radius) + # Solve simulation + run_swgradient!(wavesim, matprop, shots; compute_misfit=compute_misfit, misfit=misfit) + end +end + +@doc """ + +$(TYPEDSIGNATURES) + +Compute gradients w.r.t. model parameters using the *previously* built `WaveSimulation`. This avoids re-initializing and re-allocating several arrays in case of multiple gradient calculations. + +The `check_freq` parameter controls the checkpoiting frequency for adjoint computation. +If `nothing`, no checkpointing is performed. +If greater than 2, a checkpoint is saved every `check_freq` time step. +The optimal tradeoff value is `check_freq = sqrt(nt)` where `nt` is the number of time steps of the forward simulation. +Bigger values speed up computation at the cost of using more memory. + +See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). + +# Positional arguments +- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). + +# Keyword arguments +- `parall::Symbol = :threads`: controls which backend is used for computation: + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` + - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` + - otherwise the serial version if set to `:serial` +- `check_freq::Union{Int, Nothing} = nothing`: if specified, enables checkpointing and specifies the checkpointing frequency. +- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. +- `compute_misfit::Bool = false`: if true, also computes and return misfit value. +- `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. +- `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. +""" +function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + if logger === nothing + logger = current_logger() + end + return with_logger(logger) do + run_swgradient!(wavesim, matprop, shots; kwargs...) + end +end + +####################################################### + +## single WaveSimulation object +@views function run_swgradient!( + model::WaveSimulation{T, N}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; + compute_misfit::Bool=false, + misfit::AbstractMisfit=L2Misfit(nothing) +)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + + # Check wavesim consistency + @debug "Checking consistency across simulation type, material parameters and source-receiver types" + check_sim_consistency(model, matprop, shots) + + # Set wavesim material properties + @debug "Setting wavesim material properties" + set_wavesim_matprop!(model, matprop) + + # Initialize total gradient and total misfit + totgrad = init_gradient(model) + totmisfitval = 0 + # Shots loop + for (s, singleshot) in enumerate(shots) + @info "Shot #$s" + # Initialize shot + @debug "Initializing shot" + init_shot!(model, singleshot) + @debug "Checking invcov matrix" + check_invcov_matrix(model, singleshot.recs.invcov) + # Compute forward solver + @info "Computing gradient solver" + curgrad = swgradient_1shot!(model, singleshot, misfit) + # Accumulate gradient + accumulate_gradient!(totgrad, curgrad, model) + # Compute misfit if needed + if compute_misfit + @info "Computing misfit" + totmisfitval += misfit(singleshot.recs, matprop) + end + end + + return compute_misfit ? (totgrad, totmisfitval) : totgrad +end + +## :threadpersrc, multiple WaveSimulation objects +@views function run_swgradient!( + model::Vector{<:WaveSimulation{T, N}}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; + compute_misfit::Bool=false, + misfit::AbstractMisfit=L2Misfit(nothing) +)::Union{Dict{String, Array{T, N}}, + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + nwsim = length(model) + nthr = Threads.nthreads() + # make sure the number of threads has not changed! + @assert Threads.nthreads() == nwsim + + for w in 1:nwsim + # Check wavesim consistency + @debug "Checking consistency across simulation type, material parameters and source-receiver types" + check_sim_consistency(model[w], matprop, shots) + + # Set wavesim material properties + @debug "Setting wavesim material properties" + set_wavesim_matprop!(model[w], matprop) + end + + # Initialize total gradient and total misfit + nshots = length(shots) + allgrad = Vector{Dict{String, Array{T, N}}}(undef, nshots) + + if compute_misfit + allmisfitval = zeros(T, nshots) + totmisfitval = 0 + end + + # Shots loop + grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange + # loop on the set of WaveSimulation + Threads.@threads for w in 1:nwsim + # loop on the subset of shots per each WaveSimulation + for s in grpshots[w] + singleshot = shots[s] + @info "Shot #$s" + # Initialize shot + @debug "Initializing shot" + init_shot!(model[w], singleshot) + @debug "Checking invcov matrix" + check_invcov_matrix(model[w], singleshot.recs.invcov) + # Compute forward solver + @info "Computing gradient solver" + curgrad = swgradient_1shot!( + model[w], singleshot, misfit + ) + # Save gradient + allgrad[s] = curgrad + # Compute misfit if needed + if compute_misfit + @info "Computing misfit" + allmisfitval[s] = misfit(singleshot.recs, matprop) + end + end + end + + # Accumulate gradient and misfit + totgrad = init_gradient(model) + for curgrad in allgrad + accumulate_gradient!(model, totgrad, curgrad) + end + if compute_misfit + totmisfitval = sum(allmisfitval) + end + + return compute_misfit ? (totgrad, totmisfitval) : totgrad +end diff --git a/src/apis/misfit.jl b/src/apis/misfit.jl new file mode 100644 index 0000000..998181b --- /dev/null +++ b/src/apis/misfit.jl @@ -0,0 +1,104 @@ +@doc """ + +$(TYPEDSIGNATURES) + +Return the misfit w.r.t. observed data by running a forward simulation using the given input parameters `params` and material properties `matprop` on multiple shots. + +# Positional arguments +- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). + +# Keyword arguments +- `parall::Symbol = :threads`: controls which backend is used for computation: + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` + - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` + - otherwise the serial version if set to `:serial` + +Receivers traces are stored in the `Receivers` object for each shot. + +See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). +""" +function swmisfit!( + params::InputParameters{T, N}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; + parall::Symbol=:threads, + misfit::AbstractMisfit=L2Misfit(nothing), + logger::Union{Nothing, AbstractLogger}=nothing +)::T where {T, N} + if logger === nothing + logger = current_logger() + end + return with_logger(logger) do + # Build wavesim + wavesim = build_wavesim(params, matprop; parall=parall, gradient=false) + # Compute misfit + run_swmisfit!(wavesim, matprop, shots; misfit=misfit) + end +end + +@doc """ + +$(TYPEDSIGNATURES) + +Return the misfit w.r.t. observed data by running a forward simulation using the given `WaveSimulation` object as an input. + +# Positional arguments +- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). + +# Keyword arguments +- `parall::Symbol = :threads`: controls which backend is used for computation: + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` + - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` + - otherwise the serial version if set to `:serial` + +Receivers traces are stored in the `Receivers` object for each shot. + +See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). +""" +function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; + logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::T where {T, N} + if logger === nothing + logger = current_logger() + end + return with_logger(logger) do + run_swmisfit!(wavesim, matprop, shots; kwargs...) + end +end + +####################################################### + +### MISFITS ### + +## single or multiple WaveSimulation objects +@views function run_swmisfit!( + model::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; + misfit::AbstractMisfit=L2Misfit(nothing) +)::T where {T, N} + + # Solve forward model for all shots + run_swforward!(model, matprop, shots) + # Compute total misfit for all shots + @info "Computing misfit" + totmisfitval = 0 + for singleshot in shots + @debug "Checking invcov matrix" + if typeof(model) <: Vector{<:WaveSimulation} + for i in eachindex(model) + check_invcov_matrix(model[i], singleshot.recs.invcov) + end + else + check_invcov_matrix(model, singleshot.recs.invcov) + end + totmisfitval += misfit(singleshot.recs, matprop) + end + + return totmisfitval +end \ No newline at end of file diff --git a/src/apis/utils.jl b/src/apis/utils.jl new file mode 100644 index 0000000..01369fc --- /dev/null +++ b/src/apis/utils.jl @@ -0,0 +1,8 @@ +### UPDATE MATERIAL PROPERTIES ## + +@views function set_wavesim_matprop!(wavesim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}) where {T, N} + @debug "Checking new material properties" + check_matprop(wavesim, matprop) + @debug "Updating WaveSimulation material properties" + update_matprop!(wavesim, matprop) +end \ No newline at end of file diff --git a/src/inversion/misfits/L2Misfit.jl b/src/inversion/misfits/L2Misfit.jl new file mode 100644 index 0000000..b7e4f52 --- /dev/null +++ b/src/inversion/misfits/L2Misfit.jl @@ -0,0 +1,40 @@ +Base.@kwdef struct L2Misfit <: AbstractMisfit + regularization::Union{Nothing, AbstractRegularization} +end + +function (misfit::L2Misfit)(recs::ScalarReceivers, matprop::MaterialProperties) + # Compute residuals + residuals = recs.seismograms - recs.observed + # Window residuals using mask + mask = ones(size(residuals, 1)) + if length(recs.windows) > 0 + for wnd in recs.windows + mask[wnd.first:wnd.second] .= 2.0 + end + mask .-= 1.0 + end + residuals .= mask .* residuals + # Inner product using inverse covariance matrix + msf = dot(residuals, recs.invcov, residuals) / 2 + # Add regularization if needed + if misfit.regularization !== nothing + msf += misfit.regularization(matprop) + end + return msf +end + +function dχ_du(_::L2Misfit, recs::ScalarReceivers) + # Compute residuals + residuals = recs.seismograms - recs.observed + # Window residuals using mask + mask = ones(size(residuals, 1)) + if length(recs.windows) > 0 + for wnd in recs.windows + mask[wnd.first:wnd.second] .= 2.0 + end + mask .-= 1.0 + end + residuals .= mask .* residuals + # Multiply with inverse of covariance matrix + return recs.invcov * residuals +end \ No newline at end of file diff --git a/src/misfits.jl b/src/inversion/regularizations/ZerothOrderTikhonovRegularization.jl similarity index 56% rename from src/misfits.jl rename to src/inversion/regularizations/ZerothOrderTikhonovRegularization.jl index 4b0b135..a90a25c 100644 --- a/src/misfits.jl +++ b/src/inversion/regularizations/ZerothOrderTikhonovRegularization.jl @@ -1,44 +1,3 @@ -Base.@kwdef struct L2Misfit <: AbstractMisfit - regularization::Union{Nothing, AbstractRegularization} -end - -function (misfit::L2Misfit)(recs::ScalarReceivers, matprop::MaterialProperties) - # Compute residuals - residuals = recs.seismograms - recs.observed - # Window residuals using mask - mask = ones(size(residuals, 1)) - if length(recs.windows) > 0 - for wnd in recs.windows - mask[wnd.first:wnd.second] .= 2.0 - end - mask .-= 1.0 - end - residuals .= mask .* residuals - # Inner product using inverse covariance matrix - msf = dot(residuals, recs.invcov, residuals) / 2 - # Add regularization if needed - if misfit.regularization !== nothing - msf += misfit.regularization(matprop) - end - return msf -end - -function dχ_du(_::L2Misfit, recs::ScalarReceivers) - # Compute residuals - residuals = recs.seismograms - recs.observed - # Window residuals using mask - mask = ones(size(residuals, 1)) - if length(recs.windows) > 0 - for wnd in recs.windows - mask[wnd.first:wnd.second] .= 2.0 - end - mask .-= 1.0 - end - residuals .= mask .* residuals - # Multiply with inverse of covariance matrix - return recs.invcov * residuals -end - Base.@kwdef struct ZerothOrderTikhonovRegularization{T, M <: MaterialProperties{T}} <: AbstractRegularization matprop_prior::M alpha::T diff --git a/src/boundarycond.jl b/src/models/bdc_params.jl similarity index 100% rename from src/boundarycond.jl rename to src/models/bdc_params.jl diff --git a/src/receivers.jl b/src/shots/receivers.jl similarity index 100% rename from src/receivers.jl rename to src/shots/receivers.jl diff --git a/src/shot.jl b/src/shots/shot.jl similarity index 62% rename from src/shot.jl rename to src/shots/shot.jl index 379028a..eb0033d 100644 --- a/src/shot.jl +++ b/src/shots/shot.jl @@ -37,16 +37,3 @@ function init_shot!(model::WaveSimulation{T}, shot::Shot{T}; kwargs...) where {T # Initialize boundary conditions based on current shot init_bdc!(model, shot.srcs) end - -@views function find_nearest_grid_points(model::WaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} - # source time functions - nsrcs = size(positions, 1) # number of sources - ncoos = size(positions, 2) # number of coordinates - # find nearest grid point for each source - idx_positions = zeros(Int, size(positions)) # sources positions (in grid points) - for s in 1:nsrcs - tmp = [positions[s, i] / model.grid.spacing[i] + 1 for i in 1:ncoos] - idx_positions[s, :] .= round.(Int, tmp, RoundNearestTiesUp) - end - return idx_positions -end \ No newline at end of file diff --git a/src/sources.jl b/src/shots/sources.jl similarity index 100% rename from src/sources.jl rename to src/shots/sources.jl diff --git a/src/solve.jl b/src/solve.jl deleted file mode 100644 index 505768b..0000000 --- a/src/solve.jl +++ /dev/null @@ -1,261 +0,0 @@ -### UPDATE MATERIAL PROPERTIES ## - -@views function set_wavesim_matprop!(wavesim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}) where {T, N} - @debug "Checking new material properties" - check_matprop(wavesim, matprop) - @debug "Updating WaveSimulation material properties" - update_matprop!(wavesim, matprop) -end - -### FORWARDS ### - -## single WaveSimulation object -@views function run_swforward!( - model::WaveSimulation{T, N}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; -)::Union{Vector{Array{T}}, Nothing} where {T, N} - - # Check wavesim consistency - @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(model, matprop, shots) - - # Set wavesim material properties - # Remark: matprop in wavesim are mutated - @debug "Setting wavesim material properties" - set_wavesim_matprop!(model, matprop) - # Now onwards matprop from "outside" should not be used anymore!!! - - # Snapshots setup - takesnapshots = snapenabled(model) - if takesnapshots - snapshots_per_shot = [] - end - - # Shots loop - for (s, singleshot) in enumerate(shots) - @info "Shot #$s" - # Initialize shot - @debug "Initializing shot" - init_shot!(model, singleshot) - # Compute forward solver - @info "Computing forward solver" - swforward_1shot!(model, singleshot) - # Save shot's snapshots - if takesnapshots - @info "Saving snapshots" - push!(snapshots_per_shot, Array(model.snapshots)) - end - end - - if takesnapshots - return snapshots_per_shot - end - return nothing -end - -## :threadpersrc, multiple WaveSimulation objects -@views function run_swforward!( - model::Vector{<:WaveSimulation{T, N}}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; -)::Union{Vector{Array{T}}, Nothing} where {T, N} - nwsim = length(model) - nthr = Threads.nthreads() - # make sure the number of threads has not changed! - @assert nthr == nwsim - - snapshots_per_shot = Dict{Int, Vector}() - for w in 1:nwsim - # Check wavesim consistency - @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(model[w], matprop, shots) - # Set wavesim material properties - # Remark: matprop in wavesim are mutated - @debug "Setting wavesim material properties" - set_wavesim_matprop!(model[w], matprop) - # Now onwards matprop from outside should not be used anymore!!! - - # Snapshots setup - if snapenabled(model[w]) - snapshots_per_shot[w] = [] - end - end - - # Shots loop - nshots = length(shots) - grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange - # loop on the set of WaveSimulation - Threads.@threads for w in 1:nwsim - # loop on the subset of shots per each WaveSimulation - for s in grpshots[w] - @info "Shot #$s" - singleshot = shots[s] - # Initialize shot - @debug "Initializing shot" - init_shot!(model[w], singleshot) - # Compute forward solver - @info "Computing forward solver" - swforward_1shot!(model[w], singleshot) - # Save shot's snapshots - if snapenabled(model[w]) - @info "Saving snapshots" - push!(snapshots_per_shot[w], copy(model[w].snapshots)) - end - end - end - - if takesnapshots - return collect(values(snapshots_per_shot)) - end - return nothing -end - -### MISFITS ### - -## single or multiple WaveSimulation objects -@views function run_swmisfit!( - model::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; - misfit::AbstractMisfit=L2Misfit(nothing) -)::T where {T, N} - - # Solve forward model for all shots - run_swforward!(model, matprop, shots) - # Compute total misfit for all shots - @info "Computing misfit" - totmisfitval = 0 - for singleshot in shots - @debug "Checking invcov matrix" - if typeof(model) <: Vector{<:WaveSimulation} - for i in eachindex(model) - check_invcov_matrix(model[i], singleshot.recs.invcov) - end - else - check_invcov_matrix(model, singleshot.recs.invcov) - end - totmisfitval += misfit(singleshot.recs, matprop) - end - - return totmisfitval -end - -### GRADIENTS ### - -## single WaveSimulation object -@views function run_swgradient!( - model::WaveSimulation{T, N}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; - compute_misfit::Bool=false, - misfit::AbstractMisfit=L2Misfit(nothing) -)::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} - - # Check wavesim consistency - @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(model, matprop, shots) - - # Set wavesim material properties - @debug "Setting wavesim material properties" - set_wavesim_matprop!(model, matprop) - - # Initialize total gradient and total misfit - totgrad = init_gradient(model) - totmisfitval = 0 - # Shots loop - for (s, singleshot) in enumerate(shots) - @info "Shot #$s" - # Initialize shot - @debug "Initializing shot" - init_shot!(model, singleshot) - @debug "Checking invcov matrix" - check_invcov_matrix(model, singleshot.recs.invcov) - # Compute forward solver - @info "Computing gradient solver" - curgrad = swgradient_1shot!(model, singleshot, misfit) - # Accumulate gradient - accumulate_gradient!(totgrad, curgrad, model) - # Compute misfit if needed - if compute_misfit - @info "Computing misfit" - totmisfitval += misfit(singleshot.recs, matprop) - end - end - - return compute_misfit ? (totgrad, totmisfitval) : totgrad -end - -## :threadpersrc, multiple WaveSimulation objects -@views function run_swgradient!( - model::Vector{<:WaveSimulation{T, N}}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; - compute_misfit::Bool=false, - misfit::AbstractMisfit=L2Misfit(nothing) -)::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} - nwsim = length(model) - nthr = Threads.nthreads() - # make sure the number of threads has not changed! - @assert Threads.nthreads() == nwsim - - for w in 1:nwsim - # Check wavesim consistency - @debug "Checking consistency across simulation type, material parameters and source-receiver types" - check_sim_consistency(model[w], matprop, shots) - - # Set wavesim material properties - @debug "Setting wavesim material properties" - set_wavesim_matprop!(model[w], matprop) - end - - # Initialize total gradient and total misfit - nshots = length(shots) - allgrad = Vector{Dict{String, Array{T, N}}}(undef, nshots) - - if compute_misfit - allmisfitval = zeros(T, nshots) - totmisfitval = 0 - end - - # Shots loop - grpshots = distribsrcs(nshots, nthr) # a vector of UnitRange - # loop on the set of WaveSimulation - Threads.@threads for w in 1:nwsim - # loop on the subset of shots per each WaveSimulation - for s in grpshots[w] - singleshot = shots[s] - @info "Shot #$s" - # Initialize shot - @debug "Initializing shot" - init_shot!(model[w], singleshot) - @debug "Checking invcov matrix" - check_invcov_matrix(model[w], singleshot.recs.invcov) - # Compute forward solver - @info "Computing gradient solver" - curgrad = swgradient_1shot!( - model[w], singleshot, misfit - ) - # Save gradient - allgrad[s] = curgrad - # Compute misfit if needed - if compute_misfit - @info "Computing misfit" - allmisfitval[s] = misfit(singleshot.recs, matprop) - end - end - end - - # Accumulate gradient and misfit - totgrad = init_gradient(model) - for curgrad in allgrad - accumulate_gradient!(model, totgrad, curgrad) - end - if compute_misfit - totmisfitval = sum(allmisfitval) - end - - return compute_misfit ? (totgrad, totmisfitval) : totgrad -end diff --git a/src/srcrec_interpolation.jl b/src/srcrec_interpolation.jl deleted file mode 100644 index 4f28b40..0000000 --- a/src/srcrec_interpolation.jl +++ /dev/null @@ -1,178 +0,0 @@ - -#################################################################### - -""" -Kaiser windowing function. - -# Parameters - - - `x`: coordinate of points - - `x0`: coordinate of source or receiver point - - `b`: 'b' coefficient - - `r`: cut-off radius -""" -function kaiser(x::Vector, x0::T, b::T, r::T) where {T} - # Kaiser window function - # r is window half with - # Rule of thumb for finite diff.: - # b=4.14 b=6.31 - # r = 4.0*dx - w = zeros(T, length(x)) - for i in 1:length(x) - xcur = x[i] - x0 - if -r <= xcur <= r - den = 1.0 / besseli(0, b) - w[i] = den * besseli(0, b * (sqrt.(1 - (xcur / r)^2))) - else - w[i] = 0.0 - end - end - return w -end - -##################################################################### - -""" -Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. - -# Parameters - - - `xstart`: origin coordinate of the grid - - `Δx`: grid spacing - - `kind`: :monopole or :dipole, i.e., using sinc or derivative of sinc - - `npts` (optional): half-number of grid points for the window - - `beta` (optional): 'beta' parameter for the Kaiser windowing function -""" -function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::Int; - npts::Int64=4, beta::Union{Nothing, Real}=nothing) - ## Coefficients for sinc interpolation - ## in 1D - ## xstart is the x coordinate of first node in the regular grid - ## - ## Rule of thumb for npts==4 [Hicks 2002, Geophysics]: - ## beta=4.14 for monopoles, - ## beta=4.40 for dipoles - ### - ### Julia: sinc(x) = - ### \sin(\pi x) / (\pi x) if x \neq 0, and 1 if x = 0 - ### - @assert xcenter >= xstart - @assert xcenter <= (nx - 1) * Δx + xstart - - if beta === nothing - if kind == :monopole - beta = 4.14 - elseif kind == :dipole - beta = 4.40 - end - end - - radius = npts * Δx - # Assuming x from grid starts at xstart - xh = (xcenter - xstart) / Δx - ix = floor(Int64, xh + 1) - if mod((xcenter - xstart), Δx) == 0.0 - ixsta = ix - npts - ixend = ix + npts - else - ixsta = ix - npts + 1 - ixend = ix + npts - end - x = [xstart + Δx * (i - 1) for i in ixsta:ixend] - indexes = ixsta:ixend - - if kind == :monopole - # interpolating sinc(x) = sin(pi*x)/(pi*x) see Julia definition - intrpsinc = sinc.((x .- xcenter) ./ Δx) # factor 1/Δx ?? - - elseif kind == :dipole - # derivative of sinc - # cosc(x) is the derivative of sinc(x) in Julia - intrpsinc = cosc.((x .- xcenter) ./ Δx) - - else - error("coeffsinc1d(): Wrong argument 'kind'.") - end - # apply Kaiser windowing - kaix = kaiser(x, xcenter, beta, radius) - itpfun = kaix .* intrpsinc - # return also indices of window (as a range) - return itpfun, indexes -end - -##################################################################### - -""" -Compute 2-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. - -# Parameters - - - `xstart`, `zstart`: origin coordinates of the grid - - `Δx`,`Δz` : grid spacing - - `xcenter`, `zcenter`: coordinates of source or receiver point - - `nx`,`nz`: grid size in x and y - - `kind`: vector of symbols :monopole or :dipole, i.e., using sinc or derivative of sinc - - `npts` (optional): half-number of grid points for the window - - `beta` (optional): 'beta' parameter for the Kaiser windowing function -""" -function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter::Real, zcenter::Real, - nx::Int, nz::Int, kind::Vector{Symbol}; - npts::Int64=4, beta::Union{Nothing, Real}=nothing) - - ## Calculate the 2D array of coefficients - xcoe, xidx = coeffsinc1D(xstart, Δx, xcenter, kind[1], nx; npts=npts, beta=beta) - zcoe, zidx = coeffsinc1D(zstart, Δz, zcenter, kind[2], nz; npts=npts, beta=beta) - - function reflectcoeffsinc(coe, idx, nmax) - # - # "Reflect" coefficients past the edge, i.e., mirror and subtract them - # from the internal ones - # - if idx[1] < 1 - # We are before the edge - nab = count(idx .< 1) - # get the "reflected" coefficients - reflcoe = coe[nab:-1:1] - # Create a new set of indices excluding those above the surface - idx = idx[nab+1:end] - # Hicks 2002 Geophysics - # Subtract coefficients past the edge - coe[nab+1:2*nab] .-= reflcoe - # Create a new set of coefficients excluding those above the surface - coe = coe[nab+1:end] - - elseif idx[end] > nmax - # We are past the edge - nab = count(idx .> nmax) - # get the "reflected" coefficients - reflcoe = coe[end:-1:end-nab+1] - # Create a new set of indices excluding those above the surface - idx = idx[1:end-nab] - # Hicks 2002 Geophysics - # Subtract coefficients past the edge - coe[end-2*nab+1:end-nab] .-= reflcoe - # Create a new set of coefficients excluding those above the surface - coe = coe[1:end-nab] - end - - return coe, idx - end - - ## Crop and reflect coefficients if they go beyond model edges [Hicks 2002, Geophysics] - xcoe, xidx = reflectcoeffsinc(xcoe, xidx, nx) - zcoe, zidx = reflectcoeffsinc(zcoe, zidx, nz) - - # tensor product of coeff. in x and z - xzcoeff = zeros(typeof(xcenter), length(xcoe), length(zcoe)) - for j in eachindex(zcoe) - for i in eachindex(xcoe) - xzcoeff[i, j] = xcoe[i] * zcoe[j] - end - end - - return xidx, zidx, xzcoeff -end - -##################################################################### - -##################################################################### diff --git a/src/utils/abstract_types.jl b/src/utils/abstract_types.jl index 42bbcfe..311670e 100644 --- a/src/utils/abstract_types.jl +++ b/src/utils/abstract_types.jl @@ -1,3 +1,25 @@ +abstract type WaveSimulation{T, N} end + +abstract type InputParameters{T, N} end + +abstract type InputBoundaryConditionParameters{T} end + +abstract type MaterialProperties{T, N} end + +abstract type Shot{T} end + +abstract type Sources{T} end + +abstract type Receivers{T} end + +abstract type MomentTensor{T, N} end + +abstract type InterpolationMethod end + +abstract type AbstractMisfit end + +abstract type AbstractRegularization end + abstract type AbstractField{T} end abstract type AbstractGrid{N, T} end diff --git a/src/checks.jl b/src/utils/checks.jl similarity index 97% rename from src/checks.jl rename to src/utils/checks.jl index fbaa3d5..a9a0a1e 100644 --- a/src/checks.jl +++ b/src/utils/checks.jl @@ -25,7 +25,7 @@ function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialPro elseif model isa ElasticIsoCPMLWaveSimulation{T, 2} && # <<<<<---------<<<< matprop isa ElasticIsoMaterialProperties{T, 2} && - tysource <: MomentTensorSources{T, MomentTensor2D{T}} && + tysource <: MomentTensorSources{T, 2, MomentTensor2D{T}} && tyreceiver <: VectorReceivers{T, N} return end diff --git a/src/utils/utils.jl b/src/utils/utils.jl index 202b23a..b4aa50a 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -55,3 +55,195 @@ function distribsrcs(nsrc::Int, nw::Int) grpsrc = UnitRange.(cumsum(grpsizes) .- grpsizes .+ 1, cumsum(grpsizes)) return grpsrc end + +@views function find_nearest_grid_points(model::WaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} + # source time functions + nsrcs = size(positions, 1) # number of sources + ncoos = size(positions, 2) # number of coordinates + # find nearest grid point for each source + idx_positions = zeros(Int, size(positions)) # sources positions (in grid points) + for s in 1:nsrcs + tmp = [positions[s, i] / model.grid.spacing[i] + 1 for i in 1:ncoos] + idx_positions[s, :] .= round.(Int, tmp, RoundNearestTiesUp) + end + return idx_positions +end + + +#################################################################### + +""" +Kaiser windowing function. + +# Parameters + + - `x`: coordinate of points + - `x0`: coordinate of source or receiver point + - `b`: 'b' coefficient + - `r`: cut-off radius +""" +function kaiser(x::Vector, x0::T, b::T, r::T) where {T} + # Kaiser window function + # r is window half with + # Rule of thumb for finite diff.: + # b=4.14 b=6.31 + # r = 4.0*dx + w = zeros(T, length(x)) + for i in 1:length(x) + xcur = x[i] - x0 + if -r <= xcur <= r + den = 1.0 / besseli(0, b) + w[i] = den * besseli(0, b * (sqrt.(1 - (xcur / r)^2))) + else + w[i] = 0.0 + end + end + return w +end + +##################################################################### + +""" +Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. + +# Parameters + + - `xstart`: origin coordinate of the grid + - `Δx`: grid spacing + - `kind`: :monopole or :dipole, i.e., using sinc or derivative of sinc + - `npts` (optional): half-number of grid points for the window + - `beta` (optional): 'beta' parameter for the Kaiser windowing function +""" +function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::Int; + npts::Int64=4, beta::Union{Nothing, Real}=nothing) + ## Coefficients for sinc interpolation + ## in 1D + ## xstart is the x coordinate of first node in the regular grid + ## + ## Rule of thumb for npts==4 [Hicks 2002, Geophysics]: + ## beta=4.14 for monopoles, + ## beta=4.40 for dipoles + ### + ### Julia: sinc(x) = + ### \sin(\pi x) / (\pi x) if x \neq 0, and 1 if x = 0 + ### + @assert xcenter >= xstart + @assert xcenter <= (nx - 1) * Δx + xstart + + if beta === nothing + if kind == :monopole + beta = 4.14 + elseif kind == :dipole + beta = 4.40 + end + end + + radius = npts * Δx + # Assuming x from grid starts at xstart + xh = (xcenter - xstart) / Δx + ix = floor(Int64, xh + 1) + if mod((xcenter - xstart), Δx) == 0.0 + ixsta = ix - npts + ixend = ix + npts + else + ixsta = ix - npts + 1 + ixend = ix + npts + end + x = [xstart + Δx * (i - 1) for i in ixsta:ixend] + indexes = ixsta:ixend + + if kind == :monopole + # interpolating sinc(x) = sin(pi*x)/(pi*x) see Julia definition + intrpsinc = sinc.((x .- xcenter) ./ Δx) # factor 1/Δx ?? + + elseif kind == :dipole + # derivative of sinc + # cosc(x) is the derivative of sinc(x) in Julia + intrpsinc = cosc.((x .- xcenter) ./ Δx) + + else + error("coeffsinc1d(): Wrong argument 'kind'.") + end + # apply Kaiser windowing + kaix = kaiser(x, xcenter, beta, radius) + itpfun = kaix .* intrpsinc + # return also indices of window (as a range) + return itpfun, indexes +end + +##################################################################### + +""" +Compute 2-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. + +# Parameters + + - `xstart`, `zstart`: origin coordinates of the grid + - `Δx`,`Δz` : grid spacing + - `xcenter`, `zcenter`: coordinates of source or receiver point + - `nx`,`nz`: grid size in x and y + - `kind`: vector of symbols :monopole or :dipole, i.e., using sinc or derivative of sinc + - `npts` (optional): half-number of grid points for the window + - `beta` (optional): 'beta' parameter for the Kaiser windowing function +""" +function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter::Real, zcenter::Real, + nx::Int, nz::Int, kind::Vector{Symbol}; + npts::Int64=4, beta::Union{Nothing, Real}=nothing) + + ## Calculate the 2D array of coefficients + xcoe, xidx = coeffsinc1D(xstart, Δx, xcenter, kind[1], nx; npts=npts, beta=beta) + zcoe, zidx = coeffsinc1D(zstart, Δz, zcenter, kind[2], nz; npts=npts, beta=beta) + + function reflectcoeffsinc(coe, idx, nmax) + # + # "Reflect" coefficients past the edge, i.e., mirror and subtract them + # from the internal ones + # + if idx[1] < 1 + # We are before the edge + nab = count(idx .< 1) + # get the "reflected" coefficients + reflcoe = coe[nab:-1:1] + # Create a new set of indices excluding those above the surface + idx = idx[nab+1:end] + # Hicks 2002 Geophysics + # Subtract coefficients past the edge + coe[nab+1:2*nab] .-= reflcoe + # Create a new set of coefficients excluding those above the surface + coe = coe[nab+1:end] + + elseif idx[end] > nmax + # We are past the edge + nab = count(idx .> nmax) + # get the "reflected" coefficients + reflcoe = coe[end:-1:end-nab+1] + # Create a new set of indices excluding those above the surface + idx = idx[1:end-nab] + # Hicks 2002 Geophysics + # Subtract coefficients past the edge + coe[end-2*nab+1:end-nab] .-= reflcoe + # Create a new set of coefficients excluding those above the surface + coe = coe[1:end-nab] + end + + return coe, idx + end + + ## Crop and reflect coefficients if they go beyond model edges [Hicks 2002, Geophysics] + xcoe, xidx = reflectcoeffsinc(xcoe, xidx, nx) + zcoe, zidx = reflectcoeffsinc(zcoe, zidx, nz) + + # tensor product of coeff. in x and z + xzcoeff = zeros(typeof(xcenter), length(xcoe), length(zcoe)) + for j in eachindex(zcoe) + for i in eachindex(xcoe) + xzcoeff[i, j] = xcoe[i] * zcoe[j] + end + end + + return xidx, zidx, xzcoeff +end + +##################################################################### + +##################################################################### diff --git a/src/wrappers.jl b/src/wrappers.jl deleted file mode 100644 index 9e806f6..0000000 --- a/src/wrappers.jl +++ /dev/null @@ -1,329 +0,0 @@ - -####################################################### - -@doc """ - -$(TYPEDSIGNATURES) - -Compute forward simulation using the given input parameters `params` and material properties `matprop` on multiple shots. -Receivers traces are stored in the `Receivers` object for each shot. See also [`Receivers`](@ref). - -Return a vector of snapshots for every shot if snapshotting is enabled. - -See also [`Sources`](@ref), [`Receivers`](@ref). - -# Positional arguments -- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). - -# Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` -- `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. -- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. -""" -function swforward!( - params::InputParameters{T, N}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; - parall::Symbol=:threads, - snapevery::Union{Int, Nothing}=nothing, - infoevery::Union{Int, Nothing}=nothing, - logger::Union{Nothing, AbstractLogger}=nothing -)::Union{Vector{Array{T}}, Nothing} where {T, N} - if logger === nothing - logger = current_logger() - end - return with_logger(logger) do - # Build wavesim - wavesim = build_wavesim(params, matprop; parall=parall, snapevery=snapevery, infoevery=infoevery, gradient=false) - # Solve simulation - run_swforward!(wavesim, matprop, shots) - end -end - -@doc """ - -$(TYPEDSIGNATURES) - -Compute forward simulation using a previously constructed `WaveSimulation` object. -Return a vector of snapshots for every shot if snapshotting is enabled. - -See also [`Sources`](@ref), [`Receivers`](@ref). - -# Positional arguments -- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). - -# Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` -- `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. -- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. - """ -function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T}}, Nothing} where {T, N} - if logger === nothing - logger = current_logger() - end - return with_logger(logger) do - run_swforward!(wavesim, matprop, shots; kwargs...) - end -end - -####################################################### - -@doc """ - -$(TYPEDSIGNATURES) - -Return the misfit w.r.t. observed data by running a forward simulation using the given input parameters `params` and material properties `matprop` on multiple shots. - -# Positional arguments -- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). - -# Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` - -Receivers traces are stored in the `Receivers` object for each shot. - -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). -""" -function swmisfit!( - params::InputParameters{T, N}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; - parall::Symbol=:threads, - misfit::AbstractMisfit=L2Misfit(nothing), - logger::Union{Nothing, AbstractLogger}=nothing -)::T where {T, N} - if logger === nothing - logger = current_logger() - end - return with_logger(logger) do - # Build wavesim - wavesim = build_wavesim(params, matprop; parall=parall, gradient=false) - # Compute misfit - run_swmisfit!(wavesim, matprop, shots; misfit=misfit) - end -end - -@doc """ - -$(TYPEDSIGNATURES) - -Return the misfit w.r.t. observed data by running a forward simulation using the given `WaveSimulation` object as an input. - -# Positional arguments -- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). - -# Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` - -Receivers traces are stored in the `Receivers` object for each shot. - -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). -""" -function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::T where {T, N} - if logger === nothing - logger = current_logger() - end - return with_logger(logger) do - run_swmisfit!(wavesim, matprop, shots; kwargs...) - end -end - -####################################################### - -@doc """ - -$(TYPEDSIGNATURES) - -Compute gradients w.r.t. model parameters using the given input parameters `params` and material parameters `matprop` on multiple shots. - -The `check_freq` parameter controls the checkpoiting frequency for adjoint computation. -If `nothing`, no checkpointing is performed. -If greater than 2, a checkpoint is saved every `check_freq` time step. -The optimal tradeoff value is `check_freq = sqrt(nt)` where `nt` is the number of time steps of the forward simulation. -Bigger values speed up computation at the cost of using more memory. - -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). - -# Positional arguments -- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). - -# Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` -- `check_freq::Union{Int, Nothing} = nothing`: if specified, enables checkpointing and specifies the checkpointing frequency. -- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. -- `compute_misfit::Bool = false`: if true, also computes and return misfit value. -- `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. -- `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. -""" -function swgradient!( - params::InputParameters{T,N}, - matprop::MaterialProperties{T, N}, - shots::Vector{<:Shot{T}}; - parall::Symbol=:threads, - check_freq::Union{Int, Nothing}=nothing, - infoevery::Union{Int, Nothing}=nothing, - compute_misfit::Bool=false, - misfit::AbstractMisfit=L2Misfit(nothing), - smooth_radius::Int=5, - logger::Union{Nothing, AbstractLogger}=nothing -)::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} - if logger === nothing - logger = current_logger() - end - return with_logger(logger) do - # Build wavesim - wavesim = build_wavesim(params, matprop; parall=parall, infoevery=infoevery, gradient=true, check_freq=check_freq, smooth_radius=smooth_radius) - # Solve simulation - run_swgradient!(wavesim, matprop, shots; compute_misfit=compute_misfit, misfit=misfit) - end -end - -@doc """ - -$(TYPEDSIGNATURES) - -Compute gradients w.r.t. model parameters using the *previously* built `WaveSimulation`. This avoids re-initializing and re-allocating several arrays in case of multiple gradient calculations. - -The `check_freq` parameter controls the checkpoiting frequency for adjoint computation. -If `nothing`, no checkpointing is performed. -If greater than 2, a checkpoint is saved every `check_freq` time step. -The optimal tradeoff value is `check_freq = sqrt(nt)` where `nt` is the number of time steps of the forward simulation. -Bigger values speed up computation at the cost of using more memory. - -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). - -# Positional arguments -- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). -- `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). - -# Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` -- `check_freq::Union{Int, Nothing} = nothing`: if specified, enables checkpointing and specifies the checkpointing frequency. -- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. -- `compute_misfit::Bool = false`: if true, also computes and return misfit value. -- `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. -- `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. -""" -function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} - if logger === nothing - logger = current_logger() - end - return with_logger(logger) do - run_swgradient!(wavesim, matprop, shots; kwargs...) - end -end - -####################################################### - -@doc """ - -$(TYPEDSIGNATURES) - -Builds a wave similation based on the input paramters `params` and keyword arguments `kwargs`. - -# Positional arguments -- `params::InputParameters{T,N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - -# Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` -- `gradient::Bool = false`: whether the wave simulation is used for gradients computations. -- `check_freq::Union{<:Int, Nothing} = nothing`: if `gradient = true` and if specified, enables checkpointing and specifies the checkpointing frequency. -- `snapevery::Union{<:Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays (only for forward simulations). -- `infoevery::Union{<:Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. -""" -function build_wavesim(params::InputParameters{T, N}, matprop::MaterialProperties{T, N}; parall::Symbol, kwargs...) where {T, N} - if parall == :threadpersrc - nthr = Threads.nthreads() - wsim = [build_concrete_wavesim(params, matprop, params.boundcond; parall=parall, kwargs...) for _ in 1:nthr] - else - wsim = build_concrete_wavesim(params, matprop, params.boundcond; parall=parall, kwargs...) - end - return wsim -end - -build_concrete_wavesim( - params::InputParametersAcoustic{T,N}, - matprop::VpAcousticCDMaterialProperties{T,N}, - cpmlparams::CPMLBoundaryConditionParameters{T}; - kwargs... -) where {T,N} = AcousticCDCPMLWaveSimulation( - params, - matprop, - cpmlparams; - kwargs... -) - -build_concrete_wavesim( - params::InputParametersAcoustic{T,N}, - matprop::VpRhoAcousticVDMaterialProperties{T,N}, - cpmlparams::CPMLBoundaryConditionParameters; - kwargs... -) where {T,N} = AcousticVDStaggeredCPMLWaveSimulation( - params, - matprop, - cpmlparams; - kwargs... -) - -build_concrete_wavesim( - params::InputParametersElastic{T,N}, - matprop::ElasticIsoMaterialProperties{T,N}, - cpmlparams::CPMLBoundaryConditionParameters; - kwargs... -) where {T,N} = ElasticIsoCPMLWaveSimulation( - params.gridsize, - params.gridspacing, - params.ntimesteps, - params.dt, - matprop, - cpmlparams.halo, - cpmlparams.rcoef; - freetop=cpmlparams.freeboundtop, - kwargs... -) - -####################################################### From f24bb444235bd3450646fac1ddd2e483e2c22715 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 15:43:35 +0200 Subject: [PATCH 058/111] Refactor snapshotting --- src/SeismicWaves.jl | 1 + src/apis/forward.jl | 24 ++-- src/models/acoustic/acou_forward.jl | 28 ++--- src/models/acoustic/acou_models.jl | 124 ++++++++++---------- src/traits/snappable.jl | 2 +- src/utils/abstract_types.jl | 4 +- src/utils/fields.jl | 17 ++- src/utils/snapshotter.jl | 39 +++++++ test/test_snapshotting_constant_density.jl | 128 +++++++++++++++++++++ 9 files changed, 269 insertions(+), 98 deletions(-) create mode 100644 src/utils/snapshotter.jl create mode 100644 test/test_snapshotting_constant_density.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index f2994cd..cb86cd6 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -44,6 +44,7 @@ include("utils/checks.jl") include("utils/fields.jl") include("utils/grids.jl") include("utils/checkpointers.jl") +include("utils/snapshotter.jl") # Shots include("shots/sources.jl") diff --git a/src/apis/forward.jl b/src/apis/forward.jl index cb0fef1..f88d034 100644 --- a/src/apis/forward.jl +++ b/src/apis/forward.jl @@ -62,16 +62,14 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments -- `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` - - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - - otherwise the serial version if set to `:serial` -- `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. -- `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. """ -function swforward!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; - logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Vector{Array{T}}, Nothing} where {T, N} +function swforward!( + wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, + matprop::MaterialProperties{T, N}, + shots::Vector{<:Shot{T}}; + logger::Union{Nothing, AbstractLogger}=nothing, + kwargs... +)::Union{Vector{Dict{Int, Dict{String, <:AbstractField{T}}}}, Nothing} where {T, N} if logger === nothing logger = current_logger() end @@ -87,7 +85,7 @@ end model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; -)::Union{Vector{Array{T}}, Nothing} where {T, N} +)::Union{Vector{Dict{Int, Dict{String, <:AbstractField{T}}}}, Nothing} where {T, N} # Check wavesim consistency @debug "Checking consistency across simulation type, material parameters and source-receiver types" @@ -117,7 +115,7 @@ end # Save shot's snapshots if takesnapshots @info "Saving snapshots" - push!(snapshots_per_shot, Array(model.snapshots)) + push!(snapshots_per_shot, deepcopy(model.snapshotter.snapshots)) end end @@ -132,7 +130,7 @@ end model::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; -)::Union{Vector{Array{T}}, Nothing} where {T, N} +)::Union{Vector{Dict{Int, Dict{String, <:AbstractField{T}}}, Nothing}} where {T, N} nwsim = length(model) nthr = Threads.nthreads() # make sure the number of threads has not changed! @@ -173,7 +171,7 @@ end # Save shot's snapshots if snapenabled(model[w]) @info "Saving snapshots" - push!(snapshots_per_shot[w], copy(model[w].snapshots)) + push!(snapshots_per_shot[w], deepcopy(model.snapshotter.snapshots)) end end end diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index e6be971..238f693 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -48,18 +48,13 @@ end backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 - @info @sprintf( - "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", - it, - model.dt * (it - 1), - maximum(abs.(Array(pcur))) - ) + @info @sprintf("Iteration: %d, simulation time: %g [s]", it, model.dt * (it - 1)) end # Save snapshot - if snapenabled(model) && it % model.snapevery == 0 - @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(pcur)))) - copyto!(model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)], pcur) + if snapenabled(model) && model.snapshotter !== nothing + @info @sprintf("Snapping iteration: %d", it) + savesnapshot!(model.snapshotter, "pcur" => grid.fields["pcur"], it) end end @@ -115,18 +110,15 @@ end backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 - @info @sprintf( - "Iteration: %d, simulation time: %g [s], maximum absolute pressure: %g [Pa]", - it, - model.dt * (it - 1), - maximum(abs.(Array(grid.fields["pcur"].value))) - ) + @info @sprintf("Iteration: %d, simulation time: %g [s]", it, model.dt * (it - 1)) end # Save snapshot - if snapenabled(model) && it % model.snapevery == 0 - @info @sprintf("Snapping iteration: %d, max absolute pressure: %g [Pa]", it, maximum(abs.(Array(grid.fields["pcur"].value)))) - copyto!(model.snapshots[fill(Colon(), N)..., div(it, model.snapevery)], grid.fields["pcur"].value) + # Save snapshot + if snapenabled(model) && model.snapshotter !== nothing + @info @sprintf("Snapping iteration: %d", it) + savesnapshot!(model.snapshotter, "pcur" => grid.fields["pcur"], it) + savesnapshot!(model.snapshotter, "vcur" => grid.fields["vcur"], it) end end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 20cf9bc..18477e9 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -62,12 +62,6 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac dt::T # Computational grid grid::UniformFiniteDifferenceGrid{N, T} - # Gradient computation setup - gradient::Bool - smooth_radius::Int - # Snapshots - snapevery::Union{Int, Nothing} - snapshots::Union{Array{T}, Nothing} # Logging parameters infoevery::Int # Material properties @@ -75,7 +69,11 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients{T, V}} # Checkpointing setup - checkpointer::LinearCheckpointer{T} + checkpointer::Union{Nothing, LinearCheckpointer{T}} + # Smooth radius for gradient + smooth_radius::Int + # Snapshotter setup + snapshotter::Union{Nothing, LinearSnapshotter{T, N, Array{T, N}}} # Parallelization type parall::Symbol @@ -97,7 +95,6 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac gridsize = params.gridsize halo = cpmlparams.halo freetop = cpmlparams.freeboundtop - rcoef = cpmlparams.rcoef # Check numerics @assert nt > 0 "Number of timesteps must be positive!" @assert dt > 0 "Timestep size must be positive!" @@ -168,23 +165,27 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac ) end - # Initialize checkpointer - checkpointer = LinearCheckpointer( - nt, - check_freq === nothing ? 1 : check_freq, - filter(p -> p.first in ["pcur", "ψ", "ξ"], grid.fields), - ["pcur"]; - widths=Dict("pcur" => 2) - ) - # Save first two timesteps - savecheckpoint!(checkpointer, "pcur" => grid.fields["pold"], -1) - savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) - savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], 0) - savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) - - # Initialize snapshots array - snapshots = (snapevery !== nothing ? backend.zeros(T, gridsize..., div(nt, snapevery)) : nothing) - # Check infoevery + if gradient + # Initialize checkpointer + checkpointer = LinearCheckpointer( + nt, + check_freq === nothing ? 1 : check_freq, + filter(p -> p.first in ["pcur", "ψ", "ξ"], grid.fields), + ["pcur"]; + widths=Dict("pcur" => 2) + ) + # Save first two timesteps + savecheckpoint!(checkpointer, "pcur" => grid.fields["pold"], -1) + savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) + savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], 0) + savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) + end + + if snapevery !== nothing + # Initialize snapshotter + snapshotter = LinearSnapshotter{Array{T, N}}(nt, snapevery, filter(p -> p.first in ["pcur"], grid.fields)) + end + if infoevery === nothing infoevery = nt + 2 # never reach it else @@ -197,14 +198,12 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac nt, dt, grid, - gradient, - smooth_radius, - snapevery, - snapshots, infoevery, matprop, cpmlcoeffs, - checkpointer, + gradient ? checkpointer : nothing, + smooth_radius, + snapevery === nothing ? nothing : snapshotter, parall ) end @@ -229,7 +228,9 @@ end @views function reset!(model::AcousticCDCPMLWaveSimulation) reset!(model.grid; except=["fact", "a_pml", "b_pml"]) - reset!(model.checkpointer) + if model.checkpointer !== nothing + reset!(model.checkpointer) + end end ########################################################### @@ -314,12 +315,6 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < dt::T # Computational grid grid::UniformFiniteDifferenceGrid{N, T} - # Gradient computation setup - gradient::Bool - smooth_radius::Int - # Snapshots - snapevery::Union{Int, Nothing} - snapshots::Union{Array{T}, Nothing} # Logging parameters infoevery::Int # Material properties @@ -327,7 +322,11 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < # CPML coefficients cpmlcoeffs::NTuple{N, CPMLCoefficients{T, V}} # Checkpointing setup - checkpointer::LinearCheckpointer{T} + checkpointer::Union{Nothing, LinearCheckpointer{T}} + # Smooth radius for gradient + smooth_radius::Int + # Snapshotter setup + snapshotter::Union{Nothing, LinearSnapshotter{T, N, Array{T, N}}} # Parallelization type parall::Symbol @@ -428,22 +427,27 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < ) end - # Initialize checkpointer - checkpointer = LinearCheckpointer( - nt, - check_freq === nothing ? 1 : check_freq, - filter(p -> p.first in ["pcur", "vcur", "ψ", "ξ"], grid.fields), - ["pcur"]; - widths=Dict("pcur" => 1) - ) - # Save first two timesteps - savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) - savecheckpoint!(checkpointer, "vcur" => grid.fields["vcur"], 0) - savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], 0) - savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) - - # Initialize snapshots array - snapshots = (snapevery !== nothing ? backend.zeros(T, gridsize..., div(nt, snapevery)) : nothing) + if gradient + # Initialize checkpointer + checkpointer = LinearCheckpointer( + nt, + check_freq === nothing ? 1 : check_freq, + filter(p -> p.first in ["pcur", "vcur", "ψ", "ξ"], grid.fields), + ["pcur"]; + widths=Dict("pcur" => 1) + ) + # Save first two timesteps + savecheckpoint!(checkpointer, "pcur" => grid.fields["pcur"], 0) + savecheckpoint!(checkpointer, "vcur" => grid.fields["vcur"], 0) + savecheckpoint!(checkpointer, "ψ" => grid.fields["ψ"], 0) + savecheckpoint!(checkpointer, "ξ" => grid.fields["ξ"], 0) + end + + if snapevery !== nothing + # Initialize snapshotter + snapshotter = LinearSnapshotter{Array{N, T}}(nt, snapevery, filter(p -> p.first in ["pcur", "vcur"], grid.fields)) + end + # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it @@ -457,14 +461,12 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < nt, dt, grid, - gradient, - smooth_radius, - snapevery, - snapshots, infoevery, matprop, cpmlcoeffs, - checkpointer, + gradient ? checkpointer : nothing, + smooth_radius, + snapevery === nothing ? nothing : snapshotter, parall ) end @@ -477,7 +479,9 @@ end @views function reset!(model::AcousticVDStaggeredCPMLWaveSimulation) # Reset computational arrays reset!(model.grid; except=["fact_m0", "fact_m1_stag", "a_pml", "b_pml"]) - reset!(model.checkpointer) + if model.checkpointer !== nothing + reset!(model.checkpointer) + end end ########################################################### diff --git a/src/traits/snappable.jl b/src/traits/snappable.jl index 88a4777..88d3800 100644 --- a/src/traits/snappable.jl +++ b/src/traits/snappable.jl @@ -24,4 +24,4 @@ IsSnappableTrait(::Type{<:WaveSimulation}) = UnSnappable() Check if a model has snapping enabled. """ -snapenabled(model::WaveSimulation) = isa(IsSnappableTrait(model), Snappable) && model.snapevery !== nothing +snapenabled(model::WaveSimulation) = isa(IsSnappableTrait(model), Snappable) && model.snapshotter !== nothing diff --git a/src/utils/abstract_types.jl b/src/utils/abstract_types.jl index 311670e..92a0904 100644 --- a/src/utils/abstract_types.jl +++ b/src/utils/abstract_types.jl @@ -24,4 +24,6 @@ abstract type AbstractField{T} end abstract type AbstractGrid{N, T} end -abstract type AbstractCheckpointer{T} end \ No newline at end of file +abstract type AbstractCheckpointer{T} end + +abstract type AbstractSnapshotter{T, N} end \ No newline at end of file diff --git a/src/utils/fields.jl b/src/utils/fields.jl index 4c7da3a..725b69a 100644 --- a/src/utils/fields.jl +++ b/src/utils/fields.jl @@ -11,23 +11,30 @@ mutable struct MultiConstantField{T, N} <: AbstractField{T} MultiConstantField(value::NTuple{N, T}) where {T, N} = new{T, N}(collect(value)) end -mutable struct MultiVariableField{T, N, A <: AbstractArray{T, N}, V <: Vector{A}} <: AbstractField{T} - value::V +mutable struct MultiVariableField{T, N, A <: AbstractArray{T, N}} <: AbstractField{T} + value::Vector{A} end Base.copyto!(dest::ScalarConstantField, src::ScalarConstantField) = (dest.value = src.value) -Base.copyto!(dest::ScalarVariableField, src::Union{ScalarConstantField, ScalarVariableField}) = (dest.value .= src.value) +Base.copyto!(dest::ScalarVariableField, src::ScalarConstantField) = (dest.value .= src.value) +Base.copyto!(dest::ScalarVariableField, src::ScalarVariableField) = copyto!(dest.value, src.value) Base.copyto!(dest::MultiConstantField, src::Union{ScalarConstantField, MultiConstantField}) = (dest.value .= src.value) Base.copyto!(dest::MultiVariableField, src::ScalarConstantField) = begin for vdest in dest.value vdest .= src.value end end -Base.copyto!(dest::MultiVariableField, src::Union{MultiConstantField, MultiVariableField}) = begin +Base.copyto!(dest::MultiVariableField, src::MultiConstantField) = begin for (vdest, vsrc) in zip(dest.value, src.value) vdest .= vsrc end end +Base.copyto!(dest::MultiVariableField, src::MultiVariableField) = begin + for (vdest, vsrc) in zip(dest.value, src.value) + copyto!(vdest, vsrc) + end +end + setzero!(field::ScalarConstantField{T}) where {T} = (field.value = zero(T); return field) setzero!(field::MultiConstantField{T}) where {T} = (field.value .= zero(T); return field) @@ -44,4 +51,4 @@ Base.zero(::Type{MultiConstantField{T, N}}) where {T, N} = MultiConstantField(nt Base.zero(::ScalarConstantField{T}) where {T} = zero(ScalarConstantField{T}) Base.zero(::MultiConstantField{T, N}) where {T, N} = zero(MultiConstantField{T, N}) Base.zero(field::ScalarVariableField{T, N, A}) where {T, N, A} = ScalarVariableField(zero(field.value)) -Base.zero(field::MultiVariableField{T, N, A, V}) where {T, N, A, V} = MultiVariableField([zero(f) for f in field.value]) \ No newline at end of file +Base.zero(field::MultiVariableField{T, N, A}) where {T, N, A} = MultiVariableField([zero(f) for f in field.value]) \ No newline at end of file diff --git a/src/utils/snapshotter.jl b/src/utils/snapshotter.jl new file mode 100644 index 0000000..b3ce342 --- /dev/null +++ b/src/utils/snapshotter.jl @@ -0,0 +1,39 @@ +struct LinearSnapshotter{T, N, A} <: AbstractSnapshotter{T, N} + nt::Int + snapevery::Int + snapshots::Dict{Int, Dict{String, AbstractField{T}}} + + function LinearSnapshotter{A}( + nt::Int, + snapevery::Int, + snapshotted_fields::Dict{String, AbstractField{T}} + ) where {T, N, A <: AbstractArray{T, N}} + @assert snapevery < nt "Checkpointing frequency must be smaller than the number of timesteps!" + # Preallocate snapshots + snapshots = Dict{Int, Dict{String, Union{ScalarVariableField{T, N, A}, MultiVariableField{T, N, A}}}}() + for it in 1:nt + if it % snapevery == 0 + for (name, field) in snapshotted_fields + if !haskey(snapshots, it) + snapshots[it] = Dict() + end + cfield = copy(convert(A, field.value)) + if typeof(field) <: ScalarVariableField + snapshots[it][name] = ScalarVariableField(cfield) + elseif typeof(field) <: MultiVariableField + snapshots[it][name] = MultiVariableField(cfield) + end + end + end + end + # Preallocate buffers + new{T, N, A}(nt, snapevery, snapshots) + end +end + +function savesnapshot!(snapshotter::LinearSnapshotter{T, N}, field::Pair{String, <:AbstractField{T}}, it::Int) where {T, N} + # Save field in snapshots + if it % snapshotter.snapevery == 0 + copyto!(snapshotter.snapshots[it][field.first], field.second) + end +end diff --git a/test/test_snapshotting_constant_density.jl b/test/test_snapshotting_constant_density.jl new file mode 100644 index 0000000..1bce107 --- /dev/null +++ b/test/test_snapshotting_constant_density.jl @@ -0,0 +1,128 @@ +using Test +using DSP, NumericalIntegration, LinearAlgebra +using CUDA: CUDA +using Logging +using SeismicWaves + +with_logger(ConsoleLogger(stderr, Logging.Warn)) do + test_backends = [:serial, :threads] + # test GPU backend only if CUDA is functional + if @isdefined(CUDA) && CUDA.functional() + push!(test_backends, :GPU) + end + + for parall in test_backends + @testset "Test 1D $(parall) single-shot snapshotting" begin + # velocity setup + c0 = 1000.0 + c0max = 1300.0 + nx = 501 + r = 100 + vel = gaussian_vel_1D(nx, c0, c0max, r) + matprop = VpAcousticCDMaterialProperties(vel) + # numerics + nt = 2000 + dx = 2.5 + lx = (nx - 1) * dx + dt = dx / c0max + halo = 20 + rcoef = 0.0001 + f0 = 5.0 + snapevery = 50 + # wave simulation + params = InputParametersAcoustic(nt, dt, (nx,), (dx,), + CPMLBoundaryConditionParameters(halo, rcoef, false)) + wavesim = build_wavesim(params, matprop; parall=parall, snapevery=snapevery) + + # single source at 100 grid points from CPML boundary + times = collect(range(0.0; step=dt, length=nt)) + xsrc = (halo + 100) * dx + srcs = ScalarSources( + reshape([xsrc], 1, 1), + reshape(rickerstf.(times, 2 / f0, f0), nt, 1), + f0 + ) + # multiple receivers at different distances + nrecs = 4 + dist = 50 + recs = ScalarReceivers( + reshape(xsrc .+ dist .* collect(1:nrecs) .* fill(dx, nrecs), nrecs, 1), + nt + ) + + # compute forward + snaps = swforward!(wavesim, matprop, [ScalarShot(srcs, recs)]) + + @test snaps !== nothing + @test length(snaps) == 1 + @test sort(keys(snaps[1])) == [i for i in snapevery:snapevery:nt] + @test all(s -> !(norm(s["pcur"].value) ≈ 0), [s for (it, s) in snaps[1]]) + kk = sort(keys(snaps[1])) + @test all(it -> !(snaps[1][it[1]]["pcur"].value ≈ snaps[1][it[2]]["pcur"].value), + [(it1, it2) for (it1, it2) in zip(kk[1:end-1], kk[2:end])]) + end + + @testset "Test 1D $(parall) multi-shot snapshotting" begin + # velocity setup + c0 = 1000.0 + c0max = 1300.0 + nx = 501 + r = 100 + vel = gaussian_vel_1D(nx, c0, c0max, r) + matprop = VpAcousticCDMaterialProperties(vel) + # numerics + nt = 2000 + dx = 2.5 + lx = (nx - 1) * dx + dt = dx / c0max + halo = 20 + rcoef = 0.0001 + f0 = 5.0 + snapevery = 50 + # wave simulation + params = InputParametersAcoustic(nt, dt, (nx,), (dx,), + CPMLBoundaryConditionParameters(halo, rcoef, false)) + wavesim = build_wavesim(params, matprop; parall=parall, snapevery=snapevery) + + # single source at 100 grid points from CPML boundary + times = collect(range(0.0; step=dt, length=nt)) + xsrc = (halo + 100) * dx + srcs = ScalarSources( + reshape([xsrc], 1, 1), + reshape(rickerstf.(times, 2 / f0, f0), nt, 1), + f0 + ) + # multiple receivers at different distances + nrecs = 4 + dist = 50 + recs = ScalarReceivers( + reshape(xsrc .+ dist .* collect(1:nrecs) .* fill(dx, nrecs), nrecs, 1), + nt + ) + + # single source at 50 grid points from CPML boundary + times = collect(range(0.0; step=dt, length=nt)) + xsrc = (halo + 50) * dx + srcs2 = ScalarSources( + reshape([xsrc], 1, 1), + reshape(rickerstf.(times, 2 / f0, f0), nt, 1), + f0 + ) + # multiple receivers at different distances + nrecs = 4 + dist = 50 + recs2 = ScalarReceivers( + reshape(xsrc .+ dist .* collect(1:nrecs) .* fill(dx, nrecs), nrecs, 1), + nt + ) + + # compute forward + snaps = swforward!(wavesim, matprop, [ScalarShot(srcs, recs), ScalarShot(srcs2, recs2)]) + + @test snaps !== nothing + @test length(snaps) == 2 + @test sort(keys(snaps[1])) == sort(keys(snaps[2])) + @test all(it -> !(snaps[1][it]["pcur"].value ≈ snaps[2][it]["pcur"].value), [it for it in keys(snaps[2])]) + end + end +end From 9eeecef9320f31409e3bb5c01394b72fed91c62e Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 16:38:01 +0200 Subject: [PATCH 059/111] Fix support for single precision (or even half precision) --- ext/CUDABackendExt.jl | 10 +++++----- src/inversion/misfits/L2Misfit.jl | 16 ++++++++-------- src/models/acoustic/acou_forward.jl | 5 ++--- src/models/acoustic/acou_gradient.jl | 4 ++-- src/models/backend_selection.jl | 24 ++++++++++++------------ src/models/cpmlcoeffs.jl | 22 +++++++++++----------- test/test_forward_constant_density.jl | 24 ++++++++++++++++++++++++ test/utils/setup_models.jl | 23 +++++++++++++++++++++++ 8 files changed, 87 insertions(+), 41 deletions(-) diff --git a/ext/CUDABackendExt.jl b/ext/CUDABackendExt.jl index 689859f..b2b0ceb 100644 --- a/ext/CUDABackendExt.jl +++ b/ext/CUDABackendExt.jl @@ -11,10 +11,10 @@ include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") # Overload backend selection -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU end \ No newline at end of file diff --git a/src/inversion/misfits/L2Misfit.jl b/src/inversion/misfits/L2Misfit.jl index b7e4f52..e5162e7 100644 --- a/src/inversion/misfits/L2Misfit.jl +++ b/src/inversion/misfits/L2Misfit.jl @@ -2,16 +2,16 @@ Base.@kwdef struct L2Misfit <: AbstractMisfit regularization::Union{Nothing, AbstractRegularization} end -function (misfit::L2Misfit)(recs::ScalarReceivers, matprop::MaterialProperties) +function (misfit::L2Misfit)(recs::ScalarReceivers{T}, matprop::MaterialProperties{T}) where {T} # Compute residuals residuals = recs.seismograms - recs.observed # Window residuals using mask - mask = ones(size(residuals, 1)) + mask = ones(T, size(residuals, 1)) if length(recs.windows) > 0 for wnd in recs.windows - mask[wnd.first:wnd.second] .= 2.0 + mask[wnd.first:wnd.second] .= 2 end - mask .-= 1.0 + mask .-= 1 end residuals .= mask .* residuals # Inner product using inverse covariance matrix @@ -23,16 +23,16 @@ function (misfit::L2Misfit)(recs::ScalarReceivers, matprop::MaterialProperties) return msf end -function dχ_du(_::L2Misfit, recs::ScalarReceivers) +function dχ_du(_::L2Misfit, recs::ScalarReceivers{T}) where {T} # Compute residuals residuals = recs.seismograms - recs.observed # Window residuals using mask - mask = ones(size(residuals, 1)) + mask = ones(T, size(residuals, 1)) if length(recs.windows) > 0 for wnd in recs.windows - mask[wnd.first:wnd.second] .= 2.0 + mask[wnd.first:wnd.second] .= 2 end - mask .-= 1.0 + mask .-= 1 end residuals .= mask .* residuals # Multiply with inverse of covariance matrix diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 238f693..f3c7103 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -52,7 +52,7 @@ end end # Save snapshot - if snapenabled(model) && model.snapshotter !== nothing + if snapenabled(model) @info @sprintf("Snapping iteration: %d", it) savesnapshot!(model.snapshotter, "pcur" => grid.fields["pcur"], it) end @@ -114,8 +114,7 @@ end end # Save snapshot - # Save snapshot - if snapenabled(model) && model.snapshotter !== nothing + if snapenabled(model) @info @sprintf("Snapping iteration: %d", it) savesnapshot!(model.snapshotter, "pcur" => grid.fields["pcur"], it) savesnapshot!(model.snapshotter, "vcur" => grid.fields["vcur"], it) diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 9955eb7..c68d5b1 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -86,7 +86,7 @@ swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = # smooth gradient backend.smooth_gradient!(gradient, possrcs, model.smooth_radius) # rescale gradient - gradient .= (2.0 ./ (model.matprop.vp .^ 3)) .* gradient + gradient .= (convert(T, 2.0) ./ (model.matprop.vp .^ 3)) .* gradient # add regularization if needed if misfit.regularization !== nothing gradient .+= dχ_dm(misfit.regularization, model.matprop) @@ -192,7 +192,7 @@ end dχ_dvp, dχ_drho = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) # Rescale gradients with respect to material properties (chain rule) return Dict( - "vp" => .-2.0 .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp + "vp" => .-convert(T, 2.0) .* gradient_m0 ./ (model.matprop.vp .^ 3 .* model.matprop.rho) .+ dχ_dvp, # grad wrt vp "rho" => .-gradient_m0 ./ (model.matprop.vp .^ 2 .* model.matprop.rho .^ 2) .- gradient_m1 ./ model.matprop.rho .+ dχ_drho # grad wrt rho ) end diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index ddb5fa4..b79dc18 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -19,21 +19,21 @@ end ## VD = variable density # Backend selections for AcousticCDCPMLWaveSimulation -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:serial}}) = Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:serial}}) = Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:serial}}) = Acoustic3D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 1}}, ::Type{Val{:serial}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:serial}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 3}}, ::Type{Val{:serial}}) = Acoustic3D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:threads}}) = Acoustic3D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 1}}, ::Type{Val{:threads}}) = Acoustic1D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:threads}}) = Acoustic2D_CD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 3}}, ::Type{Val{:threads}}) = Acoustic3D_CD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:threadpersrc}}) = Acoustic1D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:threadpersrc}}) = Acoustic2D_CD_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Float64, 3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 1}}, ::Type{Val{:threadpersrc}}) = Acoustic1D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:threadpersrc}}) = Acoustic2D_CD_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:AbstractFloat, 3}}, ::Type{Val{:threadpersrc}}) = Acoustic3D_CD_CPML_Serial # Backend selections for AcousticVDStaggeredCPMLWaveSimulation -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Float64, 2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:AbstractFloat, 1}}, ::Type{Val{:threads}}) = Acoustic1D_VD_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads # Backend selections for ElasticIsoWaveSimulation -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{Float64, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 724d0d6..b60c347 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -34,9 +34,9 @@ function compute_CPML_coefficientsAxis!( f0::T ) where {T, V <: AbstractVector{T}} # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) - alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) - npower = 2.0 # CPML power coefficient - d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile + alpha_max = convert(T, π * f0) # CPML α multiplicative factor (half of dominating angular frequency) + npower = convert(T, 2.0) # CPML power coefficient + d0 = convert(T, -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness)) # damping profile a_l, a_r, b_l, b_r = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :startongrd) a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :starthalfgrd) @@ -141,9 +141,9 @@ function calc_Kab_CPML_staggeredgrid( a_right = d_right .* (b_right .- 1.0) ./ (K_right .* (d_right .+ K_right .* alpha_right)) if K_max_pml === nothing - return a_left, a_right, b_left, b_right + return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right) else - return a_left, a_right, b_left, b_right, K_left, K_right + return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right), convert.(T, K_left), convert.(T, K_right) end end @@ -159,11 +159,11 @@ function compute_CPML_coefficients!( f0::T ) where {T, V <: AbstractVector{T}} # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) - alpha_max = π * f0 # CPML α multiplicative factor (half of dominating angular frequency) - npower = 2.0 # CPML power coefficient - d0 = -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness) # damping profile + alpha_max = convert(T, π * f0) # CPML α multiplicative factor (half of dominating angular frequency) + npower = convert(T, 2.0) # CPML power coefficient + d0 = convert(T, -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness)) # damping profile if halo == 0 # fix for thickness == 0 generating NaNs - d0 = 0.0 + d0 = convert(T, 0.0) end a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") @@ -236,9 +236,9 @@ function calc_Kab_CPML( a_right = d_right .* (b_right .- 1.0) ./ (K_right .* (d_right .+ K_right .* alpha_right)) if K_max_pml === nothing - return a_left, a_right, b_left, b_right + return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right) else - return a_left, a_right, b_left, b_right, K_left, K_right + return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right), convert.(T, K_left), convert.(T, K_right) end end diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index 7654cf9..185f98a 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -12,6 +12,30 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do end for parall in test_backends + @testset "Test 1D $(parall) single precision" begin + # constant velocity setup + c0 = 1000.0f0 + nt = 500 + nx = 501 + dx = 2.5f0 + dt = dx / c0 + halo = 0 + rcoef = 1.0f0 + f0 = 5.0f0 + params, shots, vel = setup_constant_vel_1D_CPML_Float32(nt, dt, nx, dx, c0, f0, halo, rcoef) + times, Gc = analytical_solution_constant_vel_1D(c0, dt, nt, shots[1].srcs, shots[1].recs) + + # numerical solution + swforward!(params, vel, shots; parall=parall) + numerical_trace = shots[1].recs.seismograms[:, 1] + + @test numerical_trace isa Vector{Float32} + + @test length(numerical_trace) == length(Gc) == nt + # test integral of absolute difference over time is less then a constant 1% error relative to the peak analytical solution + @test integrate(times, abs.(numerical_trace .- Gc)) <= maximum(abs.(Gc)) * 0.01 * (dt * nt) + end + @testset "Test 1D $(parall) single-source multiple-receivers CPML" begin # velocity setup c0 = 1000.0 diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index abf692e..76f17a1 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -239,3 +239,26 @@ function analytical_solution_constant_vel_3D(c0, dt, nt, srcs, recs) return times, Gc end + +function setup_constant_vel_1D_CPML_Float32(nt, dt, nx, dx, c0, f0, halo, rcoef) + # constant velocity setup + lx = (nx - 1) * dx + vel = VpAcousticCDMaterialProperties(c0 .* ones(Float32, nx)) + # input parameters + params = InputParametersAcoustic(nt, dt, (nx,), (dx,), + CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) + # sources + t0 = 2f0 / f0 + times = convert.(Float32, collect(range(0.0; step=dt, length=nt))) + possrcs = zeros(Float32, 1, 1) + srctf = zeros(Float32, nt, 1) + srctf[:, 1] .= rickerstf.(times, t0, f0) + possrcs[1, :] = [lx / 2f0] + # receivers + posrecs = zeros(Float32, 1, 1) + posrecs[1, :] = [lx / 3f0] + srcs = ScalarSources(possrcs, srctf, f0) + recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(Float32, nt))) + shots = [ScalarShot(; srcs=srcs, recs=recs)] + return params, shots, vel +end \ No newline at end of file From 5b3926341aa2b8f15c74155b680ef1a5e0ef0341 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 16:44:00 +0200 Subject: [PATCH 060/111] Fix union for GPU backend --- ext/CUDABackendExt.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/CUDABackendExt.jl b/ext/CUDABackendExt.jl index b2b0ceb..c92c11a 100644 --- a/ext/CUDABackendExt.jl +++ b/ext/CUDABackendExt.jl @@ -11,10 +11,10 @@ include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") # Overload backend selection -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU end \ No newline at end of file From 29639d3b380f559447b5c9e7907b7f63b3dafde1 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 4 Jul 2024 17:09:05 +0200 Subject: [PATCH 061/111] Rename :GPU to :CUDA and add support for :AMDGPU --- Project.toml | 7 ++++-- .../constant_density/gradient_check_fd.jl | 2 +- .../variable_density/gradient_check_fd.jl | 2 +- ext/SeismicWaves_AMDGPUBackendExt.jl | 20 +++++++++++++++++ ...dExt.jl => SeismicWaves_CUDABackendExt.jl} | 22 +++++++++---------- src/apis/build.jl | 3 ++- src/apis/forward.jl | 3 ++- src/apis/gradient.jl | 6 +++-- src/apis/misfit.jl | 6 +++-- .../backends/Acoustic1D_CD_CPML_AMDGPU.jl | 13 +++++++++++ ...CPML_GPU.jl => Acoustic1D_CD_CPML_CUDA.jl} | 2 +- .../backends/Acoustic1D_VD_CPML_AMDGPU.jl | 15 +++++++++++++ ...CPML_GPU.jl => Acoustic1D_VD_CPML_CUDA.jl} | 2 +- .../backends/Acoustic2D_CD_CPML_AMDGPU.jl | 14 ++++++++++++ ...CPML_GPU.jl => Acoustic2D_CD_CPML_CUDA.jl} | 2 +- .../backends/Acoustic2D_VD_CPML_AMDGPU.jl | 15 +++++++++++++ ...CPML_GPU.jl => Acoustic2D_VD_CPML_CUDA.jl} | 2 +- .../backends/Acoustic3D_CD_CPML_AMDGPU.jl | 14 ++++++++++++ ...CPML_GPU.jl => Acoustic3D_CD_CPML_CUDA.jl} | 2 +- src/models/backend_selection.jl | 2 +- test/Project.toml | 1 + ..._vs_numerical_acoustic_constant_density.jl | 5 ++++- ..._vs_numerical_acoustic_variable_density.jl | 5 ++++- test/test_forward_constant_density.jl | 5 ++++- ...test_gradient_acoustic_constant_density.jl | 5 ++++- ...test_gradient_acoustic_variable_density.jl | 5 ++++- test/test_misfit_acoustic_constant_density.jl | 5 ++++- test/test_snapshotting_constant_density.jl | 5 ++++- 28 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 ext/SeismicWaves_AMDGPUBackendExt.jl rename ext/{CUDABackendExt.jl => SeismicWaves_CUDABackendExt.jl} (54%) create mode 100644 src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl rename src/models/acoustic/backends/{Acoustic1D_CD_CPML_GPU.jl => Acoustic1D_CD_CPML_CUDA.jl} (90%) create mode 100644 src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl rename src/models/acoustic/backends/{Acoustic1D_VD_CPML_GPU.jl => Acoustic1D_VD_CPML_CUDA.jl} (92%) create mode 100644 src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl rename src/models/acoustic/backends/{Acoustic2D_CD_CPML_GPU.jl => Acoustic2D_CD_CPML_CUDA.jl} (90%) create mode 100644 src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl rename src/models/acoustic/backends/{Acoustic2D_VD_CPML_GPU.jl => Acoustic2D_VD_CPML_CUDA.jl} (92%) create mode 100644 src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl rename src/models/acoustic/backends/{Acoustic3D_CD_CPML_GPU.jl => Acoustic3D_CD_CPML_CUDA.jl} (90%) diff --git a/Project.toml b/Project.toml index 4f1c136..546f53c 100644 --- a/Project.toml +++ b/Project.toml @@ -12,17 +12,20 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" [weakdeps] +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" [extensions] -CUDABackendExt = "CUDA" +SeismicWaves_AMDGPUBackendExt = "AMDGPU" +SeismicWaves_CUDABackendExt = "CUDA" [compat] julia = ">=1.9" [extras] +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "CUDA"] +test = ["Test", "CUDA", "AMDGPU"] diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl index c499a90..edacabc 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/constant_density/gradient_check_fd.jl @@ -136,7 +136,7 @@ if length(ARGS) >= 1 if ARGS[1] == "--threads" parall = :threads elseif ARGS[1] == "--GPU" - parall = :GPU + parall = :CUDA devs = devices() if length(devs) >= 1 && length(ARGS) >= 2 device!(parse(Int, ARGS[2])) diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl index 3eeba1c..80e5fc6 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/variable_density/gradient_check_fd.jl @@ -163,7 +163,7 @@ end ######################################################################## # Backend selection -parall = :GPU +parall = :CUDA device!(4) run = true diff --git a/ext/SeismicWaves_AMDGPUBackendExt.jl b/ext/SeismicWaves_AMDGPUBackendExt.jl new file mode 100644 index 0000000..723db9c --- /dev/null +++ b/ext/SeismicWaves_AMDGPUBackendExt.jl @@ -0,0 +1,20 @@ +module SeismicWaves_AMDGPUBackendExt + +using SeismicWaves, AMDGPU +using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimulation, AcousticVDStaggeredCPMLWaveSimulation + +# Include AMDGPU backends +include("../src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl") +include("../src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl") +include("../src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl") +include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl") +include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl") + +# Overload backend selection +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = Acoustic1D_CD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Acoustic2D_CD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:AMDGPU}}) = Acoustic3D_CD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = Acoustic1D_VD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Acoustic2D_VD_CPML_AMDGPU + +end \ No newline at end of file diff --git a/ext/CUDABackendExt.jl b/ext/SeismicWaves_CUDABackendExt.jl similarity index 54% rename from ext/CUDABackendExt.jl rename to ext/SeismicWaves_CUDABackendExt.jl index c92c11a..a997b20 100644 --- a/ext/CUDABackendExt.jl +++ b/ext/SeismicWaves_CUDABackendExt.jl @@ -1,20 +1,20 @@ -module CUDABackendExt +module SeismicWaves_CUDABackendExt using SeismicWaves, CUDA using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimulation, AcousticVDStaggeredCPMLWaveSimulation # Include CUDA backends -include("../src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl") -include("../src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl") -include("../src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl") -include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl") -include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl") +include("../src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl") +include("../src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl") +include("../src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl") +include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl") +include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl") # Overload backend selection -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:GPU}}) = Acoustic3D_CD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:GPU}}) = Acoustic1D_VD_CPML_GPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:GPU}}) = Acoustic2D_VD_CPML_GPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = Acoustic1D_CD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Acoustic2D_CD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:CUDA}}) = Acoustic3D_CD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = Acoustic1D_VD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Acoustic2D_VD_CPML_CUDA end \ No newline at end of file diff --git a/src/apis/build.jl b/src/apis/build.jl index 2730ddc..91302d3 100644 --- a/src/apis/build.jl +++ b/src/apis/build.jl @@ -9,7 +9,8 @@ Builds a wave similation based on the input paramters `params` and keyword argum # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:CUDA` + - the `AMDGPU.jl` GPU backend performing automatic domain decomposition if set to `:AMDGPU` - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` diff --git a/src/apis/forward.jl b/src/apis/forward.jl index f88d034..f984b50 100644 --- a/src/apis/forward.jl +++ b/src/apis/forward.jl @@ -20,7 +20,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref). # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:CUDA` + - the `AMDGPU.jl` GPU backend performing automatic domain decomposition if set to `:AMDGPU` - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` diff --git a/src/apis/gradient.jl b/src/apis/gradient.jl index 6142b01..4252ebe 100644 --- a/src/apis/gradient.jl +++ b/src/apis/gradient.jl @@ -21,7 +21,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:CUDA` + - the `AMDGPU.jl` GPU backend performing automatic domain decomposition if set to `:AMDGPU` - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` @@ -76,7 +77,8 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:CUDA` + - the `AMDGPU.jl` GPU backend performing automatic domain decomposition if set to `:AMDGPU` - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` diff --git a/src/apis/misfit.jl b/src/apis/misfit.jl index 998181b..62a47a8 100644 --- a/src/apis/misfit.jl +++ b/src/apis/misfit.jl @@ -11,7 +11,8 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:CUDA` + - the `AMDGPU.jl` GPU backend performing automatic domain decomposition if set to `:AMDGPU` - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` @@ -52,7 +53,8 @@ Return the misfit w.r.t. observed data by running a forward simulation using the # Keyword arguments - `parall::Symbol = :threads`: controls which backend is used for computation: - - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:GPU` + - the `CUDA.jl` GPU backend performing automatic domain decomposition if set to `:CUDA` + - the `AMDGPU.jl` GPU backend performing automatic domain decomposition if set to `:AMDGPU` - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl new file mode 100644 index 0000000..37284dc --- /dev/null +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl @@ -0,0 +1,13 @@ +module Acoustic1D_CD_CPML_AMDGPU + +using AMDGPU +using ParallelStencil +using ParallelStencil.FiniteDifferences1D +@init_parallel_stencil(package = AMDGPU, ndims = 1, inbound = true) + +include("shared/standard_xPU.jl") +include("shared/correlate_gradient_xPU.jl") +include("shared/acoustic1D_xPU.jl") +include("shared/smooth_gradient_1D.jl") + +end diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl similarity index 90% rename from src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl rename to src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl index 9fa0249..26b826e 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl @@ -1,4 +1,4 @@ -module Acoustic1D_CD_CPML_GPU +module Acoustic1D_CD_CPML_CUDA using CUDA using ParallelStencil diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl new file mode 100644 index 0000000..17b294b --- /dev/null +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl @@ -0,0 +1,15 @@ +module Acoustic1D_VD_CPML_AMDGPU + +using AMDGPU +using ParallelStencil +using ParallelStencil.FiniteDifferences1D +include("shared/fourth_order_FiniteDifferences1D.jl") + +@init_parallel_stencil(package = AMDGPU, ndims = 1, inbounds = true) + +include("shared/standard_xPU.jl") +include("shared/correlate_gradient_xPU.jl") +include("shared/acoustic1D_VD_xPU.jl") +include("shared/smooth_gradient_1D.jl") + +end diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl similarity index 92% rename from src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl rename to src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl index 07f296a..fabe805 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl @@ -1,4 +1,4 @@ -module Acoustic1D_VD_CPML_GPU +module Acoustic1D_VD_CPML_CUDA using CUDA using ParallelStencil diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl new file mode 100644 index 0000000..fb0e476 --- /dev/null +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl @@ -0,0 +1,14 @@ +module Acoustic2D_CD_CPML_AMDGPU + +using AMDGPU +using ParallelStencil +using ParallelStencil.FiniteDifferences2D + +@init_parallel_stencil(package = AMDGPU, ndims = 2, inbounds = true) + +include("shared/standard_xPU.jl") +include("shared/correlate_gradient_xPU.jl") +include("shared/acoustic2D_xPU.jl") +include("shared/smooth_gradient_2D.jl") + +end diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl similarity index 90% rename from src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl rename to src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl index c158a46..85d8f79 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl @@ -1,4 +1,4 @@ -module Acoustic2D_CD_CPML_GPU +module Acoustic2D_CD_CPML_CUDA using CUDA using ParallelStencil diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl new file mode 100644 index 0000000..7117b54 --- /dev/null +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl @@ -0,0 +1,15 @@ +module Acoustic2D_VD_CPML_AMDGPU + +using AMDGPU +using ParallelStencil +using ParallelStencil.FiniteDifferences2D +include("shared/fourth_order_FiniteDifferences2D.jl") + +@init_parallel_stencil(package = AMDGPU, ndims = 2, inbounds = true) + +include("shared/standard_xPU.jl") +include("shared/correlate_gradient_xPU.jl") +include("shared/acoustic2D_VD_xPU.jl") +include("shared/smooth_gradient_2D.jl") + +end diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl similarity index 92% rename from src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl rename to src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl index 92e5ab8..3ccdfc5 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl @@ -1,4 +1,4 @@ -module Acoustic2D_VD_CPML_GPU +module Acoustic2D_VD_CPML_CUDA using CUDA using ParallelStencil diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl new file mode 100644 index 0000000..e52f097 --- /dev/null +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl @@ -0,0 +1,14 @@ +module Acoustic3D_CD_CPML_AMDGPU + +using AMDGPU +using ParallelStencil +using ParallelStencil.FiniteDifferences3D + +@init_parallel_stencil(package = AMDGPU, ndims = 3, inbounds = true) + +include("shared/standard_xPU.jl") +include("shared/correlate_gradient_xPU.jl") +include("shared/acoustic3D_xPU.jl") +include("shared/smooth_gradient_3D.jl") + +end diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl similarity index 90% rename from src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl rename to src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl index e8577fc..c4b53fa 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_GPU.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl @@ -1,4 +1,4 @@ -module Acoustic3D_CD_CPML_GPU +module Acoustic3D_CD_CPML_CUDA using CUDA using ParallelStencil diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index b79dc18..2e3037e 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -8,7 +8,7 @@ function select_backend( wavesim_type::Type{<:WaveSimulation}, ::Type{Val{parall}} ) where {parall} - parasym = [:serial, :threads, :GPU, :threadpersrc] + parasym = [:serial, :threads, :CUDA, :AMDGPU, :threadpersrc] error( "No backend found for model of type $(wavesim_type) and `parall =` $(parall). Argument `parall` must be one of the following symbols: $parasym." ) diff --git a/test/Project.toml b/test/Project.toml index ed1a8ea..c91aeb2 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,4 +1,5 @@ [deps] +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0" CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2" diff --git a/test/test_analytical_vs_numerical_acoustic_constant_density.jl b/test/test_analytical_vs_numerical_acoustic_constant_density.jl index 5b8b3ea..a398ceb 100644 --- a/test/test_analytical_vs_numerical_acoustic_constant_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_constant_density.jl @@ -2,7 +2,10 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() - push!(test_backends, :GPU) + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_analytical_vs_numerical_acoustic_variable_density.jl b/test/test_analytical_vs_numerical_acoustic_variable_density.jl index 043650a..a548efe 100644 --- a/test/test_analytical_vs_numerical_acoustic_variable_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_variable_density.jl @@ -8,7 +8,10 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() - push!(test_backends, :GPU) + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index 185f98a..b750bb8 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -8,7 +8,10 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() - push!(test_backends, :GPU) + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_gradient_acoustic_constant_density.jl b/test/test_gradient_acoustic_constant_density.jl index bc48cc3..cf10cde 100644 --- a/test/test_gradient_acoustic_constant_density.jl +++ b/test/test_gradient_acoustic_constant_density.jl @@ -8,7 +8,10 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() - push!(test_backends, :GPU) + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_gradient_acoustic_variable_density.jl b/test/test_gradient_acoustic_variable_density.jl index 6b90bb9..799952c 100644 --- a/test/test_gradient_acoustic_variable_density.jl +++ b/test/test_gradient_acoustic_variable_density.jl @@ -8,7 +8,10 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() - push!(test_backends, :GPU) + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_misfit_acoustic_constant_density.jl b/test/test_misfit_acoustic_constant_density.jl index ab017bf..ec0f6b0 100644 --- a/test/test_misfit_acoustic_constant_density.jl +++ b/test/test_misfit_acoustic_constant_density.jl @@ -8,7 +8,10 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() - push!(test_backends, :GPU) + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_snapshotting_constant_density.jl b/test/test_snapshotting_constant_density.jl index 1bce107..c9e6371 100644 --- a/test/test_snapshotting_constant_density.jl +++ b/test/test_snapshotting_constant_density.jl @@ -8,7 +8,10 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:serial, :threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() - push!(test_backends, :GPU) + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) end for parall in test_backends From 72f4e0079dba846a1f848c45cbe415d0db56aff4 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 5 Jul 2024 16:02:33 +0200 Subject: [PATCH 062/111] Refactor elastic model --- examples/simple_example_elastic.jl | 30 +- src/SeismicWaves.jl | 2 +- src/apis/build.jl | 11 +- src/apis/forward.jl | 2 +- src/models/acoustic/acou_forward.jl | 2 - src/models/acoustic/acou_models.jl | 9 - src/models/acoustic/acou_params.jl | 4 + .../backends/Elastic2D_Iso_CPML_Serial.jl | 34 +- src/models/elastic/ela_forward.jl | 88 ++--- src/models/elastic/ela_material_properties.jl | 58 --- src/models/elastic/ela_models.jl | 347 +++++++----------- src/models/elastic/ela_params.jl | 4 + src/utils/snapshotter.jl | 10 +- 13 files changed, 215 insertions(+), 386 deletions(-) diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index 37db57c..9034429 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -52,7 +52,7 @@ function exelaprob() ##======================================== # shots definition nshots = 1 - shots = Vector{ScalarShot{Float64}}() #Pair{Sources, Receivers}}() + shots = Vector{MomentTensorShot{Float64, 2, MomentTensor2D{Float64}}}() #Pair{Sources, Receivers}}() for i in 1:nshots # sources definition @@ -79,12 +79,12 @@ function exelaprob() for s in 1:nsrc srcstf[:, s] .= rickerstf.(t, t0, f0) Mxx[s] = 5e10 #1.5e10 #1.5e6 #e20 - Mzz[s] = 3e10 #2.4e10 #1.5e6 #e20 - Mxz[s] = 2e10 #0.89e10 #0.0e6 #e20 + Mzz[s] = 5e10 #2.4e10 #1.5e6 #e20 + Mxz[s] = 0 #0.89e10 #0.0e6 #e20 end srcs = MomentTensorSources(possrcs, srcstf, - MomentTensor2D(; Mxx=Mxx, Mzz=Mzz, Mxz=Mxz), + [MomentTensor2D(; Mxx=Mxx[s], Mzz=Mzz[s], Mxz=Mxz[s]) for s in 1:nsrc], f0) #srcs = ScalarSources(possrcs, srcstf, f0) @@ -214,12 +214,12 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) xsrc = shots[1].srcs.positions[:, 1] ysrc = shots[1].srcs.positions[:, 2] - vxsnap = snapsh[1][1] - vzsnap = snapsh[1][2] + vxsnap = [snapsh[1][kk]["v"].value[1] for kk in sort(keys(snapsh[1]))] + vzsnap = [snapsh[1][kk]["v"].value[2] for kk in sort(keys(snapsh[1]))] @show size(vxsnap), size(vzsnap) - curvx = Observable(vxsnap[:, :, 1]) - curvz = Observable(vzsnap[:, :, 1]) + curvx = Observable(vxsnap[1]) + curvz = Observable(vzsnap[1]) @show typeof(curvx), size(curvx[]) vp = sqrt.((matprop.λ + 2 .* matprop.μ) ./ matprop.ρ) @@ -248,7 +248,9 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) ax1 = Axis(fig[1, 1]; aspect=DataAspect(), xlabel="x [m]", ylabel="z [m]") #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) - vmax = max(abs.(extrema(vxsnap))...) + extx = extrema.([vxsnap[i] for i in 1:length(vxsnap)]) + extx = map(p -> max(abs(p[1]), abs(p[2])), extx) + vmax = max(extx...) vminmax = scalamp .* (-vmax, vmax) hm = heatmap!(ax1, xgrd, ygrd, curvx; colormap=cmapwavefield, colorrange=vminmax) #,alpha=0.7) @@ -263,7 +265,9 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) ax2 = Axis(fig[2, 1]; aspect=DataAspect(), xlabel="x [m]", ylabel="z [m]") #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) - vmax = max(abs.(extrema(vzsnap))...) + extx = extrema.([vzsnap[i] for i in 1:length(vzsnap)]) + extx = map(p -> max(abs(p[1]), abs(p[2])), extx) + vmax = max(extx...) vminmax = scalamp .* (-vmax, vmax) hm = heatmap!(ax2, xgrd, ygrd, curvz; colormap=cmapwavefield, colorrange=vminmax) #,alpha=0.7) @@ -289,11 +293,11 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) display(fig) ##===================================== - nframes = size(vxsnap, 3) + nframes = length(vxsnap) function updatefunction(curax1, curax2, vxsnap, vzsnap, it) - cvx = vxsnap[:, :, it] - cvz = vzsnap[:, :, it] + cvx = vxsnap[it] + cvz = vzsnap[it] curax1.title = "Vx, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" curax2.title = "Vz, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" return cvx, cvz diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index cb86cd6..092a8ba 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -66,8 +66,8 @@ include("models/acoustic/acou_init_bc.jl") # Elastic include("models/elastic/ela_abstract_types.jl") -include("models/elastic/ela_material_properties.jl") include("models/elastic/ela_params.jl") +include("models/elastic/ela_material_properties.jl") include("models/elastic/ela_models.jl") include("models/elastic/ela_forward.jl") #include("models/elastic/ela_gradient.jl") diff --git a/src/apis/build.jl b/src/apis/build.jl index 91302d3..6d2cb67 100644 --- a/src/apis/build.jl +++ b/src/apis/build.jl @@ -56,17 +56,12 @@ build_concrete_wavesim( build_concrete_wavesim( params::InputParametersElastic{T,N}, matprop::ElasticIsoMaterialProperties{T,N}, - cpmlparams::CPMLBoundaryConditionParameters; + cpmlparams::CPMLBoundaryConditionParameters{T}; kwargs... ) where {T,N} = ElasticIsoCPMLWaveSimulation( - params.gridsize, - params.gridspacing, - params.ntimesteps, - params.dt, + params, matprop, - cpmlparams.halo, - cpmlparams.rcoef; - freetop=cpmlparams.freeboundtop, + cpmlparams; kwargs... ) diff --git a/src/apis/forward.jl b/src/apis/forward.jl index f984b50..3ad5ab9 100644 --- a/src/apis/forward.jl +++ b/src/apis/forward.jl @@ -36,7 +36,7 @@ function swforward!( snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, logger::Union{Nothing, AbstractLogger}=nothing -)::Union{Vector{Array{T}}, Nothing} where {T, N} +)::Union{Vector{Dict{Int, Dict{String, <:AbstractField{T}}}}, Nothing} where {T, N} if logger === nothing logger = current_logger() end diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index f3c7103..360326e 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -53,7 +53,6 @@ end # Save snapshot if snapenabled(model) - @info @sprintf("Snapping iteration: %d", it) savesnapshot!(model.snapshotter, "pcur" => grid.fields["pcur"], it) end end @@ -115,7 +114,6 @@ end # Save snapshot if snapenabled(model) - @info @sprintf("Snapping iteration: %d", it) savesnapshot!(model.snapshotter, "pcur" => grid.fields["pcur"], it) savesnapshot!(model.snapshotter, "vcur" => grid.fields["vcur"], it) end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 18477e9..2e153f5 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -95,10 +95,6 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac gridsize = params.gridsize halo = cpmlparams.halo freetop = cpmlparams.freeboundtop - # Check numerics - @assert nt > 0 "Number of timesteps must be positive!" - @assert dt > 0 "Timestep size must be positive!" - # Check BDC parameters @assert halo >= 0 "CPML halo size must be non-negative!" ns_cpml = freetop ? gridsize[1:(end-1)] : gridsize @@ -348,11 +344,6 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < gridsize = params.gridsize halo = cpmlparams.halo freetop = cpmlparams.freeboundtop - rcoef = cpmlparams.rcoef - # Check numerics - @assert nt > 0 "Number of timesteps must be positive!" - @assert dt > 0 "Timestep size must be positive!" - # Check BDC parameters @assert halo >= 0 "CPML halo size must be non-negative!" ns_cpml = freetop ? gridsize[1:(end-1)] : gridsize diff --git a/src/models/acoustic/acou_params.jl b/src/models/acoustic/acou_params.jl index cb8a2b3..3413ae7 100644 --- a/src/models/acoustic/acou_params.jl +++ b/src/models/acoustic/acou_params.jl @@ -26,6 +26,10 @@ struct InputParametersAcoustic{T, N} <: InputParameters{T, N} boundcond::InputBoundaryConditionParameters{T} ) where {T, N} @assert N <= 3 "Dimensionality must be less than or equal to 3!" + @assert all(gridsize .> 0) "All numbers of grid points must be positive!" + @assert all(gridspacing .> 0) "All grid spacings must be positive!" + @assert ntimesteps > 0 "Number of timesteps must be positive!" + @assert dt > 0 "Timestep size must be positive!" new{T, N}(ntimesteps, dt, gridsize, gridspacing, boundcond) end end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 2a19dec..5610280 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -437,14 +437,15 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, dt = model.dt nx, nz = model.grid.size[1:2] halo = model.cpmlparams.halo + grid = model.grid - vx = model.velpartic.vx - vz = model.velpartic.vz - σxx = model.stress.σxx - σzz = model.stress.σzz - σxz = model.stress.σxz + vx, vz = grid.fields["v"].value + σxx, σzz, σxz = grid.fields["σ"].value - psi = model.ψ + ψ_∂σxx∂x, ψ_∂σxz∂x = grid.fields["ψ_∂σ∂x"].value + ψ_∂σzz∂z, ψ_∂σxz∂z = grid.fields["ψ_∂σ∂z"].value + ψ_∂vx∂x, ψ_∂vz∂x = grid.fields["ψ_∂v∂x"].value + ψ_∂vx∂z, ψ_∂vz∂z = grid.fields["ψ_∂v∂z"].value a_x = cpmlcoeffs[1].a a_x_half = cpmlcoeffs[1].a_h @@ -456,12 +457,11 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, b_z = cpmlcoeffs[2].b b_z_half = cpmlcoeffs[2].b_h - λ_ihalf = matprop.λ_ihalf - ρ = matprop.ρ - ρ_ihalf_jhalf = matprop.ρ_ihalf_jhalf - μ = matprop.μ - μ_ihalf = matprop.μ_ihalf - μ_jhalf = matprop.μ_jhalf + ρ = grid.fields["ρ"].value + ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value + λ_ihalf = grid.fields["λ_ihalf"].value + μ_ihalf = grid.fields["μ_ihalf"].value + μ_jhalf = grid.fields["μ_jhalf"].value # @show size(vx),size(vz) # @show size(σxx),size(σzz),size(σxz) @@ -474,11 +474,11 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, factz = 1.0 / (24.0 * dz) # update velocity vx - update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, psi.ψ_∂σxx∂x, psi.ψ_∂σxz∂z, + update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x, b_z, a_x, a_z, freetop) # update velocity vz - update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, psi.ψ_∂σxz∂x, - psi.ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, + ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # inject sources (external body force) #inject_bodyforce_sources!(vx,vz,fx,fz,srctf_bk, dt, possrcs_bk,it) @@ -486,12 +486,12 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, # update stresses σxx and σzz update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ_ihalf, μ_ihalf, - psi.ψ_∂vx∂x, psi.ψ_∂vz∂z, + ψ_∂vx∂x, ψ_∂vz∂z, b_x_half, b_z, a_x_half, a_z, freetop) # update stress σxz update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_jhalf, b_x, b_z_half, - psi.ψ_∂vx∂z, psi.ψ_∂vz∂x, a_x, a_z_half, freetop) + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) # inject sources (moment tensor type of internal force) inject_momten_sources2D!(σxx, σzz, σxz, Mxx_bk, Mzz_bk, Mxz_bk, srctf_bk, dt, diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 56ddf87..3945ccf 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -5,10 +5,6 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound ::CPMLBoundaryCondition, model::ElasticIsoCPMLWaveSimulation{T, 2}, shot::MomentTensorShot{T, 2, MomentTensor2D{T}} - # possrcs::Matrix{<:Int}, - # posrecs::Matrix{<:Int}, - # srctf, - # recs ) where {T} # scale source time function, etc. @@ -16,59 +12,47 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound # possrcs = find_nearest_grid_points(model, shot.srcs.positions) # posrecs = find_nearest_grid_points(model, shot.recs.positions) - if N == 2 - # interpolation coefficients for sources - srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.srcs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - # interpolation coefficients for receivers - reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - elseif N == 3 - error("swforward_1shot!(): Elastic 3D not yet implemented!") - end + # interpolation coefficients for sources + srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, + shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for receivers + reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, + shot.recs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) # source time function srctf = shot.srcs.tf # moment tensors momtens = shot.srcs.momtens + # Get computational grid and backend + backend = select_backend(typeof(model), model.parall) + # Numerics nt = model.nt # Wrap sources and receivers arrays - - # possrcs_bk = model.backend.Data.Array(possrcs) - # posrecs_bk = model.backend.Data.Array(posrecs) - - srccoeij_bk = model.backend.Data.Array(srccoeij) - srccoeval_bk = model.backend.Data.Array(srccoeval) - reccoeij_bk = model.backend.Data.Array(reccoeij) - reccoeval_bk = model.backend.Data.Array(reccoeval) - - srctf_bk = model.backend.Data.Array(srctf) - traces_bk = model.backend.Data.Array(shot.recs.seismograms) - - if N == 2 - ## ONLY 2D for now!!! - Mxx_bk = model.backend.Data.Array(momtens.Mxx) - Mzz_bk = model.backend.Data.Array(momtens.Mzz) - Mxz_bk = model.backend.Data.Array(momtens.Mxz) - elseif N == 3 - error("swforward_1shot!(): Elastic 3D not yet implemented!") - end + srccoeij_bk = backend.Data.Array(srccoeij) + srccoeval_bk = backend.Data.Array(srccoeval) + reccoeij_bk = backend.Data.Array(reccoeij) + reccoeval_bk = backend.Data.Array(reccoeval) + + srctf_bk = backend.Data.Array(srctf) + traces_bk = backend.Data.Array(shot.recs.seismograms) + + ## ONLY 2D for now!!! + nsrcs = length(momtens) + Mxx_bk = backend.Data.Array([momtens[i].Mxx for i in 1:nsrcs]) + Mzz_bk = backend.Data.Array([momtens[i].Mzz for i in 1:nsrcs]) + Mxz_bk = backend.Data.Array([momtens[i].Mxz for i in 1:nsrcs]) # Reset wavesim reset!(model) - # Zeros traces (there is a summation in record_receivers2D!() - traces_bk .= 0.0 # Time loop for it in 1:nt - if N == 2 - # Compute one forward step - model.backend.forward_onestep_CPML!(model, + backend.forward_onestep_CPML!(model, srccoeij_bk, srccoeval_bk, reccoeij_bk, @@ -78,18 +62,6 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound it, Mxx_bk, Mzz_bk, Mxz_bk; save_trace=true) - # # Compute one forward step - # model.backend.forward_onestep_CPML!(model, - # possrcs_bk, - # srctf_bk, - # posrecs_bk, - # traces_bk, - # it, - # Mxx_bk,Mzz_bk,Mxz_bk, - # save_trace=true) - else - error("swforward_1shot!(): Elastic 3D not yet implemented!") - end # Print timestep info if it % model.infoevery == 0 @@ -105,14 +77,8 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound end # Save snapshot - if snapenabled(model) && it % model.snapevery == 0 - #error("Snapshot for elastic not yet implemented...") - @info @sprintf("Snapping iteration: %d", it) - dummyidxs = fill(Colon(), N) - # Vx - model.snapshots[1][dummyidxs..., div(it, model.snapevery)] .= Array(model.velpartic.vx) - # Vz - model.snapshots[2][dummyidxs..., div(it, model.snapevery)] .= Array(model.velpartic.vz) + if snapenabled(model) + savesnapshot!(model.snapshotter, "v" => model.grid.fields["v"], it) end end diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index 9171726..8a72fa9 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -4,61 +4,3 @@ Base.@kwdef struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIsoMaterial μ::Array{T, N} ρ::Array{T, N} end - -# Material properties for 2D simulations -Base.@kwdef struct ElasticIsoMaterialProperties2D{T} <: AbstrElasticIsoMaterialProperties{T, 2} - λ::Array{T, 2} - μ::Array{T, 2} - ρ::Array{T, 2} - λ_ihalf::Array{T, 2} - μ_ihalf::Array{T, 2} - μ_jhalf::Array{T, 2} - ρ_ihalf_jhalf::Array{T, 2} - - # function ElasticIsoMaterialProperties{N}(ρ::Array{T, N}, - # μ::Array{T, N}, - # λ::Array{T, N}) where {N} - - # @assert ndims(λ)==2 - # nx,ny = size(λ) - # tyrho = eltype(λ) - # ρ_ihalf_jhalf = zeros(tyrho,nx-1,ny-1) - # μ_ihalf = zeros(tyrho,nx-1,ny) - # μ_jhalf = zeros(tyrho,nx, ny-1) - # λ_ihalf = zeros(tyrho,nx-1,ny) - # precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; - # harmonicaver_μ=true) - - # return new{N}(λ,μ,ρ,λ_ihalf,μ_ihalf,μ_jhalf,ρ_ihalf_jhalf) - # end -end - -function precomp_elaprop!(matprop::ElasticIsoMaterialProperties2D; harmonicaver_μ=true) - - # function precomp_elaprop2D!(ρ,μ,λ,ρ_ihalf_jhalf,μ_ihalf,μ_jhalf,λ_ihalf ; - # harmonicaver_μ=true) - - #------------------------------------------------------------- - # pre-interpolate properties at half distances between nodes - #------------------------------------------------------------- - # ρ_ihalf_jhalf (nx-1,nz-1) ?? - # arithmetic mean for ρ - @. matprop.ρ_ihalf_jhalf = (matprop.ρ[2:end, 2:end] + matprop.ρ[2:end, 1:end-1] + - matprop.ρ[1:end-1, 2:end] + matprop.ρ[1:end-1, 1:end-1]) / 4.0 - # μ_ihalf (nx-1,nz) ?? - # μ_ihalf (nx,nz-1) ?? - if harmonicaver_μ == true - # harmonic mean for μ - @. matprop.μ_ihalf = 1.0 / (1.0 / matprop.μ[2:end, :] + 1.0 / matprop.μ[1:end-1, :]) - @. matprop.μ_jhalf = 1.0 / (1.0 / matprop.μ[:, 2:end] + 1.0 / matprop.μ[:, 1:end-1]) - else - # arithmetic mean for μ - @. matprop.μ_ihalf = (matprop.μ[2:end, :] + matprop.μ[1:end-1, :]) / 2.0 - @. matprop.μ_jhalf = (matprop.μ[:, 2:end] + matprop.μ[:, 1:end-1]) / 2.0 - end - # λ_ihalf (nx-1,nz) ?? - # arithmetic mean for λ - @. matprop.λ_ihalf = (matprop.λ[2:end, :] + matprop.λ[1:end-1, :]) / 2.0 - - return -end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index c6d5a8e..31624f3 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -41,255 +41,197 @@ function check_numerics( return end -@views function update_matprop!(model::ElasticIsoWaveSimulation{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} +@views function update_matprop!(model::ElasticIsoWaveSimulation{T, 2}, matprop::ElasticIsoMaterialProperties{T, 2}) where {T} # Update material properties - model.matprop.λ .= matprop.λ - model.matprop.μ .= matprop.μ - model.matprop.ρ .= matprop.ρ + copyto!(model.matprop.λ, matprop.λ) + copyto!(model.matprop.μ, matprop.μ) + copyto!(model.matprop.ρ, matprop.ρ) # the following on device? - precomp_elaprop!(model.matprop) - - return + precomp_elaprop!(model) end -########################################################### - -struct Elasticψdomain2D{T <: AbstractFloat} - ψ_∂σxx∂x::Array{T, 2} - ψ_∂σxz∂z::Array{T, 2} - ψ_∂σxz∂x::Array{T, 2} - ψ_∂σzz∂z::Array{T, 2} - ψ_∂vx∂x::Array{T, 2} - ψ_∂vz∂z::Array{T, 2} - ψ_∂vz∂x::Array{T, 2} - ψ_∂vx∂z::Array{T, 2} - - function Elasticψdomain2D(backend, gridsize, halo) - @assert length(gridsize) == 2 - ψ_gridsize = [gridsize...] - - gs1, gs2 = copy(ψ_gridsize), copy(ψ_gridsize) - gs1[1] = 2 * halo - gs2[2] = 2 * halo - - ψ_∂σxx∂x = backend.zeros(T, gs1...) - ψ_∂σxz∂z = backend.zeros(T, gs2...) - ψ_∂σxz∂x = backend.zeros(T, gs1...) - ψ_∂σzz∂z = backend.zeros(T, gs2...) - ψ_∂vx∂x = backend.zeros(T, gs1...) - ψ_∂vz∂z = backend.zeros(T, gs2...) - ψ_∂vz∂x = backend.zeros(T, gs1...) - ψ_∂vx∂z = backend.zeros(T, gs2...) - - T = eltype(ψ_∂σxx∂x) - return new{T}(ψ_∂σxx∂x, - ψ_∂σxz∂z, - ψ_∂σxz∂x, - ψ_∂σzz∂z, - ψ_∂vx∂x, - ψ_∂vz∂z, - ψ_∂vz∂x, - ψ_∂vx∂z) +function precomp_elaprop!(model::ElasticIsoWaveSimulation{T, 2}; harmonicaver_μ=true) where {T} + # Excract fields + ρ, λ, μ = model.grid.fields["ρ"].value, model.grid.fields["λ"].value, model.grid.fields["μ"].value + ρ_ihalf_jhalf = model.grid.fields["ρ_ihalf_jhalf"].value + μ_ihalf = model.grid.fields["μ_ihalf"].value + μ_jhalf = model.grid.fields["μ_jhalf"].value + λ_ihalf = model.grid.fields["λ_ihalf"].value + # Copy from internal matprop + copyto!(ρ, model.matprop.ρ) + copyto!(λ, model.matprop.λ) + copyto!(μ, model.matprop.μ) + #------------------------------------------------------------- + # pre-interpolate properties at half distances between nodes + #------------------------------------------------------------- + # ρ_ihalf_jhalf (nx-1,nz-1) ?? + # arithmetic mean for ρ + @. ρ_ihalf_jhalf = (ρ[2:end,2:end] .+ ρ[2:end, 1:end-1] .+ ρ[1:end-1, 2:end] .+ ρ[1:end-1, 1:end-1]) ./ 4.0 + # μ_ihalf (nx-1,nz) ?? + # μ_ihalf (nx,nz-1) ?? + if harmonicaver_μ == true + # harmonic mean for μ + @. μ_ihalf = 1.0 ./ (1.0 ./ μ[2:end, :] .+ 1.0 ./ μ[1:end-1, :]) + @. μ_jhalf = 1.0 ./ (1.0 ./ μ[:, 2:end] .+ 1.0 ./ μ[:, 1:end-1]) + else + # arithmetic mean for μ + @. μ_ihalf = (μ[2:end, :] + μ[1:end-1, :]) / 2.0 + @. μ_jhalf = (μ[:, 2:end] + μ[:, 1:end-1]) / 2.0 end -end - -struct Velpartic2D{T <: AbstractFloat} - vx::Array{T, 2} - vz::Array{T, 2} -end + # λ_ihalf (nx-1,nz) ?? + # arithmetic mean for λ + @. λ_ihalf = (λ[2:end, :] + λ[1:end-1, :]) / 2.0 -struct Stress2D{T <: AbstractFloat} - σxx::Array{T, 2} - σzz::Array{T, 2} - σxz::Array{T, 2} + return end ############################################################## -struct ElasticIsoCPMLWaveSimulation{T, N} <: ElasticIsoWaveSimulation{T, N} - # Physics - extent::NTuple{N, T} +struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: AbstractVector{T}} <: ElasticIsoWaveSimulation{T, N} + # Parameters + params::InputParametersElastic{T, N} + cpmlparams::CPMLBoundaryConditionParameters{T} # Numerics - gridsize::NTuple{N, Int} - gridspacing::NTuple{N, T} nt::Int dt::T - # BDC and CPML parameters - halo::Int - rcoef::T - freetop::Bool - # Gradient computation setup - gradient::Bool - check_freq::Union{Int, Nothing} - # Snapshots - snapevery::Union{Int, Nothing} - snapshots::Union{Vector{<:Array{T}}, Nothing} + # Computational grid + grid::UniformFiniteDifferenceGrid{N, T} # Logging parameters infoevery::Int # Material properties - matprop::AbstrElasticIsoMaterialProperties{T, N} - # Forward computation arrays - velpartic::Any # 2D: 2 comp, 3D: 3 comp - stress::Any # 2D: 3 arrays, 3D: 6 arrays + matprop::ElasticIsoMaterialProperties{T, N} # CPML coefficients - cpmlcoeffs::Any - ψ::Any - # Gradient computation arrays - adj::Any - ψ_adj::Any - grad::Any + cpmlcoeffs::NTuple{N, CPMLCoefficientsAxis{T, V}} # Checkpointing setup - last_checkpoint::Union{Int, Nothing} - save_buffer::Any - checkpoints::Any - checkpoints_ψ::Any - # Backend - backend::Module + checkpointer::Union{Nothing, LinearCheckpointer{T}} + # Smooth radius for gradient + smooth_radius::Int + # Snapshotter setup + snapshotter::Union{Nothing, LinearSnapshotter{T, N, Array{T, N}}} + # Parallelization type parall::Symbol function ElasticIsoCPMLWaveSimulation( - gridsize::NTuple{N, Int}, - gridspacing::NTuple{N, T}, - nt::Int, - dt::T, + params::InputParametersElastic{T, N}, matprop::ElasticIsoMaterialProperties{T, N}, - halo::Int, - rcoef::T; - parall::Symbol=:serial, - freetop::Bool=true, + cpmlparams::CPMLBoundaryConditionParameters{T}; + parall::Symbol=:threads, gradient::Bool=false, check_freq::Union{Int, Nothing}=nothing, snapevery::Union{Int, Nothing}=nothing, - infoevery::Union{Int, Nothing}=nothing + infoevery::Union{Int, Nothing}=nothing, + smooth_radius::Int=5 ) where {T, N} - # Check numerics - @assert all(gridsize .> 0) "All numbers of grid points must be positive!" - @assert all(gridspacing .> 0) "All grid spacings must be positive!" - @assert nt > 0 "Number of timesteps must be positive!" - @assert dt > 0 "Timestep size must be positive!" - + # Extract params + nt = params.ntimesteps + dt = params.dt + gridspacing = params.gridspacing + gridsize = params.gridsize + halo = cpmlparams.halo + freetop = cpmlparams.freeboundtop # Check BDC parameters @assert halo >= 0 "CPML halo size must be non-negative!" gridsize_cpml = freetop ? gridsize[1:(end-1)] : gridsize @assert all(n -> n >= 2halo + 3, gridsize_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" - # Compute model sizes - extent = gridspacing .* (gridsize .- 1) - # Select backend - backend = select_backend(ElasticIsoCPMLWaveSimulation{T, N}, parall) + backend = select_backend(AcousticCDCPMLWaveSimulation{T, N}, parall) + A = backend.Data.Array{T, N} V = backend.Data.Array{T, 1} - - # Initialize computational arrays - if N == 2 - velpartic = Velpartic2D([backend.zeros(T, gridsize...) for _ in 1:N]...) # vx, vy[, vz] - stress = Stress2D([backend.zeros(T, gridsize...) for _ in 1:(N-1)*3]...) # vx, vy[, vz] - end - - ## - if N == 2 # 2D - ψ = Elasticψdomain2D(backend, gridsize, halo) + # Initialize computational grid + grid = UniformFiniteDifferenceGrid(gridsize, gridspacing) + # Initialize CPML coefficients + cpmlcoeffs = tuple([CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N]...) + + # Populate computational grid + if N==2 + # Stress and velocity + addfield!(grid, "σ" => MultiVariableField( + [backend.zeros(T, gridsize...) for _ in 1:3] + )) + addfield!(grid, "v" => MultiVariableField( + [backend.zeros(T, gridsize...) for _ in 1:2] + )) + # Material properties + addfield!(grid, "λ" => ScalarVariableField( + backend.zeros(T, gridsize...) + )) + addfield!(grid, "μ" => ScalarVariableField( + backend.zeros(T, gridsize...) + )) + addfield!(grid, "ρ" => ScalarVariableField( + backend.zeros(T, gridsize...) + )) + addfield!(grid, "λ_ihalf" => ScalarVariableField( + backend.zeros(T, (gridsize.-[1,0])...) + )) + addfield!(grid, "μ_ihalf" => ScalarVariableField( + backend.zeros(T, (gridsize.-[1,0])...) + )) + addfield!(grid, "μ_jhalf" => ScalarVariableField( + backend.zeros(T, (gridsize.-[0,1])...) + )) + addfield!(grid, "ρ_ihalf_jhalf" => ScalarVariableField( + backend.zeros(T, (gridsize.-1)...) + )) + # CPML memory variables + grds = [gridsize...] + gs1, gs2 = copy(grds), copy(grds) + gs1[1] = 2 * halo + gs2[2] = 2 * halo + addfield!(grid, "ψ_∂σ∂x" => MultiVariableField( + [backend.zeros(T, gs1...) for _ in 1:2] + )) + addfield!(grid, "ψ_∂σ∂z" => MultiVariableField( + [backend.zeros(T, gs2...) for _ in 1:2] + )) + addfield!(grid, "ψ_∂v∂x" => MultiVariableField( + [backend.zeros(T, gs1...) for _ in 1:2] + )) + addfield!(grid, "ψ_∂v∂z" => MultiVariableField( + [backend.zeros(T, gs2...) for _ in 1:2] + )) else error("Only elastic 2D is currently implemented.") end # Initialize CPML coefficients - cpmlcoeffs = [CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N] + cpmlcoeffs = tuple([CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N]...) # Initialize gradient arrays if needed if gradient error("Gradient for elastic calculations not yet implemented!") + end - # # Current gradient array - # curgrad = backend.zeros(T, gridsize...) - # # Adjoint arrays - # adj = backend.zeros(T, gridsize...) - # # Initialize CPML arrays - # ψ_adj = [] - # ξ_adj = [] - # for i in 1:N - # ψ_gridsize = [gridsize...] - # ξ_gridsize = [gridsize...] - # ψ_gridsize[i] = halo + 1 - # ξ_gridsize[i] = halo - # append!(ψ_adj, [backend.zeros(T, ψ_gridsize...), backend.zeros(T, ψ_gridsize...)]) - # append!(ξ_adj, [backend.zeros(T, ξ_gridsize...), backend.zeros(T, ξ_gridsize...)]) - # end - # # Checkpointing setup - # if check_freq !== nothing - # @assert check_freq > 2 "Checkpointing frequency must be bigger than 2!" - # @assert check_freq < nt "Checkpointing frequency must be smaller than the number of timesteps!" - # # Time step of last checkpoint - # last_checkpoint = floor(Int, nt / check_freq) * check_freq - # # Checkpointing arrays - # save_buffer = backend.zeros(T, gridsize..., check_freq + 2) # pressure window buffer - # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints - # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints - # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints - # # Save initial conditions as first checkpoint - # checkpoints[-1] = copy(pold) - # checkpoints[0] = copy(pcur) - # checkpoints_ψ[0] = copy.(ψ) - # checkpoints_ξ[0] = copy.(ξ) - # # Preallocate future checkpoints - # for it in 1:(nt+1) - # if it % check_freq == 0 - # checkpoints[it] = backend.zeros(T, gridsize...) - # checkpoints[it-1] = backend.zeros(T, gridsize...) - # checkpoints_ψ[it] = copy.(ψ) - # checkpoints_ξ[it] = copy.(ξ) - # end - # end - # else # no checkpointing - # last_checkpoint = 0 # simulate a checkpoint at time step 0 (so buffer will start from -1) - # save_buffer = backend.zeros(T, gridsize..., nt + 2) # save all timesteps (from -1 to nt+1 so nt+2) - # checkpoints = Dict{Int, backend.Data.Array}() # pressure checkpoints (will remain empty) - # checkpoints_ψ = Dict{Int, Any}() # ψ arrays checkpoints (will remain empty) - # checkpoints_ξ = Dict{Int, Any}() # ξ arrays checkpoints (will remain empty) - # end - # # Save first 2 timesteps in save buffer - # save_buffer[fill(Colon(), N)..., 1] .= pold - # save_buffer[fill(Colon(), N)..., 2] .= pcur + if snapevery !== nothing + # Initialize snapshotter + snapshotter = LinearSnapshotter{Array{T, N}}(nt, snapevery, Dict("v" => MultiVariableField( + [backend.zeros(T, gridsize...) for _ in 1:N] + ))) end - # Initialize snapshots array - snapshots = (snapevery !== nothing ? [zeros(T, gridsize..., div(nt, snapevery)) for _ in 1:N] : nothing) # Check infoevery if infoevery === nothing infoevery = nt + 2 # never reach it else @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end + - return new{T, N}( - extent, - gridsize, - gridspacing, + return new{T, N, A, V}( + params, + cpmlparams, nt, dt, - halo, - rcoef, - freetop, - gradient, - gradient ? check_freq : nothing, - snapevery, - snapshots, + grid, infoevery, matprop, - velpartic, - stress, cpmlcoeffs, - ψ, - gradient ? adj : nothing, - gradient ? ψ_adj : nothing, - gradient ? grad : nothing, - gradient ? last_checkpoint : nothing, - gradient ? save_buffer : nothing, - gradient ? checkpoints : nothing, - gradient ? checkpoints_ψ : nothing, - backend, + gradient ? checkpointer : nothing, + smooth_radius, + snapevery === nothing ? nothing : snapshotter, parall ) end @@ -300,29 +242,10 @@ end # Specific functions for ElasticIsoCPMLWaveSimulation @views function reset!(model::ElasticIsoCPMLWaveSimulation{T, N}) where {T, N} - # Reset computational arrays - for p in propertynames(model.velpartic) - getfield(model.velpartic, p) .= 0.0 - end - for p in propertynames(model.stress) - getfield(model.stress, p) .= 0.0 - end - for p in propertynames(model.ψ) - getfield(model.ψ, p) .= 0.0 - end - - # Reset gradient arrays - if model.gradient - for p in eachindex(model.adj) - model.adj[p][:] .= 0.0 - end - for p in eachindex(model.grad) - model.grad[p] .= 0.0 - end - for p in propertynames(model.ψ_adj) - getfield(model.ψ_adj, p) .= 0.0 - end + reset!(model.grid; except=["ρ", "λ", "μ", "λ_ihalf", "μ_ihalf", "μ_jhalf", "ρ_ihalf_jhalf"]) + if model.checkpointer !== nothing + reset!(model.checkpointer) end end ########################################################### diff --git a/src/models/elastic/ela_params.jl b/src/models/elastic/ela_params.jl index 84684a5..db7d021 100644 --- a/src/models/elastic/ela_params.jl +++ b/src/models/elastic/ela_params.jl @@ -25,6 +25,10 @@ struct InputParametersElastic{T, N} <: InputParameters{T, N} boundcond::InputBoundaryConditionParameters{T} ) where {T, N} @assert N <= 3 "Dimensionality must be less than or equal to 3!" + @assert all(gridsize .> 0) "All numbers of grid points must be positive!" + @assert all(gridspacing .> 0) "All grid spacings must be positive!" + @assert ntimesteps > 0 "Number of timesteps must be positive!" + @assert dt > 0 "Timestep size must be positive!" new{T, N}(ntimesteps, dt, tuple(gridsize...), tuple(gridspacing...), boundcond) end end \ No newline at end of file diff --git a/src/utils/snapshotter.jl b/src/utils/snapshotter.jl index b3ce342..11d0cf5 100644 --- a/src/utils/snapshotter.jl +++ b/src/utils/snapshotter.jl @@ -1,12 +1,12 @@ struct LinearSnapshotter{T, N, A} <: AbstractSnapshotter{T, N} nt::Int snapevery::Int - snapshots::Dict{Int, Dict{String, AbstractField{T}}} + snapshots::Dict{Int, Dict{String, <:AbstractField{T}}} function LinearSnapshotter{A}( nt::Int, snapevery::Int, - snapshotted_fields::Dict{String, AbstractField{T}} + snapshotted_fields::Dict{String, <:AbstractField{T}} ) where {T, N, A <: AbstractArray{T, N}} @assert snapevery < nt "Checkpointing frequency must be smaller than the number of timesteps!" # Preallocate snapshots @@ -17,11 +17,12 @@ struct LinearSnapshotter{T, N, A} <: AbstractSnapshotter{T, N} if !haskey(snapshots, it) snapshots[it] = Dict() end - cfield = copy(convert(A, field.value)) if typeof(field) <: ScalarVariableField + cfield = copy(convert(A, field.value)) snapshots[it][name] = ScalarVariableField(cfield) elseif typeof(field) <: MultiVariableField - snapshots[it][name] = MultiVariableField(cfield) + cfields = [copy(convert(A, field.value[i])) for i in 1:length(field.value)] + snapshots[it][name] = MultiVariableField(cfields) end end end @@ -34,6 +35,7 @@ end function savesnapshot!(snapshotter::LinearSnapshotter{T, N}, field::Pair{String, <:AbstractField{T}}, it::Int) where {T, N} # Save field in snapshots if it % snapshotter.snapevery == 0 + @info @sprintf("Snapping iteration: %d", it) copyto!(snapshotter.snapshots[it][field.first], field.second) end end From c317758e1ea4102884e25713e7bebd1b50cd9c9c Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 5 Jul 2024 17:46:55 +0200 Subject: [PATCH 063/111] Add PS implementation for elastic 2D iso --- examples/simple_example_elastic.jl | 2 +- ext/SeismicWaves_AMDGPUBackendExt.jl | 2 + ext/SeismicWaves_CUDABackendExt.jl | 2 + src/SeismicWaves.jl | 1 + src/models/backend_selection.jl | 1 + .../backends/Elastic2D_Iso_CPML_AMDGPU.jl | 13 + .../backends/Elastic2D_Iso_CPML_CUDA.jl | 13 + .../backends/Elastic2D_Iso_CPML_Serial.jl | 30 +- .../backends/Elastic2D_Iso_CPML_Threads.jl | 12 + .../backends/shared/elastic2D_iso_xPU.jl | 342 ++++++++++++++++++ .../fourth_order_FiniteDifferences2D.jl | 7 + .../elastic/backends/shared/standard_xPU.jl | 4 + 12 files changed, 405 insertions(+), 24 deletions(-) create mode 100644 src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl create mode 100644 src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl create mode 100644 src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl create mode 100644 src/models/elastic/backends/shared/elastic2D_iso_xPU.jl create mode 100644 src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl create mode 100644 src/models/elastic/backends/shared/standard_xPU.jl diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index 9034429..1fae8a5 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -127,7 +127,7 @@ function exelaprob() snapshots = swforward!(params, matprop, shots; - parall=:serial, + parall=:threads, infoevery=infoevery, snapevery=snapevery) diff --git a/ext/SeismicWaves_AMDGPUBackendExt.jl b/ext/SeismicWaves_AMDGPUBackendExt.jl index 723db9c..fdcf1b0 100644 --- a/ext/SeismicWaves_AMDGPUBackendExt.jl +++ b/ext/SeismicWaves_AMDGPUBackendExt.jl @@ -9,6 +9,7 @@ include("../src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl") include("../src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl") include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl") include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl") +include("../src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl") # Overload backend selection SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = Acoustic1D_CD_CPML_AMDGPU @@ -16,5 +17,6 @@ SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:Acous SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:AMDGPU}}) = Acoustic3D_CD_CPML_AMDGPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = Acoustic1D_VD_CPML_AMDGPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Acoustic2D_VD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Elastic2D_Iso_CPML_AMDGPU end \ No newline at end of file diff --git a/ext/SeismicWaves_CUDABackendExt.jl b/ext/SeismicWaves_CUDABackendExt.jl index a997b20..d37539b 100644 --- a/ext/SeismicWaves_CUDABackendExt.jl +++ b/ext/SeismicWaves_CUDABackendExt.jl @@ -9,6 +9,7 @@ include("../src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl") include("../src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl") include("../src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl") include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl") +include("../src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl") # Overload backend selection SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = Acoustic1D_CD_CPML_CUDA @@ -16,5 +17,6 @@ SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:Acous SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:CUDA}}) = Acoustic3D_CD_CPML_CUDA SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = Acoustic1D_VD_CPML_CUDA SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Acoustic2D_VD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Elastic2D_Iso_CPML_CUDA end \ No newline at end of file diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 092a8ba..571501d 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -104,6 +104,7 @@ include("models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl") include("models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl") # Elastic parallel backends +include("models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl") ## HMC stuff include("HMCseiswaves.jl") diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index 2e3037e..d7e8094 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -37,3 +37,4 @@ select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggere # Backend selections for ElasticIsoWaveSimulation select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:threads}}) = Elastic2D_Iso_CPML_Threads diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl new file mode 100644 index 0000000..7002cc2 --- /dev/null +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl @@ -0,0 +1,13 @@ +module Elastic2D_Iso_CPML_AMDGPU + +using AMDGPU +using ParallelStencil +using ParallelStencil.FiniteDifferences2D + +@init_parallel_stencil(package = AMDGPU, ndims = 2, inbounds = false) + +include("shared/standard_xPU.jl") +include("shared/fourth_order_FiniteDifferences2D.jl") +include("shared/elastic2D_iso_xPU.jl") + +end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl new file mode 100644 index 0000000..817f0ff --- /dev/null +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl @@ -0,0 +1,13 @@ +module Elastic2D_Iso_CPML_CUDA + +using CUDA +using ParallelStencil +using ParallelStencil.FiniteDifferences2D + +@init_parallel_stencil(package = CUDA, ndims = 2, inbounds = false) + +include("shared/standard_xPU.jl") +include("shared/fourth_order_FiniteDifferences2D.jl") +include("shared/elastic2D_iso_xPU.jl") + +end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 5610280..50bf505 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -199,7 +199,7 @@ function update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ih end # vz - for j in 2:nz-2 + for j in 2:nz-2 # TODO maybe typo (2 -> 3) for i in 2:nx-2 # Vz @@ -405,7 +405,8 @@ function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, return end -function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, +function forward_onestep_CPML!( + model::ElasticIsoCPMLWaveSimulation{T, N}, srccoeij_bk::Array{Int}, srccoeval_bk::Array{T}, reccoeij_bk::Array{Int}, @@ -416,22 +417,11 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, Mxx_bk::Vector{T}, Mzz_bk::Vector{T}, Mxz_bk::Vector{T}; - save_trace::Bool=true) where {T, N} - # function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T,N}, - # possrcs_bk::Array{Int,2}, - # srctf_bk::Matrix{T}, - # posrecs_bk::Array{Int,2}, - # traces_bk::Array{T}, - # it::Int, - # Mxx_bk::Vector{T}, - # Mzz_bk::Vector{T}, - # Mxz_bk::Vector{T}; - # save_trace::Bool=true) where {N} - - @assert N == 2 + save_trace::Bool=true +) where {T, N} + # Extract info from grid freetop = model.cpmlparams.freeboundtop cpmlcoeffs = model.cpmlcoeffs - matprop = model.matprop dx = model.grid.spacing[1] dz = model.grid.spacing[2] dt = model.dt @@ -463,13 +453,7 @@ function forward_onestep_CPML!(model::ElasticIsoCPMLWaveSimulation{T, N}, μ_ihalf = grid.fields["μ_ihalf"].value μ_jhalf = grid.fields["μ_jhalf"].value - # @show size(vx),size(vz) - # @show size(σxx),size(σzz),size(σxz) - # @show size(a_x),size(a_x_half) - # @show size(b_x),size(b_x_half) - # error("\nExiting...") - - ## pre-scale coefficients + # Precomputing divisions factx = 1.0 / (24.0 * dx) factz = 1.0 / (24.0 * dz) diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl new file mode 100644 index 0000000..4c3635d --- /dev/null +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl @@ -0,0 +1,12 @@ +module Elastic2D_Iso_CPML_Threads + +using ParallelStencil +using ParallelStencil.FiniteDifferences2D + +@init_parallel_stencil(package = Threads, ndims = 2, inbounds = false) + +include("shared/standard_xPU.jl") +include("shared/fourth_order_FiniteDifferences2D.jl") +include("shared/elastic2D_iso_xPU.jl") + +end diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl new file mode 100644 index 0000000..8ef0654 --- /dev/null +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -0,0 +1,342 @@ +@parallel_indices (i, j) function update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x, b_z, a_x, a_z, freetop) + if freetop && j <= 2 + # σxx derivative only in x so no problem + ∂σxx∂x_bkw = factx * (σxx[i-2, j] - 27.0 * σxx[i-1, j] + 27.0 * σxx[i, j] - σxx[i+1, j]) + # image, mirroring σxz[i,j-2] = -σxz[i,j+1], etc. + #∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) + if j == 1 + # j bwd-> -2 -1|0 1 (mirror -2 and -1) + ∂σxz∂z_bkw = factz * (-σxz[i, j+1] + 27.0 * σxz[i, j] + 27.0 * σxz[i, j] - σxz[i, j+1]) + elseif j == 2 + # j bwd-> -2|-1 0 1 (mirror only -2) + ∂σxz∂z_bkw = factz * (-σxz[i, j] - 27.0 * σxz[i, j-1] + 27.0 * σxz[i, j] - σxz[i, j+1]) + end + # update velocity + vx[i, j] = vx[i, j] + (dt / ρ[i, j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) + end + + if j >= 3 + ∂σxx∂x_bkw = factx * (σxx[i-2, j] - 27.0 * σxx[i-1, j] + 27.0 * σxx[i, j] - σxx[i+1, j]) + ∂σxz∂z_bkw = factz * (σxz[i, j-2] - 27.0 * σxz[i, j-1] + 27.0 * σxz[i, j] - σxz[i, j+1]) + + if i <= halo # + # left boundary + ψ_∂σxx∂x[i, j] = b_x[i] * ψ_∂σxx∂x[i, j] + a_x[i] * ∂σxx∂x_bkw + ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i, j] + elseif i >= nx - halo + 1 + # right boundary + ii = i - (nx - 2 * halo) + ψ_∂σxx∂x[ii, j] = b_x[ii] * ψ_∂σxx∂x[ii, j] + a_x[ii] * ∂σxx∂x_bkw + ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii, j] + end + # y boundaries + if j <= halo && freetop == false + # top boundary + ψ_∂σxz∂z[i, j] = b_z[j] * ψ_∂σxz∂z[i, j] + a_z[j] * ∂σxz∂z_bkw + ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i, j] + elseif j >= nz - halo + 1 + # bottom boundary + jj = j - (nz - 2 * halo) + ψ_∂σxz∂z[i, jj] = b_z[jj] * ψ_∂σxz∂z[i, jj] + a_z[jj] * ∂σxz∂z_bkw + ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i, jj] + end + + # update velocity + vx[i, j] = vx[i, j] + (dt / ρ[i, j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) + end + + return nothing +end + +@parallel_indices (i, j) function update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + if freetop && j <= 2 + # σxz derivative only in x so no problem + ∂σxz∂x_fwd = factx * (σxz[i-1, j] - 27.0 * σxz[i, j] + 27.0 * σxz[i+1, j] - σxz[i+2, j]) + # image, mirroring σzz[i,j-1] = -σxz[i,j+2], etc. + #∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) + if j == 1 + # j fwd-> -1 0| 1 2 (mirror -2 and -1) + ∂σzz∂z_fwd = factz * (-σzz[i, j+2] + 27.0 * σzz[i, j+1] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) + elseif j == 2 + # j fwd-> -1|0 1 2 (mirror only -1) + ∂σzz∂z_fwd = factz * (-σzz[i, j+2] - 27.0 * σzz[i, j] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) + end + # update velocity (ρ has been interpolated in advance) + vz[i, j] = vz[i, j] + (dt / ρ_ihalf_jhalf[i, j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) + end + + # vz + if j >= 3 + # Vz + ∂σxz∂x_fwd = factx * (σxz[i-1, j] - 27.0 * σxz[i, j] + 27.0 * σxz[i+1, j] - σxz[i+2, j]) + ∂σzz∂z_fwd = factz * (σzz[i, j-1] - 27.0 * σzz[i, j] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) + + ##======================= + # C-PML stuff + ##======================= + # x boundaries + if i <= halo + # left boundary + ψ_∂σxz∂x[i, j] = b_x_half[i] * ψ_∂σxz∂x[i, j] + a_x_half[i] * ∂σxz∂x_fwd + ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i, j] + elseif i >= nx - halo + 1 + # right boundary + ii = i - (nx - 2 * halo) + ψ_∂σxz∂x[ii, j] = b_x_half[ii] * ψ_∂σxz∂x[ii, j] + a_x_half[ii] * ∂σxz∂x_fwd + ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[ii, j] + end + # y boundaries + if j <= halo && freetop == false # + 1 + # top boundary + ψ_∂σzz∂z[i, j] = b_z_half[j] * ψ_∂σzz∂z[i, j] + a_z_half[j] * ∂σzz∂z_fwd + ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i, j] + elseif j >= nz - halo + 1 + # bottom boundary + jj = j - (nz - 2 * halo) + ψ_∂σzz∂z[i, jj] = b_z_half[jj] * ψ_∂σzz∂z[i, jj] + a_z_half[jj] * ∂σzz∂z_fwd + ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i, jj] + end + ##======================= + + # update velocity (ρ has been interpolated in advance) + vz[i, j] = vz[i, j] + (dt / ρ_ihalf_jhalf[i, j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) + end + + return nothing +end + +@parallel_indices (i, j) function update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, ψ_∂vx∂x, ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + if freetop == true + # σxx, σzz + # j=1: we are on the free surface! + if j == 1 + # σxx + # vx derivative only in x so no problem + ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) + # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd + ∂vz∂z_bkd = -(1.0 - 2.0 * μ_ihalf[i, j] / λ_ihalf[i, j]) * ∂vx∂x_fwd + # σxx + # σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] - λ_ihalf[i, j] / (λ_ihalf[i, j] + 2 + μ_ihalf[i, j]) + 2 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + # σzz + σzz[i, j] = 0.0 # we are on the free surface! + end + + # j=2: we are just below the surface (1/2) + if j == 2 + # σxx + # vx derivative only in x so no problem + ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) + # zero velocity above the free surface + ∂vz∂z_bkd = factz * (0.0 - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) + # σxx + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i, j] * dt * ∂vz∂z_bkd + # σzz + σzz[i, j] = σzz[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vz∂z_bkd + + λ_ihalf[i, j] * dt * ∂vx∂x_fwd + end + end + + # σxx, σzz + if j >= 3 + # σxx,σzz + ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) + ∂vz∂z_bkd = factz * (vz[i, j-2] - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) + + ##======================= + # C-PML stuff + ##======================= + # x boundaries + if i <= halo + # left boundary + ψ_∂vx∂x[i, j] = b_x_half[i] * ψ_∂vx∂x[i, j] + a_x_half[i] * ∂vx∂x_fwd + ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i, j] + elseif i >= nx - halo + 1 + # right boundary + ii = i - (nx - 2 * halo) + ψ_∂vx∂x[ii, j] = b_x_half[ii] * ψ_∂vx∂x[ii, j] + a_x_half[ii] * ∂vx∂x_fwd + ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[ii, j] + end + # y boundaries + if j <= halo && freetop == false + # top boundary + ψ_∂vz∂z[i, j] = b_z[j] * ψ_∂vz∂z[i, j] + a_z[j] * ∂vz∂z_bkd + ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i, j] + elseif j >= nz - halo + 1 + # bottom boundary + jj = j - (nz - 2 * halo) + ψ_∂vz∂z[i, jj] = b_z[jj] * ψ_∂vz∂z[i, jj] + a_z[jj] * ∂vz∂z_bkd + ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i, jj] + end + ##======================= + # σxx + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i, j] * dt * ∂vz∂z_bkd + + ## derivatives are the same than for σxx + # σzz + σzz[i, j] = σzz[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vz∂z_bkd + + λ_ihalf[i, j] * dt * ∂vx∂x_fwd + end + + return nothing +end + +@parallel_indices (i, j) function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, + freetop) + if freetop + # σxz + if j == 1 + # zero velocity above the free surface + ∂vx∂z_fwd = factz * (0.0 - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) + # vz derivative only in x so no problem + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) + # σxz + σxz[i, j] = σxz[i, j] + μ_jhalf[i, j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) + end + end + + # σxz + if j >= 2 + # σxz + ∂vx∂z_fwd = factz * (vx[i, j-1] - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) + + ##======================= + # C-PML stuff + ##======================= + # x boundaries + if i <= halo + # left boundary + ψ_∂vz∂x[i, j] = b_x[i] * ψ_∂vz∂x[i, j] + a_x[i] * ∂vz∂x_bkd + ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i, j] + elseif i >= nx - halo + 1 + # right boundary + ii = i - (nx - 2 * halo) + ψ_∂vz∂x[ii, j] = b_x[ii] * ψ_∂vz∂x[ii, j] + a_x[ii] * ∂vz∂x_bkd + ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[ii, j] + end + # y boundaries + if j <= halo && freetop == false + # top boundary + ψ_∂vx∂z[i, j] = b_z_half[j] * ψ_∂vx∂z[i, j] + a_z_half[j] * ∂vx∂z_fwd + ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i, j] + elseif j >= nz - halo + 1 + # bottom boundary + jj = j - (nz - 2 * halo) + ψ_∂vx∂z[i, jj] = b_z_half[jj] * ψ_∂vx∂z[i, jj] + a_z_half[jj] * ∂vx∂z_fwd + ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i, jj] + end + ##======================= + + # σxz + σxz[i, j] = σxz[i, j] + μ_jhalf[i, j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) + end + + return nothing +end + +@parallel_indices (p) function inject_momten_sources2D!(σxx, σzz, σxz, Mxx, Mzz, Mxz, srctf_bk, dt, srccoeij_bk, srccoeval_bk, it) + s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] + σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] * dt + + return nothing +end + +@parallel_indices (p) function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) + r, irec, jrec = reccoeij_bk[p, :] + traces_bk[it, 1, r] += vx[irec, jrec] + traces_bk[it, 2, r] += vz[irec, jrec] + + return nothing +end + + +function forward_onestep_CPML!( + model, + srccoeij_bk::Array{Int}, + srccoeval_bk::Array{T}, + reccoeij_bk::Array{Int}, + reccoeval_bk::Array{T}, + srctf_bk::Matrix{T}, + traces_bk::Array{T}, + it::Int, + Mxx_bk::Vector{T}, + Mzz_bk::Vector{T}, + Mxz_bk::Vector{T}; + save_trace::Bool=true +) where {T} + # Extract info from grid + freetop = model.cpmlparams.freeboundtop + cpmlcoeffs = model.cpmlcoeffs + dx = model.grid.spacing[1] + dz = model.grid.spacing[2] + dt = model.dt + nx, nz = model.grid.size[1:2] + halo = model.cpmlparams.halo + grid = model.grid + + vx, vz = grid.fields["v"].value + σxx, σzz, σxz = grid.fields["σ"].value + + ψ_∂σxx∂x, ψ_∂σxz∂x = grid.fields["ψ_∂σ∂x"].value + ψ_∂σzz∂z, ψ_∂σxz∂z = grid.fields["ψ_∂σ∂z"].value + ψ_∂vx∂x, ψ_∂vz∂x = grid.fields["ψ_∂v∂x"].value + ψ_∂vx∂z, ψ_∂vz∂z = grid.fields["ψ_∂v∂z"].value + + a_x = cpmlcoeffs[1].a + a_x_half = cpmlcoeffs[1].a_h + b_x = cpmlcoeffs[1].b + b_x_half = cpmlcoeffs[1].b_h + + a_z = cpmlcoeffs[2].a + a_z_half = cpmlcoeffs[2].a_h + b_z = cpmlcoeffs[2].b + b_z_half = cpmlcoeffs[2].b_h + + ρ = grid.fields["ρ"].value + ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value + λ_ihalf = grid.fields["λ_ihalf"].value + μ_ihalf = grid.fields["μ_ihalf"].value + μ_jhalf = grid.fields["μ_jhalf"].value + + # Precomputing divisions + factx = 1.0 / (24.0 * dx) + factz = 1.0 / (24.0 * dz) + + # update velocity vx + @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, + b_x, b_z, a_x, a_z, freetop) + # update velocity vz + @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, + ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + + # update stresses σxx and σzz + @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, + ψ_∂vx∂x, ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + # update stress σxz + @parallel (3:nx-1, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + + # inject sources (moment tensor type of internal force) + nsrcpts = size(srccoeij_bk, 1) + @parallel (1:nsrcpts) inject_momten_sources2D!(σxx, σzz, σxz, Mxx_bk, Mzz_bk, Mxz_bk, srctf_bk, dt, srccoeij_bk, srccoeval_bk, it) + + # record receivers + if save_trace + nrecpts = size(reccoeij_bk, 1) + @parallel (1:nrecpts) record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) + end + + return +end \ No newline at end of file diff --git a/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl b/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl new file mode 100644 index 0000000..2dce407 --- /dev/null +++ b/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl @@ -0,0 +1,7 @@ +macro d_dx_4th(a, i, j) + return esc(:((-$a[$i+1, $j] + 27.0 * $a[$i, $j] - 27.0 * $a[$i-1, $j] + $a[$i-2, $j]))) +end + +macro d_dy_4th(a, i, j) + return esc(:((-$a[$i, $j+1] + 27.0 * $a[$i, $j] - 27.0 * $a[$i, $j-1] + $a[$i, $j-2]))) +end diff --git a/src/models/elastic/backends/shared/standard_xPU.jl b/src/models/elastic/backends/shared/standard_xPU.jl new file mode 100644 index 0000000..569c7d1 --- /dev/null +++ b/src/models/elastic/backends/shared/standard_xPU.jl @@ -0,0 +1,4 @@ +zeros(T, x...) = @zeros(x..., eltype = T) +ones(T, x...) = @ones(x..., eltype = T) +rand(T, x...) = @rand(x..., eltype = T) +fill(T, x...) = @rand(x..., eltype = T) \ No newline at end of file From c4a6eb007e2a54e2dd7c494e92bba76858e7254b Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 5 Jul 2024 17:55:59 +0200 Subject: [PATCH 064/111] Fix bug --- src/models/elastic/ela_models.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 31624f3..3fd81fd 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -137,7 +137,7 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac @assert all(n -> n >= 2halo + 3, gridsize_cpml) "Number grid points in the dimensions with C-PML boundaries must be at least 2*halo+3 = $(2halo+3)!" # Select backend - backend = select_backend(AcousticCDCPMLWaveSimulation{T, N}, parall) + backend = select_backend(ElasticIsoCPMLWaveSimulation{T, N}, parall) A = backend.Data.Array{T, N} V = backend.Data.Array{T, 1} # Initialize computational grid From edc9cb0b516bc054ef4861576f9e0b97a30fc745 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 5 Jul 2024 17:59:34 +0200 Subject: [PATCH 065/111] Fix backend selection --- ext/SeismicWaves_AMDGPUBackendExt.jl | 2 +- ext/SeismicWaves_CUDABackendExt.jl | 3 +-- src/models/backend_selection.jl | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/SeismicWaves_AMDGPUBackendExt.jl b/ext/SeismicWaves_AMDGPUBackendExt.jl index fdcf1b0..fb961c4 100644 --- a/ext/SeismicWaves_AMDGPUBackendExt.jl +++ b/ext/SeismicWaves_AMDGPUBackendExt.jl @@ -17,6 +17,6 @@ SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:Acous SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:AMDGPU}}) = Acoustic3D_CD_CPML_AMDGPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = Acoustic1D_VD_CPML_AMDGPU SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Acoustic2D_VD_CPML_AMDGPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Elastic2D_Iso_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Elastic2D_Iso_CPML_AMDGPU end \ No newline at end of file diff --git a/ext/SeismicWaves_CUDABackendExt.jl b/ext/SeismicWaves_CUDABackendExt.jl index d37539b..102cd72 100644 --- a/ext/SeismicWaves_CUDABackendExt.jl +++ b/ext/SeismicWaves_CUDABackendExt.jl @@ -17,6 +17,5 @@ SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:Acous SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:CUDA}}) = Acoustic3D_CD_CPML_CUDA SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = Acoustic1D_VD_CPML_CUDA SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Acoustic2D_VD_CPML_CUDA -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Elastic2D_Iso_CPML_CUDA - +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Elastic2D_Iso_CPML_CUDA end \ No newline at end of file diff --git a/src/models/backend_selection.jl b/src/models/backend_selection.jl index d7e8094..2a9f0f3 100644 --- a/src/models/backend_selection.jl +++ b/src/models/backend_selection.jl @@ -36,5 +36,5 @@ select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggere select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:threads}}) = Acoustic2D_VD_CPML_Threads # Backend selections for ElasticIsoWaveSimulation -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial -select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:threads}}) = Elastic2D_Iso_CPML_Threads +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:serial}}) = Elastic2D_Iso_CPML_Serial +select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:AbstractFloat, 2}}, ::Type{Val{:threads}}) = Elastic2D_Iso_CPML_Threads From 5077ac8b3af6c29638aa59c0171cc3eb5ef1317e Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 5 Jul 2024 18:01:12 +0200 Subject: [PATCH 066/111] Fix backend again --- ext/SeismicWaves_AMDGPUBackendExt.jl | 2 +- ext/SeismicWaves_CUDABackendExt.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/SeismicWaves_AMDGPUBackendExt.jl b/ext/SeismicWaves_AMDGPUBackendExt.jl index fb961c4..99f9adc 100644 --- a/ext/SeismicWaves_AMDGPUBackendExt.jl +++ b/ext/SeismicWaves_AMDGPUBackendExt.jl @@ -1,7 +1,7 @@ module SeismicWaves_AMDGPUBackendExt using SeismicWaves, AMDGPU -using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimulation, AcousticVDStaggeredCPMLWaveSimulation +using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimulation, AcousticVDStaggeredCPMLWaveSimulation, ElasticIsoCPMLWaveSimulation # Include AMDGPU backends include("../src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl") diff --git a/ext/SeismicWaves_CUDABackendExt.jl b/ext/SeismicWaves_CUDABackendExt.jl index 102cd72..a03d3e7 100644 --- a/ext/SeismicWaves_CUDABackendExt.jl +++ b/ext/SeismicWaves_CUDABackendExt.jl @@ -1,7 +1,7 @@ module SeismicWaves_CUDABackendExt using SeismicWaves, CUDA -using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimulation, AcousticVDStaggeredCPMLWaveSimulation +using SeismicWaves: CPMLBoundaryCondition, LocalGrid, AcousticCDCPMLWaveSimulation, AcousticVDStaggeredCPMLWaveSimulation, ElasticIsoCPMLWaveSimulation # Include CUDA backends include("../src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl") From c32fd92432bc54389dcbe7e67a2d2da92ccc712b Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 5 Jul 2024 18:03:06 +0200 Subject: [PATCH 067/111] Fix shared 2D --- .../backends/shared/elastic2D_iso_xPU.jl | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 8ef0654..b138908 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -261,18 +261,18 @@ end function forward_onestep_CPML!( model, - srccoeij_bk::Array{Int}, - srccoeval_bk::Array{T}, - reccoeij_bk::Array{Int}, - reccoeval_bk::Array{T}, - srctf_bk::Matrix{T}, - traces_bk::Array{T}, + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + traces_bk, it::Int, - Mxx_bk::Vector{T}, - Mzz_bk::Vector{T}, - Mxz_bk::Vector{T}; + Mxx_bk, + Mzz_bk, + Mxz_bk; save_trace::Bool=true -) where {T} +) # Extract info from grid freetop = model.cpmlparams.freeboundtop cpmlcoeffs = model.cpmlcoeffs From 7f1405d6f594dd555f2c1e9bc9ed36a8bc1e951a Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 5 Jul 2024 18:04:57 +0200 Subject: [PATCH 068/111] Fix shared 2D again --- src/models/elastic/backends/shared/elastic2D_iso_xPU.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index b138908..38bc586 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -251,7 +251,7 @@ end end @parallel_indices (p) function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) - r, irec, jrec = reccoeij_bk[p, :] + r, irec, jrec = reccoeij_bk[p, 1], reccoeij_bk[p, 2], reccoeij_bk[p, 3] traces_bk[it, 1, r] += vx[irec, jrec] traces_bk[it, 2, r] += vz[irec, jrec] From 116a7d11a87198addebe002667fb4f810657da53 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 9 Jul 2024 13:54:50 +0200 Subject: [PATCH 069/111] Update README --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3629cfa..7dfce71 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,16 @@ [![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://juliageoph.gitlab.io/SeismicWaves.jl/stable) [![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://juliageoph.gitlab.io/SeismicWaves.jl/dev) -2D and 3D acoustic seismic wave propagation for constant and variable density. Gradients with respect to a misfit function are computed using the adjoint method (also using checkpointing). -Computations can be run in parallel mode on GPUs or threads thanks to the package [`ParallelStencil.jl`](https://github.com/omlins/ParallelStencil.jl). +SeismicWaves.jl is a Julia package for acoustic and elastic wave propagation simulations designed to be used in a Full-Waveform Inversion framework. -Elastic wave propagation is work in progress. +The main features of SeismicWaves.jl are: +- forward wave simulations with multiple sources and receivers (shots) +- 1D, 2D, and 3D acoustic wave simulations (constant density and variable density) +- 2D P-SV elastic wave similations (isotropic) +- gradients of misfit functions with respect to model parameters using the adjoint method (only acoustic simulations supported as of now) +- checkpointing of forward simulations for adjoint method +- device agnostic backends (CPUs or GPUs) thanks to [`ParallelStencil.jl`](https://github.com/omlins/ParallelStencil.jl) ---- +More information and an extensive list of features can be found in the documentation, which you can either find [online](https://juliageoph.gitlab.io/SeismicWaves.jl/stable) or build locally by running the docs/make.jl file. -Warning: **Documentation is currently minimal** (work in progress...). - ---- +Warning: **Documentation is currently minimal**! From 36e3b5e82703ad1c3ef2e6d4cd86cf5e640182ca Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 9 Jul 2024 16:10:20 +0200 Subject: [PATCH 070/111] Better documentation --- README.md | 9 +- docs/Project.toml | 1 + docs/make.jl | 19 +- docs/src/api.md | 47 +++++ docs/src/examples.jl | 167 +++++++++++++++++ docs/src/examples.md | 176 ++++++++++++++++++ docs/src/guide.md | 3 + docs/src/index.md | 29 ++- examples/simple_example_elastic.jl | 10 +- src/SeismicWaves.jl | 16 +- src/apis/forward.jl | 24 ++- src/models/elastic/ela_material_properties.jl | 10 + src/shots/receivers.jl | 1 - src/utils/abstract_types.jl | 64 +++++++ 14 files changed, 531 insertions(+), 45 deletions(-) create mode 100644 docs/src/api.md create mode 100644 docs/src/examples.jl create mode 100644 docs/src/examples.md create mode 100644 docs/src/guide.md diff --git a/README.md b/README.md index 7dfce71..6e476a0 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,19 @@ [![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://juliageoph.gitlab.io/SeismicWaves.jl/stable) [![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://juliageoph.gitlab.io/SeismicWaves.jl/dev) -SeismicWaves.jl is a Julia package for acoustic and elastic wave propagation simulations designed to be used in a Full-Waveform Inversion framework. +SeismicWaves.jl is a Julia package for acoustic and elastic wave propagation simulations designed to be used in a Full-Waveform Inversion framework. It solves different flavours of the wave equation using the finite difference method. The main features of SeismicWaves.jl are: -- forward wave simulations with multiple sources and receivers (shots) +- forward wave simulations with multiple pairs of sources and receivers (shots) - 1D, 2D, and 3D acoustic wave simulations (constant density and variable density) - 2D P-SV elastic wave similations (isotropic) +- free boundary and C-PML absorbing boundary conditions supported - gradients of misfit functions with respect to model parameters using the adjoint method (only acoustic simulations supported as of now) - checkpointing of forward simulations for adjoint method - device agnostic backends (CPUs or GPUs) thanks to [`ParallelStencil.jl`](https://github.com/omlins/ParallelStencil.jl) +This package additionally provides some functions to solve inverse problems using the Hamiltonian Monte Carlo (HMC) method, as part of the [`HMCLab`](https://gitlab.com/JuliaGeoph/HMCLab.jl) framework. + More information and an extensive list of features can be found in the documentation, which you can either find [online](https://juliageoph.gitlab.io/SeismicWaves.jl/stable) or build locally by running the docs/make.jl file. -Warning: **Documentation is currently minimal**! +Warning: **Documentation is currently minimal** and work in progress! diff --git a/docs/Project.toml b/docs/Project.toml index d0d97ed..c05b34b 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,5 +1,6 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" SeismicWaves = "f2cc81fa-a164-11e9-3f65-e3f851c759e3" [compat] diff --git a/docs/make.jl b/docs/make.jl index ddc2fe2..b2ba61c 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,5 +1,17 @@ -using Documenter, SeismicWaves +using SeismicWaves + +import Literate +using Documenter + +println("Converting examples...") + +Literate.markdown( + joinpath(@__DIR__, "src", "examples.jl"), joinpath(@__DIR__, "src"); + credit = false +) + +println("Building documentation...") makedocs(; repo=Remotes.GitLab("JuliaGeoph", "SeismicWaves.jl"), # "https://gitlab.com/JuliaGeoph/SeismicWaves.jl/blob/{commit}{path}#{line}", sitename="SeismicWaves.jl", @@ -7,7 +19,10 @@ makedocs(; repo=Remotes.GitLab("JuliaGeoph", "SeismicWaves.jl"), # "https://gitl authors="Andrea Zunino, Giacomo Aloisi", format=Documenter.HTML(; prettyurls=get(ENV, "CI", nothing) == "true"), pages=[ - "Home" => "index.md" + "Home" => "index.md", + "User guide" => "guide.md", + "Examples" => "examples.md", + "API" => "api.md" ], warnonly=[:missing_docs, :cross_references] ) diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 0000000..47f6dce --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,47 @@ +# [API](@id api) + +## Input parameters +```@autodocs +Modules = [SeismicWaves] +Private = false +Filter = t -> (typeof(t) === DataType || typeof(t) === UnionAll) && (t <: InputParameters) +``` + +## Input BDCs parameters +```@autodocs +Modules = [SeismicWaves] +Private = false +Filter = t -> (typeof(t) === DataType || typeof(t) === UnionAll) && (t <: InputBoundaryConditionParameters) +``` + +## Material properties +```@autodocs +Modules = [SeismicWaves] +Private = false +Filter = t -> (typeof(t) === DataType || typeof(t) === UnionAll) && (t <: MaterialProperties) +``` + +## Shots, sources and receivers +```@autodocs +Modules = [SeismicWaves] +Private = false +Filter = t -> (typeof(t) === DataType || typeof(t) === UnionAll) && (t <: Shot || t <: Sources || t <: Receivers) +``` + +## Solver functions + +```@docs +swforward! +swmisfit! +swgradient! +``` + +## Utilities + +```@docs +build_wavesim +gaussstf +gaussderivstf +rickerstf +``` + diff --git a/docs/src/examples.jl b/docs/src/examples.jl new file mode 100644 index 0000000..2082cd6 --- /dev/null +++ b/docs/src/examples.jl @@ -0,0 +1,167 @@ +# # [Examples](@id examples) + +# ## Acoustic wave simulation example + +using SeismicWaves + +## numerics +nt = 1500 +dt = 0.0012 +dh = 10.0 +t = collect(Float64, range(0.0; step=dt, length=nt)) ## time vector + +## create a velocity model (gradient from top to bottom) +nx = 211 +nz = 120 +velmod = zeros(nx, nz) +for i in 1:nx + for j in 1:nz + velmod[i, j] = 2000.0 + 12.0 * (j - 1) + end +end +matprop = VpAcousticCDMaterialProperties(velmod) + +## shots definition +nshots = 6 +shots = Vector{ScalarShot{Float64}}() +## sources x-position (in grid points) (different for every shot) +ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) +for i in 1:nshots + ## sources definition + nsrc = 1 + possrcs = zeros(1, 2) ## 1 source, 2 dimensions + possrcs[:, 1] .= (ixsrc[i] - 1) * dh ## x-positions in meters + possrcs[:, 2] .= 2 * dh ## y-positions in meters + ## source time functions + srcstf = zeros(nt, nsrc) + for s in 1:nsrc + srcstf[:, s] .= 1000.0 .* rickerstf.(t, 1.20 / 12.0, 12.0) + end + srcs = ScalarSources(possrcs, srcstf, 12.0) + + ## receivers definition + nrecs = 20 + ## receivers x-positions (in grid points) (same for every shot) + ixrec = round.(Int, LinRange(30, nx - 29, nrecs)) + posrecs = zeros(nrecs, 2) ## 20 receivers, 2 dimensions + posrecs[:, 1] .= (ixrec .- 1) .* dh ## x-positions in meters + posrecs[:, 2] .= 2 * dh ## y-positions in meters + recs = ScalarReceivers(posrecs, nt) + + ## add pair as shot + push!(shots, ScalarShot(; srcs=srcs, recs=recs)) ## srcs => recs) +end + +## Input parameters for acoustic simulation +snapevery = 100 +boundcond = CPMLBoundaryConditionParameters(; halo=20, rcoef=0.0001, freeboundtop=true) +params = InputParametersAcoustic(nt, dt, (nx, nz), (dh, dh), boundcond) + +## Compute the seismograms +snapshots = swforward!( + params, + matprop, + shots; + parall=:threads, + snapevery=snapevery +) + +# ## Elastic wave simulation example + +## time stuff +nt = 3000 #1500 +dt = 0.0008 +t = collect(Float64, range(0.0; step=dt, length=nt)) # seconds + +## create a velocity model +nx = 380 ## 211 +nz = 270 ## 120 +dh = 4.5 ## meters + +vp = zeros(nx, nz) +vp[nx÷2+10:end, :] .= 3100.0 +for i in 1:nx + for j in 1:nz + vp[i, j] = 2000.0 + dh * (j - 1) + end +end +vs = vp ./ sqrt(3) + +ρ = 2100.0 * ones(nx, nz) +μ = vs .^ 2 .* ρ ## μ = Vs^2⋅ρ +λ = (vp .^ 2 .* ρ) .- (2 .* μ) ## λ = vp^2 · ρ - 2μ + +matprop = ElasticIsoMaterialProperties(; λ=λ, μ=μ, ρ=ρ) + +## shots definition +nshots = 1 +shots = Vector{MomentTensorShot{Float64, 2, MomentTensor2D{Float64}}}() + +for i in 1:nshots + ## sources definition + nsrc = 1 + ## sources x-position (in grid points) (different for every shot) + if nsrc == 1 + ixsrc = [nx / 2] + else + ixsrc = round.(Int, LinRange(30, nx - 31, nsrc)) + end + possrcs = zeros(nsrc, 2) ## 1 source, 2 dimensions + for s in 1:nsrc + possrcs[s, 1] = (ixsrc[i] - 1) * dh .+ 0.124 ## x-positions in meters + possrcs[s, 2] = (nz / 2) * dh .+ 0.124 ## y-positions in meters + end + + ## source time functions + f0 = 12.0 + t0 = 1.20 / f0 + srcstf = zeros(nt, nsrc) + Mxx = zeros(nsrc) + Mzz = zeros(nsrc) + Mxz = zeros(nsrc) + for s in 1:nsrc + srcstf[:, s] .= rickerstf.(t, t0, f0) + Mxx[s] = 5e10 + Mzz[s] = 5e10 + Mxz[s] = 0.89e10 + end + + srcs = MomentTensorSources( + possrcs, srcstf, + [MomentTensor2D(; Mxx=Mxx[s], Mzz=Mzz[s], Mxz=Mxz[s]) for s in 1:nsrc], + f0 + ) + + ## receivers definition + nrecs = 10 + ## receivers x-positions (in grid points) (same for every shot) + ixrec = round.(Int, LinRange(40, nx - 40, nrecs)) + posrecs = zeros(nrecs, 2) ## 20 receivers, 2 dimensions + posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 ## x-positions in meters + posrecs[:, 2] .= (10) * dh ## y-positions in meters + + ndim = 2 + recs = VectorReceivers(posrecs, nt, ndim) + + ## add pair as shot + push!(shots, MomentTensorShot(; srcs=srcs, recs=recs)) # srcs => recs) +end + +## Input parameters for elastic simulation +snapevery = 5 +infoevery = 100 +freetop = true +halo = 20 +rcoef = 0.0001 +boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=freetop) +params = InputParametersElastic(nt, dt, (nx, nz), (dh, dh), boundcond) + +## Compute the seismograms +snapshots = swforward!( + params, + matprop, + shots; + parall=:threads, + infoevery=infoevery, + snapevery=snapevery +) \ No newline at end of file diff --git a/docs/src/examples.md b/docs/src/examples.md new file mode 100644 index 0000000..916e23f --- /dev/null +++ b/docs/src/examples.md @@ -0,0 +1,176 @@ +```@meta +EditURL = "examples.jl" +``` + +# [Examples](@id examples) + +## Acoustic wave simulation example + +````@example examples +using SeismicWaves + +# numerics +nt = 1500 +dt = 0.0012 +dh = 10.0 +t = collect(Float64, range(0.0; step=dt, length=nt)) ## time vector + +# create a velocity model (gradient from top to bottom) +nx = 211 +nz = 120 +velmod = zeros(nx, nz) +for i in 1:nx + for j in 1:nz + velmod[i, j] = 2000.0 + 12.0 * (j - 1) + end +end +matprop = VpAcousticCDMaterialProperties(velmod) + +# shots definition +nshots = 6 +shots = Vector{ScalarShot{Float64}}() +# sources x-position (in grid points) (different for every shot) +ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) +for i in 1:nshots + # sources definition + nsrc = 1 + possrcs = zeros(1, 2) ## 1 source, 2 dimensions + possrcs[:, 1] .= (ixsrc[i] - 1) * dh ## x-positions in meters + possrcs[:, 2] .= 2 * dh ## y-positions in meters + # source time functions + srcstf = zeros(nt, nsrc) + for s in 1:nsrc + srcstf[:, s] .= 1000.0 .* rickerstf.(t, 1.20 / 12.0, 12.0) + end + srcs = ScalarSources(possrcs, srcstf, 12.0) + + # receivers definition + nrecs = 20 + # receivers x-positions (in grid points) (same for every shot) + ixrec = round.(Int, LinRange(30, nx - 29, nrecs)) + posrecs = zeros(nrecs, 2) ## 20 receivers, 2 dimensions + posrecs[:, 1] .= (ixrec .- 1) .* dh ## x-positions in meters + posrecs[:, 2] .= 2 * dh ## y-positions in meters + recs = ScalarReceivers(posrecs, nt) + + # add pair as shot + push!(shots, ScalarShot(; srcs=srcs, recs=recs)) ## srcs => recs) +end + +# Input parameters for acoustic simulation +snapevery = 100 +boundcond = CPMLBoundaryConditionParameters(; halo=20, rcoef=0.0001, freeboundtop=true) +params = InputParametersAcoustic(nt, dt, (nx, nz), (dh, dh), boundcond) + +# Compute the seismograms +snapshots = swforward!( + params, + matprop, + shots; + parall=:threads, + snapevery=snapevery +) +```` + +## Elastic wave simulation example + +````@example examples +# time stuff +nt = 3000 #1500 +dt = 0.0008 +t = collect(Float64, range(0.0; step=dt, length=nt)) # seconds + +# create a velocity model +nx = 380 ## 211 +nz = 270 ## 120 +dh = 4.5 ## meters + +vp = zeros(nx, nz) +vp[nx÷2+10:end, :] .= 3100.0 +for i in 1:nx + for j in 1:nz + vp[i, j] = 2000.0 + dh * (j - 1) + end +end +vs = vp ./ sqrt(3) + +ρ = 2100.0 * ones(nx, nz) +μ = vs .^ 2 .* ρ ## μ = Vs^2⋅ρ +λ = (vp .^ 2 .* ρ) .- (2 .* μ) ## λ = vp^2 · ρ - 2μ + +matprop = ElasticIsoMaterialProperties(; λ=λ, μ=μ, ρ=ρ) + +# shots definition +nshots = 1 +shots = Vector{MomentTensorShot{Float64, 2, MomentTensor2D{Float64}}}() + +for i in 1:nshots + # sources definition + nsrc = 1 + # sources x-position (in grid points) (different for every shot) + if nsrc == 1 + ixsrc = [nx / 2] + else + ixsrc = round.(Int, LinRange(30, nx - 31, nsrc)) + end + possrcs = zeros(nsrc, 2) ## 1 source, 2 dimensions + for s in 1:nsrc + possrcs[s, 1] = (ixsrc[i] - 1) * dh .+ 0.124 ## x-positions in meters + possrcs[s, 2] = (nz / 2) * dh .+ 0.124 ## y-positions in meters + end + + # source time functions + f0 = 12.0 + t0 = 1.20 / f0 + srcstf = zeros(nt, nsrc) + Mxx = zeros(nsrc) + Mzz = zeros(nsrc) + Mxz = zeros(nsrc) + for s in 1:nsrc + srcstf[:, s] .= rickerstf.(t, t0, f0) + Mxx[s] = 5e10 + Mzz[s] = 5e10 + Mxz[s] = 0.89e10 + end + + srcs = MomentTensorSources( + possrcs, srcstf, + [MomentTensor2D(; Mxx=Mxx[s], Mzz=Mzz[s], Mxz=Mxz[s]) for s in 1:nsrc], + f0 + ) + + # receivers definition + nrecs = 10 + # receivers x-positions (in grid points) (same for every shot) + ixrec = round.(Int, LinRange(40, nx - 40, nrecs)) + posrecs = zeros(nrecs, 2) ## 20 receivers, 2 dimensions + posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 ## x-positions in meters + posrecs[:, 2] .= (10) * dh ## y-positions in meters + + ndim = 2 + recs = VectorReceivers(posrecs, nt, ndim) + + # add pair as shot + push!(shots, MomentTensorShot(; srcs=srcs, recs=recs)) # srcs => recs) +end + +# Input parameters for elastic simulation +snapevery = 5 +infoevery = 100 +freetop = true +halo = 20 +rcoef = 0.0001 +boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=freetop) +params = InputParametersElastic(nt, dt, (nx, nz), (dh, dh), boundcond) + +# Compute the seismograms +snapshots = swforward!( + params, + matprop, + shots; + parall=:threads, + infoevery=infoevery, + snapevery=snapevery +) +```` + diff --git a/docs/src/guide.md b/docs/src/guide.md new file mode 100644 index 0000000..0c4c695 --- /dev/null +++ b/docs/src/guide.md @@ -0,0 +1,3 @@ +# User guide + +TODO \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index 76345f9..be25782 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -3,26 +3,25 @@ EditURL = "https://gitlab.com/JuliaGeoph/SeismicWaves.jl/-/tree/main/docs/src/" ``` -# Contents +# SeismicWaves.jl -```@contents -Pages = ["index.md"] -Depth = 4 -``` +SeismicWaves.jl is a Julia package for acoustic and elastic wave propagation simulations designed to be used in a Full-Waveform Inversion framework. It solves different flavours of the wave equation using the finite difference method. -# User guide +The main features of SeismicWaves.jl are: +- forward wave simulations with multiple pairs of sources and receivers (shots) +- 1D, 2D, and 3D acoustic wave simulations (constant density and variable density) +- 2D P-SV elastic wave similations (isotropic) +- free boundary and C-PML absorbing boundary conditions supported +- gradients of misfit functions with respect to model parameters using the adjoint method (only acoustic simulations supported as of now) +- checkpointing of forward simulations for adjoint method +- device agnostic backends (CPUs or GPUs) thanks to [`ParallelStencil.jl`](https://github.com/omlins/ParallelStencil.jl) -**SeismicWaves** is a Julia package for seismic wave propagation using the finite difference method. `SeismicWaves` provides functions to solve the forward problem and the gradient of a misfit functional with respect to model parameters. This package additionally provides some functions to solve inverse problems using the Hamiltonian Monte Carlo (HMC) method, as part of the [`HMCLab`](https://gitlab.com/JuliaGeoph/HMCLab.jl) framework. +More information and an extensive list of features can be found in the documentation, which you can either find [online](https://juliageoph.gitlab.io/SeismicWaves.jl/stable) or build locally by running the docs/make.jl file. +> Warning: **Documentation is currently minimal** and work in progress! -## Public API - -```@autodocs -Modules = [SeismicWaves] -Private = false -``` - - +See the [Examples](@ref examples) for how to use this package! +See the [API](@ref api) for detailed information about the functionalities of this package! diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index 1fae8a5..15064c4 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -11,7 +11,7 @@ function exelaprob() ##======================================== # time stuff - nt = 1500 #1500 + nt = 3000 #1500 dt = 0.0008 t = collect(Float64, range(0.0; step=dt, length=nt)) # seconds #@show dt,(nt-1)*dt @@ -80,7 +80,7 @@ function exelaprob() srcstf[:, s] .= rickerstf.(t, t0, f0) Mxx[s] = 5e10 #1.5e10 #1.5e6 #e20 Mzz[s] = 5e10 #2.4e10 #1.5e6 #e20 - Mxz[s] = 0 #0.89e10 #0.0e6 #e20 + Mxz[s] = 0.89e10 #0.89e10 #0.0e6 #e20 end srcs = MomentTensorSources(possrcs, srcstf, @@ -96,7 +96,7 @@ function exelaprob() ixrec = round.(Int, LinRange(40, nx - 40, nrecs)) posrecs = zeros(nrecs, 2) # 20 receivers, 2 dimensions posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 # x-positions in meters - posrecs[:, 2] .= (nz / 4) * dh .- 0.312 # (nz/2) * dh # y-positions in meters + posrecs[:, 2] .= (10) * dh # (nz/2) * dh # y-positions in meters ndim = 2 recs = VectorReceivers(posrecs, nt, ndim) @@ -303,7 +303,7 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) return cvx, cvz end - fps = 15 + fps = 30 # live plot # for j in 1:1 @@ -330,7 +330,7 @@ global_logger(info_logger) par, matprop, shots, snapsh = exelaprob() -snapanimate(par, matprop, shots, snapsh) +snapanimate(par, matprop, shots, snapsh; scalamp=0.02) fig = plotstuff(par, matprop, shots) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 571501d..79558d0 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -1,6 +1,3 @@ -""" -Module for generalized wave propagation solvers. -""" module SeismicWaves using LinearAlgebra @@ -12,21 +9,22 @@ using DocStringExtensions # main struct for wave simulation export WaveSimulation -export build_wavesim # input parameters -export InputParametersAcoustic, InputParametersElastic +export InputParameters, InputParametersAcoustic, InputParametersElastic # boundary conditions +export InputBoundaryConditionParameters export CPMLBoundaryConditionParameters, ReflectiveBoundaryConditionParameters # material properties +export MaterialProperties export VpAcousticCDMaterialProperties, VpRhoAcousticVDMaterialProperties export ElasticIsoMaterialProperties # export sources, receivers and shots -export ScalarShot, MomentTensorShot -export ScalarSources, MomentTensorSources +export Shot, ScalarShot, MomentTensorShot +export Sources, ScalarSources, MomentTensorSources export MomentTensor2D, MomentTensor3D -export ScalarReceivers, VectorReceivers +export Receivers, ScalarReceivers, VectorReceivers # forward, misfit and gradient functions -export swforward!, swmisfit!, swgradient! +export build_wavesim, swforward!, swmisfit!, swgradient! # source time functions export gaussstf, gaussderivstf, rickerstf diff --git a/src/apis/forward.jl b/src/apis/forward.jl index 3ad5ab9..2870bdd 100644 --- a/src/apis/forward.jl +++ b/src/apis/forward.jl @@ -7,15 +7,15 @@ $(TYPEDSIGNATURES) Compute forward simulation using the given input parameters `params` and material properties `matprop` on multiple shots. -Receivers traces are stored in the `Receivers` object for each shot. See also [`Receivers`](@ref). +Receivers traces are stored in the receivers for each shot. -Return a vector of snapshots for every shot if snapshotting is enabled. +Return a vector of `Dict` containing for each shot the snapshots of the fields computed in the simulation for each timestep. -See also [`Sources`](@ref), [`Receivers`](@ref). +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). # Positional arguments -- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation type. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation type. - `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments @@ -27,6 +27,7 @@ See also [`Sources`](@ref), [`Receivers`](@ref). - otherwise the serial version if set to `:serial` - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. +- `logger::Union{Nothing, AbstractLogger} = nothing`: if specified, uses the given `logger` object to print logs, otherwise it uses the logger returned from `current_logger()`. """ function swforward!( params::InputParameters{T, N}, @@ -53,17 +54,20 @@ end $(TYPEDSIGNATURES) Compute forward simulation using a previously constructed `WaveSimulation` object. -Return a vector of snapshots for every shot if snapshotting is enabled. +Receivers traces are stored in the receivers for each shot. -See also [`Sources`](@ref), [`Receivers`](@ref). +Return a vector of `Dict` containing for each shot the snapshots of the fields computed in the simulation for each timestep. + +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). # Positional arguments -- `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. -- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). +- `wavesim`: wave simulation object containing all required information to run the simulation. +- `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation type. - `shots::Vector{<:Shot{T}}`: a vector whose elements are `Shot` structures. Each shot contains information about both source(s) and receiver(s). # Keyword arguments - """ +- `logger::Union{Nothing, AbstractLogger} = nothing`: if specified, uses the given `logger` object to print logs, otherwise it uses the logger returned from `current_logger()`. +""" function swforward!( wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index 8a72fa9..ef9d6b0 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -1,6 +1,16 @@ +@doc """ +$(TYPEDEF) + +Material properties for elastic isotropic simulation. + +$(TYPEDFIELDS) +""" Base.@kwdef struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIsoMaterialProperties{T, N} + "First Lamé parameter" λ::Array{T, N} + "Second Lamé parameter (shear modulus)" μ::Array{T, N} + "Density" ρ::Array{T, N} end diff --git a/src/shots/receivers.jl b/src/shots/receivers.jl index 522a34f..36b4178 100644 --- a/src/shots/receivers.jl +++ b/src/shots/receivers.jl @@ -67,7 +67,6 @@ Type representing a multi-receiver configuration for a wave propagation shot. $(TYPEDFIELDS) """ -# What about using the package ComputedFieldTypes.jl? @computed ... struct VectorReceivers{T, N} <: Receivers{T} "Receiver positions" positions::Matrix{T} diff --git a/src/utils/abstract_types.jl b/src/utils/abstract_types.jl index 92a0904..2ff5a1a 100644 --- a/src/utils/abstract_types.jl +++ b/src/utils/abstract_types.jl @@ -1,15 +1,79 @@ abstract type WaveSimulation{T, N} end +@doc """ + +$(TYPEDEF) + +`InputParameters` is the abstract supertype describing input parameters for wave simulations. + +Currently implemented concrete parameters are [`InputParametersAcoustic`](@ref) and [`InputParametersElastic`](@ref), for acoustic and elasic wave simulation respectively. + +""" abstract type InputParameters{T, N} end + +@doc """ + +$(TYPEDEF) + +`InputBoundaryConditionParameters` is the abstract supertype describing boundary conditions input parameters for wave simulations. + +Currently implemented concrete parameters are [`CPMLBoundaryConditionParameters`](@ref) and [`ReflectiveBoundaryConditionParameters`](@ref). + +""" abstract type InputBoundaryConditionParameters{T} end +@doc """ + +$(TYPEDEF) + +`MaterialProperties` is the abstract supertype describing material properties for wave simulations. It defines which type of wave equation is solved. + +Currently implemented concrete properties are: +- [`VpAcousticCDMaterialProperties`](@ref) for acoustic constant density wave equation +- [`VpRhoAcousticVDMaterialProperties`](@ref) for acoustic variable density wave equation +- [`ElasticIsoMaterialProperties`](@ref) for elasitic isotropic wave equation + +""" abstract type MaterialProperties{T, N} end +@doc """ + +$(TYPEDEF) + +`Shot` is the abstract supertype describing a shot composed of sources and receivers. + +Currently implemented concrete shot types are: +- [`ScalarShot`](@ref) for scalar field sources and receivers +- [`MomentTensorShot`](@ref) for moment tensor sources and vector field receivers + +""" abstract type Shot{T} end +@doc """ + +$(TYPEDEF) + +`Sources` is the abstract supertype describing seismic sources. + +Currently implemented concrete sources types are: +- [`ScalarSources`](@ref) for scalar field sources +- [`MomentTensorSources`](@ref) for moment tensor sources + +""" abstract type Sources{T} end +@doc """ + +$(TYPEDEF) + +`Sources` is the abstract supertype describing seismic receivers. + +Currently implemented concrete receivers types are: +- [`ScalarReceivers`](@ref) for scalar field receivers +- [`VectorReceivers`](@ref) for vector field receivers + +""" abstract type Receivers{T} end abstract type MomentTensor{T, N} end From 6911a28b33b2ab84c48a1c19ec160d9aa100c94c Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 9 Jul 2024 16:12:36 +0200 Subject: [PATCH 071/111] Remove generated md --- docs/src/examples.md | 176 ------------------------------------------- 1 file changed, 176 deletions(-) delete mode 100644 docs/src/examples.md diff --git a/docs/src/examples.md b/docs/src/examples.md deleted file mode 100644 index 916e23f..0000000 --- a/docs/src/examples.md +++ /dev/null @@ -1,176 +0,0 @@ -```@meta -EditURL = "examples.jl" -``` - -# [Examples](@id examples) - -## Acoustic wave simulation example - -````@example examples -using SeismicWaves - -# numerics -nt = 1500 -dt = 0.0012 -dh = 10.0 -t = collect(Float64, range(0.0; step=dt, length=nt)) ## time vector - -# create a velocity model (gradient from top to bottom) -nx = 211 -nz = 120 -velmod = zeros(nx, nz) -for i in 1:nx - for j in 1:nz - velmod[i, j] = 2000.0 + 12.0 * (j - 1) - end -end -matprop = VpAcousticCDMaterialProperties(velmod) - -# shots definition -nshots = 6 -shots = Vector{ScalarShot{Float64}}() -# sources x-position (in grid points) (different for every shot) -ixsrc = round.(Int, LinRange(32, nx - 31, nshots)) -for i in 1:nshots - # sources definition - nsrc = 1 - possrcs = zeros(1, 2) ## 1 source, 2 dimensions - possrcs[:, 1] .= (ixsrc[i] - 1) * dh ## x-positions in meters - possrcs[:, 2] .= 2 * dh ## y-positions in meters - # source time functions - srcstf = zeros(nt, nsrc) - for s in 1:nsrc - srcstf[:, s] .= 1000.0 .* rickerstf.(t, 1.20 / 12.0, 12.0) - end - srcs = ScalarSources(possrcs, srcstf, 12.0) - - # receivers definition - nrecs = 20 - # receivers x-positions (in grid points) (same for every shot) - ixrec = round.(Int, LinRange(30, nx - 29, nrecs)) - posrecs = zeros(nrecs, 2) ## 20 receivers, 2 dimensions - posrecs[:, 1] .= (ixrec .- 1) .* dh ## x-positions in meters - posrecs[:, 2] .= 2 * dh ## y-positions in meters - recs = ScalarReceivers(posrecs, nt) - - # add pair as shot - push!(shots, ScalarShot(; srcs=srcs, recs=recs)) ## srcs => recs) -end - -# Input parameters for acoustic simulation -snapevery = 100 -boundcond = CPMLBoundaryConditionParameters(; halo=20, rcoef=0.0001, freeboundtop=true) -params = InputParametersAcoustic(nt, dt, (nx, nz), (dh, dh), boundcond) - -# Compute the seismograms -snapshots = swforward!( - params, - matprop, - shots; - parall=:threads, - snapevery=snapevery -) -```` - -## Elastic wave simulation example - -````@example examples -# time stuff -nt = 3000 #1500 -dt = 0.0008 -t = collect(Float64, range(0.0; step=dt, length=nt)) # seconds - -# create a velocity model -nx = 380 ## 211 -nz = 270 ## 120 -dh = 4.5 ## meters - -vp = zeros(nx, nz) -vp[nx÷2+10:end, :] .= 3100.0 -for i in 1:nx - for j in 1:nz - vp[i, j] = 2000.0 + dh * (j - 1) - end -end -vs = vp ./ sqrt(3) - -ρ = 2100.0 * ones(nx, nz) -μ = vs .^ 2 .* ρ ## μ = Vs^2⋅ρ -λ = (vp .^ 2 .* ρ) .- (2 .* μ) ## λ = vp^2 · ρ - 2μ - -matprop = ElasticIsoMaterialProperties(; λ=λ, μ=μ, ρ=ρ) - -# shots definition -nshots = 1 -shots = Vector{MomentTensorShot{Float64, 2, MomentTensor2D{Float64}}}() - -for i in 1:nshots - # sources definition - nsrc = 1 - # sources x-position (in grid points) (different for every shot) - if nsrc == 1 - ixsrc = [nx / 2] - else - ixsrc = round.(Int, LinRange(30, nx - 31, nsrc)) - end - possrcs = zeros(nsrc, 2) ## 1 source, 2 dimensions - for s in 1:nsrc - possrcs[s, 1] = (ixsrc[i] - 1) * dh .+ 0.124 ## x-positions in meters - possrcs[s, 2] = (nz / 2) * dh .+ 0.124 ## y-positions in meters - end - - # source time functions - f0 = 12.0 - t0 = 1.20 / f0 - srcstf = zeros(nt, nsrc) - Mxx = zeros(nsrc) - Mzz = zeros(nsrc) - Mxz = zeros(nsrc) - for s in 1:nsrc - srcstf[:, s] .= rickerstf.(t, t0, f0) - Mxx[s] = 5e10 - Mzz[s] = 5e10 - Mxz[s] = 0.89e10 - end - - srcs = MomentTensorSources( - possrcs, srcstf, - [MomentTensor2D(; Mxx=Mxx[s], Mzz=Mzz[s], Mxz=Mxz[s]) for s in 1:nsrc], - f0 - ) - - # receivers definition - nrecs = 10 - # receivers x-positions (in grid points) (same for every shot) - ixrec = round.(Int, LinRange(40, nx - 40, nrecs)) - posrecs = zeros(nrecs, 2) ## 20 receivers, 2 dimensions - posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 ## x-positions in meters - posrecs[:, 2] .= (10) * dh ## y-positions in meters - - ndim = 2 - recs = VectorReceivers(posrecs, nt, ndim) - - # add pair as shot - push!(shots, MomentTensorShot(; srcs=srcs, recs=recs)) # srcs => recs) -end - -# Input parameters for elastic simulation -snapevery = 5 -infoevery = 100 -freetop = true -halo = 20 -rcoef = 0.0001 -boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=freetop) -params = InputParametersElastic(nt, dt, (nx, nz), (dh, dh), boundcond) - -# Compute the seismograms -snapshots = swforward!( - params, - matprop, - shots; - parall=:threads, - infoevery=infoevery, - snapevery=snapevery -) -```` - From e9dada51369fc802d217ffb19025fca13874705e Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 9 Jul 2024 16:21:33 +0200 Subject: [PATCH 072/111] Fix some docs and add generated to gitignore --- .gitignore | 1 + src/apis/forward.jl | 10 +++++----- src/apis/gradient.jl | 13 ++++++++----- src/apis/misfit.jl | 13 +++++++------ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index c157110..47dfce1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ deps/src/ # Build artifacts for creating documentation generated by the Documenter package docs/build/ +docs/src/examples.md docs/site/ # File generated by Pkg, the package manager, based on a corresponding Project.toml diff --git a/src/apis/forward.jl b/src/apis/forward.jl index 2870bdd..2c46e19 100644 --- a/src/apis/forward.jl +++ b/src/apis/forward.jl @@ -11,8 +11,6 @@ Receivers traces are stored in the receivers for each shot. Return a vector of `Dict` containing for each shot the snapshots of the fields computed in the simulation for each timestep. -See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). - # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation type. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation type. @@ -28,6 +26,8 @@ See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@r - `snapevery::Union{Int, Nothing} = nothing`: if specified, saves itermediate snapshots at the specified frequency (one every `snapevery` time step iteration) and return them as a vector of arrays. - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. - `logger::Union{Nothing, AbstractLogger} = nothing`: if specified, uses the given `logger` object to print logs, otherwise it uses the logger returned from `current_logger()`. + +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). """ function swforward!( params::InputParameters{T, N}, @@ -53,13 +53,11 @@ end $(TYPEDSIGNATURES) -Compute forward simulation using a previously constructed `WaveSimulation` object. +Compute forward simulation using a previously constructed `WaveSimulation` object. See also [`build_wavesim`](@ref) on how to build the `WaveSimulation`. Receivers traces are stored in the receivers for each shot. Return a vector of `Dict` containing for each shot the snapshots of the fields computed in the simulation for each timestep. -See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). - # Positional arguments - `wavesim`: wave simulation object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation type. @@ -67,6 +65,8 @@ See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@r # Keyword arguments - `logger::Union{Nothing, AbstractLogger} = nothing`: if specified, uses the given `logger` object to print logs, otherwise it uses the logger returned from `current_logger()`. + +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). """ function swforward!( wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, diff --git a/src/apis/gradient.jl b/src/apis/gradient.jl index 4252ebe..e5f5e3c 100644 --- a/src/apis/gradient.jl +++ b/src/apis/gradient.jl @@ -12,8 +12,6 @@ If greater than 2, a checkpoint is saved every `check_freq` time step. The optimal tradeoff value is `check_freq = sqrt(nt)` where `nt` is the number of time steps of the forward simulation. Bigger values speed up computation at the cost of using more memory. -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). - # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). @@ -30,7 +28,10 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `infoevery::Union{Int, Nothing} = nothing`: if specified, logs info about the current state of simulation every `infoevery` time steps. - `compute_misfit::Bool = false`: if true, also computes and return misfit value. - `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. -- `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. +- `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. + +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). +See also [`swforward!`](@ref) and [`swmisfit!`](@ref) and [`Shot`](@ref). """ function swgradient!( params::InputParameters{T,N}, @@ -61,6 +62,7 @@ end $(TYPEDSIGNATURES) Compute gradients w.r.t. model parameters using the *previously* built `WaveSimulation`. This avoids re-initializing and re-allocating several arrays in case of multiple gradient calculations. +See also [`build_wavesim`](@ref) on how to build the `WaveSimulation`. The `check_freq` parameter controls the checkpoiting frequency for adjoint computation. If `nothing`, no checkpointing is performed. @@ -68,8 +70,6 @@ If greater than 2, a checkpoint is saved every `check_freq` time step. The optimal tradeoff value is `check_freq = sqrt(nt)` where `nt` is the number of time steps of the forward simulation. Bigger values speed up computation at the cost of using more memory. -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfit!`](@ref). - # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. - `matprop::MaterialProperties{T, N}`: material properties for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., Vp only is required for an acoustic constant-density simulation). @@ -87,6 +87,9 @@ See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref), [`swmisfi - `compute_misfit::Bool = false`: if true, also computes and return misfit value. - `smooth_radius::Int = 5`: grid points inside a ball with radius specified by the parameter (in grid points) will have their gradient smoothed by a factor inversely proportional to their distance from sources positions. - `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. + +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). +See also [`swforward!`](@ref) and [`swmisfit!`](@ref) and [`Shot`](@ref). """ function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Dict{String, Array{T, N}}, diff --git a/src/apis/misfit.jl b/src/apis/misfit.jl index 62a47a8..44312da 100644 --- a/src/apis/misfit.jl +++ b/src/apis/misfit.jl @@ -3,6 +3,7 @@ $(TYPEDSIGNATURES) Return the misfit w.r.t. observed data by running a forward simulation using the given input parameters `params` and material properties `matprop` on multiple shots. +Receivers traces are stored in the receivers for each shot. # Positional arguments - `params::InputParameters{T, N}`: input parameters for the simulation, where T represents the data type and N represents the number of dimensions. They vary depending on the simulation kind (e.g., acoustic variable-density). @@ -16,10 +17,10 @@ Return the misfit w.r.t. observed data by running a forward simulation using the - `Base.Threads` CPU threads performing automatic domain decomposition if set to `:threads` - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` +- `logger::Union{Nothing,AbstractLogger}`: specifies the logger to be used. -Receivers traces are stored in the `Receivers` object for each shot. - -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). +See also [`swforward!`](@ref) and [`swgradient!`](@ref) and [`Shot`](@ref). """ function swmisfit!( params::InputParameters{T, N}, @@ -45,6 +46,7 @@ end $(TYPEDSIGNATURES) Return the misfit w.r.t. observed data by running a forward simulation using the given `WaveSimulation` object as an input. +Receivers traces are stored in the receivers for each shot. See also [`build_wavesim`](@ref) on how to build the `WaveSimulation`. # Positional arguments - `wavesim::Union{WaveSimulation{T,N},Vector{<:WaveSimulation{T,N}}}`: input `WaveSimulation` object containing all required information to run the simulation. @@ -59,9 +61,8 @@ Return the misfit w.r.t. observed data by running a forward simulation using the - `Base.Threads` CPU threads sending a group of sources to each thread if set to `:threadpersrc` - otherwise the serial version if set to `:serial` -Receivers traces are stored in the `Receivers` object for each shot. - -See also [`Sources`](@ref), [`Receivers`](@ref), [`swforward!`](@ref). +See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). +See also [`swforward!`](@ref) and [`swgradient!`](@ref) and [`Shot`](@ref). """ function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::T where {T, N} From cd6538394f9d92f46d1bf6fb40c4e49fbe95a8a5 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 10 Jul 2024 16:13:57 +0200 Subject: [PATCH 073/111] Update example --- docs/src/examples.jl | 2 +- examples/simple_example_elastic.jl | 35 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/docs/src/examples.jl b/docs/src/examples.jl index 2082cd6..52a90c5 100644 --- a/docs/src/examples.jl +++ b/docs/src/examples.jl @@ -138,7 +138,7 @@ for i in 1:nshots ixrec = round.(Int, LinRange(40, nx - 40, nrecs)) posrecs = zeros(nrecs, 2) ## 20 receivers, 2 dimensions posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 ## x-positions in meters - posrecs[:, 2] .= (10) * dh ## y-positions in meters + posrecs[:, 2] .= 3 * dh ## y-positions in meters ndim = 2 recs = VectorReceivers(posrecs, nt, ndim) diff --git a/examples/simple_example_elastic.jl b/examples/simple_example_elastic.jl index 15064c4..c32a263 100644 --- a/examples/simple_example_elastic.jl +++ b/examples/simple_example_elastic.jl @@ -96,7 +96,7 @@ function exelaprob() ixrec = round.(Int, LinRange(40, nx - 40, nrecs)) posrecs = zeros(nrecs, 2) # 20 receivers, 2 dimensions posrecs[:, 1] .= (ixrec .- 1) .* dh .- 0.324 # x-positions in meters - posrecs[:, 2] .= (10) * dh # (nz/2) * dh # y-positions in meters + posrecs[:, 2] .= 3 * dh # (nz/2) * dh # y-positions in meters ndim = 2 recs = VectorReceivers(posrecs, nt, ndim) @@ -241,12 +241,14 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) end ##===================================== - fig = Figure(; size=(900, 1800)) + fig = Figure(; size=(800, 1500)) - cmapwavefield = :balance #:cyclic_grey_15_85_c0_n256_s25 #:balance + nframes = length(vxsnap) + + cmapwavefield = :vik #:cyclic_grey_15_85_c0_n256_s25 #:balance ax1 = Axis(fig[1, 1]; aspect=DataAspect(), - xlabel="x [m]", ylabel="z [m]") + xlabel="x [m]", ylabel="z [m]", title="Vx, clip at $scalamp of max amplitude, iteration 0 of $(snapevery*nframes)") #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) extx = extrema.([vxsnap[i] for i in 1:length(vxsnap)]) extx = map(p -> max(abs(p[1]), abs(p[2])), extx) @@ -259,11 +261,11 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) lines!(ax1, Rect(rectpml...); color=:green) scatter!(ax1, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) scatter!(ax1, xsrc, ysrc; label="Sources", markersize=15) - axislegend(ax1) + # axislegend(ax1) ax1.yreversed = true ax2 = Axis(fig[2, 1]; aspect=DataAspect(), - xlabel="x [m]", ylabel="z [m]") + xlabel="x [m]", ylabel="z [m]", title="Vz, clip at $scalamp of max amplitude, iteration 0 of $(snapevery*nframes)") #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) extx = extrema.([vzsnap[i] for i in 1:length(vzsnap)]) extx = map(p -> max(abs(p[1]), abs(p[2])), extx) @@ -276,25 +278,24 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) lines!(ax2, Rect(rectpml...); color=:green) scatter!(ax2, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) scatter!(ax2, xsrc, ysrc; label="Sources", markersize=15) - axislegend(ax2) + # axislegend(ax2) ax2.yreversed = true - ax3 = Axis(fig[3, 1]; aspect=DataAspect(), - xlabel="x [m]", ylabel="z [m]") - hm = heatmap!(ax3, xgrd, ygrd, vp; colormap=:Reds) #,alpha=0.7) - Colorbar(fig[3, 2], hm; label="Vp") + # ax3 = Axis(fig[3, 1]; aspect=DataAspect(), + # xlabel="x [m]", ylabel="z [m]") + # hm = heatmap!(ax3, xgrd, ygrd, vp; colormap=:Reds) #,alpha=0.7) + # Colorbar(fig[3, 2], hm; label="Vp") - scatter!(ax3, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) - scatter!(ax3, xsrc, ysrc; label="Sources", markersize=15) - axislegend(ax3) - ax3.yreversed = true + # scatter!(ax3, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + # scatter!(ax3, xsrc, ysrc; label="Sources", markersize=15) + # axislegend(ax3) + # ax3.yreversed = true ## display(fig) + save("first_frame.png", fig) ##===================================== - nframes = length(vxsnap) - function updatefunction(curax1, curax2, vxsnap, vzsnap, it) cvx = vxsnap[it] cvz = vzsnap[it] From 2d4b195e911f9505f8a9fcbd9d28a4ca55e82fea Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 10 Jul 2024 16:15:28 +0200 Subject: [PATCH 074/111] Update guide with links to other sections --- docs/src/guide.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/src/guide.md b/docs/src/guide.md index 0c4c695..c89c82a 100644 --- a/docs/src/guide.md +++ b/docs/src/guide.md @@ -1,3 +1,7 @@ # User guide -TODO \ No newline at end of file +> Warning: **User guide is currently work in progress**! + +See the [Examples](@ref examples) for how to use this package! + +See the [API](@ref api) for detailed information about the functionalities of this package! \ No newline at end of file From f195774b5697d0c5ce7e01cf79e2715f8a2b1617 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 5 Sep 2024 17:00:31 +0200 Subject: [PATCH 075/111] Elastic gradient (WIP) --- src/SeismicWaves.jl | 2 +- .../backends/Elastic2D_Iso_CPML_AMDGPU.jl | 1 + .../backends/Elastic2D_Iso_CPML_CUDA.jl | 1 + .../backends/Elastic2D_Iso_CPML_Serial.jl | 114 +++++++++++-- .../backends/Elastic2D_Iso_CPML_Threads.jl | 1 + .../backends/shared/correlate_gradient_xPU.jl | 23 +++ .../backends/shared/elastic2D_iso_xPU.jl | 81 ++++++++- src/models/elastic/ela_gradient.jl | 154 ++++++++++++++++++ src/models/elastic/ela_material_properties.jl | 2 + src/models/elastic/ela_models.jl | 57 ++++++- src/utils/utils.jl | 28 +++- 11 files changed, 442 insertions(+), 22 deletions(-) create mode 100644 src/models/elastic/backends/shared/correlate_gradient_xPU.jl create mode 100644 src/models/elastic/ela_gradient.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 79558d0..9d10a63 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -68,7 +68,7 @@ include("models/elastic/ela_params.jl") include("models/elastic/ela_material_properties.jl") include("models/elastic/ela_models.jl") include("models/elastic/ela_forward.jl") -#include("models/elastic/ela_gradient.jl") +include("models/elastic/ela_gradient.jl") include("models/elastic/ela_init_bc.jl") # Backend selection diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl index 7002cc2..df745e3 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl @@ -9,5 +9,6 @@ using ParallelStencil.FiniteDifferences2D include("shared/standard_xPU.jl") include("shared/fourth_order_FiniteDifferences2D.jl") include("shared/elastic2D_iso_xPU.jl") +include("shared/correlate_gradient_xPU.jl") end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl index 817f0ff..4037ccc 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl @@ -9,5 +9,6 @@ using ParallelStencil.FiniteDifferences2D include("shared/standard_xPU.jl") include("shared/fourth_order_FiniteDifferences2D.jl") include("shared/elastic2D_iso_xPU.jl") +include("shared/correlate_gradient_xPU.jl") end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 50bf505..d149bdd 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -490,6 +490,74 @@ function forward_onestep_CPML!( return end +function adjoint_onestep_CPML!( + model, + srccoeij_bk, + srccoeval_bk, + residuals_bk, + it +) + # Extract info from grid + freetop = model.cpmlparams.freeboundtop + cpmlcoeffs = model.cpmlcoeffs + dx = model.grid.spacing[1] + dz = model.grid.spacing[2] + dt = model.dt + nx, nz = model.grid.size[1:2] + halo = model.cpmlparams.halo + grid = model.grid + + vx, vz = grid.fields["adjv"].value + σxx, σzz, σxz = grid.fields["adjσ"].value + + ψ_∂σxx∂x, ψ_∂σxz∂x = grid.fields["adjψ_∂σ∂x"].value + ψ_∂σzz∂z, ψ_∂σxz∂z = grid.fields["adjψ_∂σ∂z"].value + ψ_∂vx∂x, ψ_∂vz∂x = grid.fields["adjψ_∂v∂x"].value + ψ_∂vx∂z, ψ_∂vz∂z = grid.fields["adjψ_∂v∂z"].value + + a_x = cpmlcoeffs[1].a + a_x_half = cpmlcoeffs[1].a_h + b_x = cpmlcoeffs[1].b + b_x_half = cpmlcoeffs[1].b_h + + a_z = cpmlcoeffs[2].a + a_z_half = cpmlcoeffs[2].a_h + b_z = cpmlcoeffs[2].b + b_z_half = cpmlcoeffs[2].b_h + + ρ = grid.fields["ρ"].value + ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value + λ_ihalf = grid.fields["λ_ihalf"].value + μ_ihalf = grid.fields["μ_ihalf"].value + μ_jhalf = grid.fields["μ_jhalf"].value + + # Precomputing divisions + factx = 1.0 / (24.0 * dx) + factz = 1.0 / (24.0 * dz) + + # update velocity vx + update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, + b_x, b_z, a_x, a_z, freetop) + # update velocity vz + update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, + ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + + # inject sources (external body force) + inject_vel_sources2D!(vx, vz, residuals_bk, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, it) + + # update stresses σxx and σzz + update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, + ψ_∂vx∂x, ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + # update stress σxz + update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + + return +end + function inject_momten_sources2D!(σxx, σzz, σxz, Mxx, Mzz, Mxz, srctf_bk, dt, srccoeij_bk, srccoeval_bk, it) #function inject_momten_sources!(σxx,σzz,σxz,Mxx, Mzz, Mxz, srctf_bk, dt, possrcs_bk, it) @@ -522,6 +590,16 @@ function inject_momten_sources2D!(σxx, σzz, σxz, Mxx, Mzz, Mxz, srctf_bk, dt, return end +function inject_vel_sources2D!(vx, vz, f, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, it) + nsrcpts = size(srccoeij_bk, 1) + for p in 1:nsrcpts + s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] + vx[isrc, jsrc] += srccoeval_bk[s] * f[it, 1, s] * dt / ρ[isrc, jsrc] + vz[isrc, jsrc] += srccoeval_bk[s] * f[it, 2, s] * dt / ρ_ihalf_jhalf[isrc, jsrc] + end + return nothing +end + function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) # total number of interpolation points @@ -532,8 +610,8 @@ function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) # [src_id, i, j] r, irec, jrec = reccoeij_bk[p, :] # update traces by summing up values from all sinc interpolation points - traces_bk[it, 1, r] += vx[irec, jrec] - traces_bk[it, 2, r] += vz[irec, jrec] + traces_bk[it, 1, r] += reccoeval_bk[r] * vx[irec, jrec] + traces_bk[it, 2, r] += reccoeval_bk[r] * vz[irec, jrec] end # for ir in axes(posrecs, 1) @@ -546,16 +624,28 @@ function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) return end -#function correlate_gradient!( ) -# _dt2 = 1 / dt^2 -# nx, nz = size(curgrad) -# for j in 1:nz -# for i in 1:nx -# curgrad[i, j] = curgrad[i, j] + (adjcur[i, j] * (pcur[i, j] - 2.0 * pold[i, j] + pveryold[i, j]) * _dt2) -# end -# end -# return -#end +function correlate_gradient_ρ_kernel!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, _dt2) + @. curgrad_ρ += adjv * (v_curr - 2 * v_old + v_veryold) * _dt2 + return nothing +end + +function correlate_gradient_ρ!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, dt) + _dt2 = 1 / dt^2 + adjvx = adjv[1] + vx_curr = v_curr[1] + vx_old = v_old[1] + vx_veryold = v_veryold[1] + correlate_gradient_ρ_kernel!(curgrad_ρ, adjvx, vx_curr, vx_old, vx_veryold, _dt2) +end + +function correlate_gradient_ρ_ihalf_jhalf!(curgrad_ρ_ihalf_jhalf, adjv, v_curr, v_old, v_veryold, dt) + _dt2 = 1 / dt^2 + adjvz = adjv[2] + vz_curr = v_curr[2] + vz_old = v_old[2] + vz_veryold = v_veryold[2] + correlate_gradient_ρ_kernel!(curgrad_ρ_ihalf_jhalf, adjvz, vz_curr, vz_old, vz_veryold, _dt2) +end ######################################### end # end module diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl index 4c3635d..075efcf 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl @@ -8,5 +8,6 @@ using ParallelStencil.FiniteDifferences2D include("shared/standard_xPU.jl") include("shared/fourth_order_FiniteDifferences2D.jl") include("shared/elastic2D_iso_xPU.jl") +include("shared/correlate_gradient_xPU.jl") end diff --git a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl new file mode 100644 index 0000000..bab247e --- /dev/null +++ b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl @@ -0,0 +1,23 @@ +@parallel function correlate_gradient_ρ_kernel!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, _dt2) + @all(curgrad_ρ) = @all(curgrad_ρ) + (@all(adjv) * (@all(v_curr) - 2 * @all(v_old) + @all(v_veryold)) * _dt2) + + return nothing +end + +@views function correlate_gradient_ρ!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, dt) + _dt2 = 1 / dt^2 + adjvx = adjv[1] + vx_curr = v_curr[1] + vx_old = v_old[1] + vx_veryold = v_veryold[1] + @parallel correlate_gradient_ρ_kernel!(curgrad_ρ, adjvx, vx_curr, vx_old, vx_veryold, _dt2) +end + +@views function correlate_gradient_ρ_ihalf_jhalf!(curgrad_ρ_ihalf_jhalf, adjv, v_curr, v_old, v_veryold, dt) + _dt2 = 1 / dt^2 + adjvz = adjv[2] + vz_curr = v_curr[2] + vz_old = v_old[2] + vz_veryold = v_veryold[2] + @parallel correlate_gradient_ρ_kernel!(curgrad_ρ_ihalf_jhalf, adjvz, vz_curr, vz_old, vz_veryold, _dt2) +end diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 38bc586..5366485 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -250,10 +250,18 @@ end return nothing end +@parallel_indices (p) function inject_vel_sources2D!(vx, vz, f, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, it) + s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] + vx[isrc, jsrc] += srccoeval_bk[s] * f[it, 1, s] * dt / ρ[isrc, jsrc] + vz[isrc, jsrc] += srccoeval_bk[s] * f[it, 2, s] * dt / ρ_ihalf_jhalf[isrc, jsrc] + return nothing +end + + @parallel_indices (p) function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) r, irec, jrec = reccoeij_bk[p, 1], reccoeij_bk[p, 2], reccoeij_bk[p, 3] - traces_bk[it, 1, r] += vx[irec, jrec] - traces_bk[it, 2, r] += vz[irec, jrec] + traces_bk[it, 1, r] += reccoeval_bk[p] * vx[irec, jrec] + traces_bk[it, 2, r] += reccoeval_bk[p] * vz[irec, jrec] return nothing end @@ -338,5 +346,74 @@ function forward_onestep_CPML!( @parallel (1:nrecpts) record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) end + return +end + +function adjoint_onestep_CPML!( + model, + srccoeij_bk, + srccoeval_bk, + residuals_bk, + it +) + # Extract info from grid + freetop = model.cpmlparams.freeboundtop + cpmlcoeffs = model.cpmlcoeffs + dx = model.grid.spacing[1] + dz = model.grid.spacing[2] + dt = model.dt + nx, nz = model.grid.size[1:2] + halo = model.cpmlparams.halo + grid = model.grid + + vx, vz = grid.fields["adjv"].value + σxx, σzz, σxz = grid.fields["adjσ"].value + + ψ_∂σxx∂x, ψ_∂σxz∂x = grid.fields["adjψ_∂σ∂x"].value + ψ_∂σzz∂z, ψ_∂σxz∂z = grid.fields["adjψ_∂σ∂z"].value + ψ_∂vx∂x, ψ_∂vz∂x = grid.fields["adjψ_∂v∂x"].value + ψ_∂vx∂z, ψ_∂vz∂z = grid.fields["adjψ_∂v∂z"].value + + a_x = cpmlcoeffs[1].a + a_x_half = cpmlcoeffs[1].a_h + b_x = cpmlcoeffs[1].b + b_x_half = cpmlcoeffs[1].b_h + + a_z = cpmlcoeffs[2].a + a_z_half = cpmlcoeffs[2].a_h + b_z = cpmlcoeffs[2].b + b_z_half = cpmlcoeffs[2].b_h + + ρ = grid.fields["ρ"].value + ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value + λ_ihalf = grid.fields["λ_ihalf"].value + μ_ihalf = grid.fields["μ_ihalf"].value + μ_jhalf = grid.fields["μ_jhalf"].value + + # Precomputing divisions + factx = 1.0 / (24.0 * dx) + factz = 1.0 / (24.0 * dz) + + # update velocity vx + @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, + b_x, b_z, a_x, a_z, freetop) + # update velocity vz + @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, + ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + + # inject sources (residuals as velocities) + nsrcpts = size(srccoeij_bk, 1) + @parallel (1:nsrcpts) inject_vel_sources2D!(vx, vz, residuals_bk, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, it) + + # update stresses σxx and σzz + @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, + ψ_∂vx∂x, ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + # update stress σxz + @parallel (3:nx-1, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + return end \ No newline at end of file diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl new file mode 100644 index 0000000..9823ecc --- /dev/null +++ b/src/models/elastic/ela_gradient.jl @@ -0,0 +1,154 @@ +@views function swgradient_1shot!( + ::CPMLBoundaryCondition, + model::ElasticIsoCPMLWaveSimulation{T, 2}, + shot::MomentTensorShot{T, 2, MomentTensor2D{T}}, + misfit +)::Dict{String, Array{T, 2}} where {T} + + # interpolation coefficients for sources + srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, + shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for receivers + reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, + shot.recs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + + # source time function + srctf = shot.srcs.tf + # moment tensors + momtens = shot.srcs.momtens + + # Get computational grid, checkpointer and backend + grid = model.grid + checkpointer = model.checkpointer + backend = select_backend(typeof(model), model.parall) + + # Numerics + nt = model.nt + # Wrap sources and receivers arrays + srccoeij_bk = backend.Data.Array(srccoeij) + srccoeval_bk = backend.Data.Array(srccoeval) + reccoeij_bk = backend.Data.Array(reccoeij) + reccoeval_bk = backend.Data.Array(reccoeval) + + srctf_bk = backend.Data.Array(srctf) + traces_bk = backend.Data.Array(shot.recs.seismograms) + + ## ONLY 2D for now!!! + nsrcs = length(momtens) + Mxx_bk = backend.Data.Array([momtens[i].Mxx for i in 1:nsrcs]) + Mzz_bk = backend.Data.Array([momtens[i].Mzz for i in 1:nsrcs]) + Mxz_bk = backend.Data.Array([momtens[i].Mxz for i in 1:nsrcs]) + + # Reset wavesim + reset!(model) + + # Forward time loop + for it in 1:nt + # Compute one forward step + backend.forward_onestep_CPML!(model, + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + traces_bk, + it, + Mxx_bk, Mzz_bk, Mxz_bk; + save_trace=true) + + # Print timestep info + if it % model.infoevery == 0 + # Move the cursor to the beginning to overwrite last line + # ter = REPL.Terminals.TTYTerminal("", stdin, stdout, stderr) + # REPL.Terminals.clear_line(ter) + # REPL.Terminals.cmove_line_up(ter) + @info @sprintf( + "Iteration: %d/%d, simulation time: %g s", + it, nt, + model.dt * (it - 1) + ) + end + # Save checkpoint + savecheckpoint!(checkpointer, "σ" => grid.fields["σ"], it) + savecheckpoint!(checkpointer, "v" => grid.fields["v"], it) + savecheckpoint!(checkpointer, "ψ_∂σ∂x" => grid.fields["ψ_∂σ∂x"], it) + savecheckpoint!(checkpointer, "ψ_∂σ∂z" => grid.fields["ψ_∂σ∂z"], it) + savecheckpoint!(checkpointer, "ψ_∂v∂x" => grid.fields["ψ_∂v∂x"], it) + savecheckpoint!(checkpointer, "ψ_∂v∂z" => grid.fields["ψ_∂v∂z"], it) + end + + @info "Saving seismograms" + copyto!(shot.recs.seismograms, traces_bk) + + @debug "Computing residuals" + residuals_bk = backend.Data.Array(dχ_du(misfit, shot.recs)) + + @debug "Computing gradients" + # Adjoint time loop (backward in time) + for it in nt:-1:1 + # Compute one adjoint step + backend.adjoint_onestep_CPML!(model, + reccoeij_bk, + reccoeval_bk, + residuals_bk, + it) + # Print timestep info + if it % model.infoevery == 0 + @info @sprintf("Backward iteration: %d", it) + end + # Check if out of save buffer + if !issaved(checkpointer, "v", it - 2) + @debug @sprintf("Out of save buffer at iteration: %d", it) + initrecover!(checkpointer) + copyto!(grid.fields["σ"], getsaved(checkpointer, "σ", checkpointer.curr_checkpoint)) + copyto!(grid.fields["v"], getsaved(checkpointer, "v", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂σ∂x"], getsaved(checkpointer, "ψ_∂σ∂x", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂σ∂z"], getsaved(checkpointer, "ψ_∂σ∂z", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂v∂x"], getsaved(checkpointer, "ψ_∂v∂x", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂v∂z"], getsaved(checkpointer, "ψ_∂v∂z", checkpointer.curr_checkpoint)) + recover!( + checkpointer, + recit -> begin + backend.forward_onestep_CPML!(model, + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + nothing, + it, + Mxx_bk, Mzz_bk, Mxz_bk; + save_trace=false) + return ["v" => grid.fields["v"]] + end + ) + end + # Get velocity fields from saved buffer + v_curr = getsaved(checkpointer, "v", it).value + v_old = getsaved(checkpointer, "v", it - 1).value + v_veryold = getsaved(checkpointer, "v", it - 2).value + # Correlate for gradient computation + backend.correlate_gradient_ρ!(grid.fields["grad_ρ"].value, grid.fields["adjv"].value, v_curr, v_old, v_veryold, dt) + backend.correlate_gradient_ρ_ihalf_jhalf!(grid.fields["grad_ρ_ihalf_jhalf"].value, grid.fields["adjv"].value, v_curr, v_old, v_veryold, dt) + # TODO add other correlations + end + # Allocate gradients + gradient_ρ = zeros(T, grid.size...) + gradient_λ = zeros(T, grid.size...) + gradient_μ = zeros(T, grid.size...) + # Get gradients + copyto!(gradient_ρ, grid.fields["grad_ρ"].value) + # TODO compute chain rule for ρ_ihalf_jhalf to ρ + gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, Array(grid.fields["grad_ρ_ihalf_jhalf"].value), [1, 2]) + # TODO smooth gradients + # Compute regularization if needed + ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) + # Return gradients + return Dict( + "rho" => gradient_ρ .+ ∂χ_∂ρ, + "lambda" => gradient_λ .+ ∂χ_∂λ, + "mu" => gradient_μ .+ ∂χ_∂μ, + ) +end \ No newline at end of file diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index ef9d6b0..a1c4dd2 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -13,4 +13,6 @@ Base.@kwdef struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIsoMaterial μ::Array{T, N} "Density" ρ::Array{T, N} + "Interpolation method for density" + interp_method_ρ::InterpolationMethod = ArithmeticAverageInterpolation(2) end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 3fd81fd..9cc9d17 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -68,7 +68,7 @@ function precomp_elaprop!(model::ElasticIsoWaveSimulation{T, 2}; harmonicaver_μ #------------------------------------------------------------- # ρ_ihalf_jhalf (nx-1,nz-1) ?? # arithmetic mean for ρ - @. ρ_ihalf_jhalf = (ρ[2:end,2:end] .+ ρ[2:end, 1:end-1] .+ ρ[1:end-1, 2:end] .+ ρ[1:end-1, 1:end-1]) ./ 4.0 + copyto!(ρ_ihalf_jhalf, interp(model.matprop.interp_method_ρ, model.matprop.ρ, [1, 2])) # μ_ihalf (nx-1,nz) ?? # μ_ihalf (nx,nz-1) ?? if harmonicaver_μ == true @@ -193,6 +193,56 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac addfield!(grid, "ψ_∂v∂z" => MultiVariableField( [backend.zeros(T, gs2...) for _ in 1:2] )) + # Initialize gradient arrays if needed + if gradient + error("Gradient for elastic calculations not yet implemented!") + + # Stress and velocity + addfield!(grid, "adjσ" => MultiVariableField( + [backend.zeros(T, gridsize...) for _ in 1:3] + )) + addfield!(grid, "adjv" => MultiVariableField( + [backend.zeros(T, gridsize...) for _ in 1:2] + )) + # CPML memory variables + addfield!(grid, "adjψ_∂σ∂x" => MultiVariableField( + [backend.zeros(T, gs1...) for _ in 1:2] + )) + addfield!(grid, "adjψ_∂σ∂z" => MultiVariableField( + [backend.zeros(T, gs2...) for _ in 1:2] + )) + addfield!(grid, "adjψ_∂v∂x" => MultiVariableField( + [backend.zeros(T, gs1...) for _ in 1:2] + )) + addfield!(grid, "adjψ_∂v∂z" => MultiVariableField( + [backend.zeros(T, gs2...) for _ in 1:2] + )) + # Gradient arrays + addfield!(grid, "grad_ρ" => ScalarVariableField( + backend.zeros(T, gridsize...) + )) + addfield!(grid, "grad_ρ_ihalf_jhalf" => ScalarVariableField( + backend.zeros(T, gridsize...) + )) + # TODO add other gradient fields + + # Initialize checkpointer + checkpointer = LinearCheckpointer( + nt, + check_freq === nothing ? 1 : check_freq, + filter(p -> p.first in ["σ", "v", "ψ_∂σ∂x", "ψ_∂σ∂z", "ψ_∂v∂x", "ψ_∂v∂z"], grid.fields), + ["v"]; + widths=Dict("v" => 2) + ) + # Save first two timesteps + savecheckpoint!(checkpointer, "σ" => grid.fields["σ"], 0) + savecheckpoint!(checkpointer, "v" => grid.fields["v"], -1) + savecheckpoint!(checkpointer, "v" => grid.fields["v"], 0) + savecheckpoint!(checkpointer, "ψ_∂σ∂x" => grid.fields["ψ_∂σ∂x"], 0) + savecheckpoint!(checkpointer, "ψ_∂σ∂z" => grid.fields["ψ_∂σ∂z"], 0) + savecheckpoint!(checkpointer, "ψ_∂v∂x" => grid.fields["ψ_∂v∂x"], 0) + savecheckpoint!(checkpointer, "ψ_∂v∂z" => grid.fields["ψ_∂v∂z"], 0) + end else error("Only elastic 2D is currently implemented.") end @@ -200,11 +250,6 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac # Initialize CPML coefficients cpmlcoeffs = tuple([CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N]...) - # Initialize gradient arrays if needed - if gradient - error("Gradient for elastic calculations not yet implemented!") - end - if snapevery !== nothing # Initialize snapshotter snapshotter = LinearSnapshotter{Array{T, N}}(nt, snapevery, Dict("v" => MultiVariableField( diff --git a/src/utils/utils.jl b/src/utils/utils.jl index b4aa50a..ad54623 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -25,12 +25,38 @@ end interpolate(a::Array{T, N}, interp_method) where {T, N} = collect(interp(interp_method, a, i) for i in 1:N) -@views function interp(method::ArithmeticAverageInterpolation, a::Array{<:Real, N}, dim) where {N} +@views function interp(method::ArithmeticAverageInterpolation, a::Array{<:Real, N}, dim::Int) where {N} return sum( a[CartesianIndices(Tuple(i == dim ? (j:size(a, i)+j-method.width) : (1:size(a, i)) for i in 1:N))] for j in 1:method.width ) ./ method.width end +@views function interp(method::ArithmeticAverageInterpolation, a::Array{<:Real, N}, dims::Vector{Int}) where {N} + return sum( + a[CartesianIndices(Tuple(i in dims ? (j:size(a, i)+j-method.width) : (1:size(a, i)) for i in 1:N))] for j in 1:method.width + ) ./ method.width +end + +@views function back_interp(method::ArithmeticAverageInterpolation, a::Array{T, N}, dim::Int) where {T, N} + res = zeros(T, size(a) .+ [i == dim ? 1 : 0 for i in 1:N]) + for k in 1:method.width + res[CartesianIndices(Tuple( + i == dim ? (k:size(res, i)*k-method.width) : (1:size(res, i)) for i in 1:N + ))] .+= a + end + return res ./ method.width +end + +@views function back_interp(method::ArithmeticAverageInterpolation, a::Array{T, N}, dims::Vector{Int}) where {T, N} + res = zeros(T, size(a) .+ [i in dim ? 1 : 0 for i in 1:N]) + for k in 1:method.width + res[CartesianIndices(Tuple( + i in dims ? (k:size(res, i)*k-method.width) : (1:size(res, i)) for i in 1:N + ))] .+= a + end + return res ./ method.width +end + """ $(TYPEDSIGNATURES) From cedb240fda6ae7e9c15d556e3b67e1139c5e4c54 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Fri, 20 Sep 2024 18:28:59 +0200 Subject: [PATCH 076/111] Implement adjoint and gradients for 2D elastic isotropic --- src/SeismicWaves.jl | 2 +- src/apis/build.jl | 18 +-- src/apis/forward.jl | 2 +- src/apis/gradient.jl | 8 +- src/apis/misfit.jl | 2 +- src/inversion/misfits/L2Misfit.jl | 40 ++++++ .../ZerothOrderTikhonovRegularization.jl | 25 +++- src/models/acoustic/acou_gradient.jl | 7 +- src/models/acoustic/acou_models.jl | 38 ++++-- .../backends/Elastic2D_Iso_CPML_Serial.jl | 127 +++++++++++++----- .../backends/shared/correlate_gradient_xPU.jl | 83 +++++++++--- .../backends/shared/elastic2D_iso_xPU.jl | 67 +++++---- src/models/elastic/ela_forward.jl | 41 ++---- src/models/elastic/ela_gradient.jl | 93 +++++++------ src/models/elastic/ela_init_bc.jl | 2 +- src/models/elastic/ela_material_properties.jl | 6 +- src/models/elastic/ela_models.jl | 100 ++++++++------ src/shots/receivers.jl | 14 +- src/shots/shot.jl | 2 - src/utils/abstract_types.jl | 1 - src/utils/fields.jl | 1 - src/utils/interpolations.jl | 52 +++++++ src/utils/utils.jl | 39 ------ test/runtests.jl | 3 +- ..._vs_numerical_acoustic_constant_density.jl | 2 +- ..._vs_numerical_acoustic_variable_density.jl | 2 +- test/test_forward_constant_density.jl | 4 +- ...test_gradient_acoustic_constant_density.jl | 2 +- ...test_gradient_acoustic_variable_density.jl | 2 +- .../test_gradient_elastic_constant_density.jl | 61 +++++++++ test/test_misfit_acoustic_constant_density.jl | 2 +- test/test_snapshotting_constant_density.jl | 2 +- test/utils/setup_models.jl | 44 ++++-- 33 files changed, 608 insertions(+), 286 deletions(-) create mode 100644 src/utils/interpolations.jl create mode 100644 test/test_gradient_elastic_constant_density.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 9d10a63..dffd047 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -37,6 +37,7 @@ include("traits/snappable.jl") include("traits/grid.jl") # Utils +include("utils/interpolations.jl") include("utils/utils.jl") include("utils/checks.jl") include("utils/fields.jl") @@ -85,7 +86,6 @@ include("apis/forward.jl") include("apis/misfit.jl") include("apis/gradient.jl") - # Acoustic serial backend include("models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl") include("models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl") diff --git a/src/apis/build.jl b/src/apis/build.jl index 6d2cb67..70a621f 100644 --- a/src/apis/build.jl +++ b/src/apis/build.jl @@ -30,11 +30,11 @@ function build_wavesim(params::InputParameters{T, N}, matprop::MaterialPropertie end build_concrete_wavesim( - params::InputParametersAcoustic{T,N}, - matprop::VpAcousticCDMaterialProperties{T,N}, + params::InputParametersAcoustic{T, N}, + matprop::VpAcousticCDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters{T}; kwargs... -) where {T,N} = AcousticCDCPMLWaveSimulation( +) where {T, N} = AcousticCDCPMLWaveSimulation( params, matprop, cpmlparams; @@ -42,11 +42,11 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersAcoustic{T,N}, - matprop::VpRhoAcousticVDMaterialProperties{T,N}, + params::InputParametersAcoustic{T, N}, + matprop::VpRhoAcousticVDMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters; kwargs... -) where {T,N} = AcousticVDStaggeredCPMLWaveSimulation( +) where {T, N} = AcousticVDStaggeredCPMLWaveSimulation( params, matprop, cpmlparams; @@ -54,11 +54,11 @@ build_concrete_wavesim( ) build_concrete_wavesim( - params::InputParametersElastic{T,N}, - matprop::ElasticIsoMaterialProperties{T,N}, + params::InputParametersElastic{T, N}, + matprop::ElasticIsoMaterialProperties{T, N}, cpmlparams::CPMLBoundaryConditionParameters{T}; kwargs... -) where {T,N} = ElasticIsoCPMLWaveSimulation( +) where {T, N} = ElasticIsoCPMLWaveSimulation( params, matprop, cpmlparams; diff --git a/src/apis/forward.jl b/src/apis/forward.jl index 2c46e19..3195c55 100644 --- a/src/apis/forward.jl +++ b/src/apis/forward.jl @@ -69,7 +69,7 @@ Return a vector of `Dict` containing for each shot the snapshots of the fields c See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). """ function swforward!( - wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, + wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, diff --git a/src/apis/gradient.jl b/src/apis/gradient.jl index e5f5e3c..37e7411 100644 --- a/src/apis/gradient.jl +++ b/src/apis/gradient.jl @@ -34,7 +34,7 @@ See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@r See also [`swforward!`](@ref) and [`swmisfit!`](@ref) and [`Shot`](@ref). """ function swgradient!( - params::InputParameters{T,N}, + params::InputParameters{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; parall::Symbol=:threads, @@ -45,7 +45,7 @@ function swgradient!( smooth_radius::Int=5, logger::Union{Nothing, AbstractLogger}=nothing )::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end @@ -91,9 +91,9 @@ Bigger values speed up computation at the cost of using more memory. See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). See also [`swforward!`](@ref) and [`swmisfit!`](@ref) and [`Shot`](@ref). """ -function swgradient!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; +function swgradient!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::Union{Dict{String, Array{T, N}}, - Tuple{Dict{String, Array{T, N}}, T}} where {T, N} + Tuple{Dict{String, Array{T, N}}, T}} where {T, N} if logger === nothing logger = current_logger() end diff --git a/src/apis/misfit.jl b/src/apis/misfit.jl index 44312da..19daf1f 100644 --- a/src/apis/misfit.jl +++ b/src/apis/misfit.jl @@ -64,7 +64,7 @@ Receivers traces are stored in the receivers for each shot. See also [`build_wav See also [`InputParameters`](@ref), [`MaterialProperties`](@ref) and [`Shot`](@ref). See also [`swforward!`](@ref) and [`swgradient!`](@ref) and [`Shot`](@ref). """ -function swmisfit!(wavesim::Union{WaveSimulation{T,N}, Vector{<:WaveSimulation{T,N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; +function swmisfit!(wavesim::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; logger::Union{Nothing, AbstractLogger}=nothing, kwargs...)::T where {T, N} if logger === nothing logger = current_logger() diff --git a/src/inversion/misfits/L2Misfit.jl b/src/inversion/misfits/L2Misfit.jl index e5162e7..79a5116 100644 --- a/src/inversion/misfits/L2Misfit.jl +++ b/src/inversion/misfits/L2Misfit.jl @@ -23,6 +23,27 @@ function (misfit::L2Misfit)(recs::ScalarReceivers{T}, matprop::MaterialPropertie return msf end +function (misfit::L2Misfit)(recs::VectorReceivers{T, N}, matprop::MaterialProperties{T}) where {T, N} + # Compute residuals + residuals = recs.seismograms - recs.observed + # Window residuals using mask + mask = ones(T, size(residuals, 1)) + if length(recs.windows) > 0 + for wnd in recs.windows + mask[wnd.first:wnd.second] .= 2 + end + mask .-= 1 + end + residuals .= mask .* residuals + # Inner product using inverse covariance matrix + msf = sum([dot(residuals[:,i,:], recs.invcov, residuals[:,i,:]) for i in 1:N]) / 2 + # Add regularization if needed + if misfit.regularization !== nothing + msf += misfit.regularization(matprop) + end + return msf +end + function dχ_du(_::L2Misfit, recs::ScalarReceivers{T}) where {T} # Compute residuals residuals = recs.seismograms - recs.observed @@ -37,4 +58,23 @@ function dχ_du(_::L2Misfit, recs::ScalarReceivers{T}) where {T} residuals .= mask .* residuals # Multiply with inverse of covariance matrix return recs.invcov * residuals +end + +function dχ_du(_::L2Misfit, recs::VectorReceivers{T}) where {T} + # Compute residuals + residuals = recs.seismograms - recs.observed + # Window residuals using mask + mask = ones(T, size(residuals, 1)) + if length(recs.windows) > 0 + for wnd in recs.windows + mask[wnd.first:wnd.second] .= 2 + end + mask .-= 1 + end + residuals .= mask .* residuals + # Multiply with inverse of covariance matrix + for d in axes(residuals, 2) + residuals[:,d,:] .= recs.invcov * residuals[:,d,:] + end + return residuals end \ No newline at end of file diff --git a/src/inversion/regularizations/ZerothOrderTikhonovRegularization.jl b/src/inversion/regularizations/ZerothOrderTikhonovRegularization.jl index a90a25c..494e33e 100644 --- a/src/inversion/regularizations/ZerothOrderTikhonovRegularization.jl +++ b/src/inversion/regularizations/ZerothOrderTikhonovRegularization.jl @@ -3,14 +3,14 @@ Base.@kwdef struct ZerothOrderTikhonovRegularization{T, M <: MaterialProperties{ alpha::T end -function (regularization::ZerothOrderTikhonovRegularization{T, VpAcousticCDMaterialProperties{T, N}})(matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +function (regularization::ZerothOrderTikhonovRegularization{T, M})(matprop::M) where {T, N, M <: VpAcousticCDMaterialProperties{T, N}} vp = matprop.vp vp_prior = regularization.matprop_prior.vp vp_norm_sq = norm(vp - vp_prior)^2 return regularization.alpha / 2 * vp_norm_sq end -function (regularization::ZerothOrderTikhonovRegularization{T, VpRhoAcousticVDMaterialProperties{T, N}})(matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +function (regularization::ZerothOrderTikhonovRegularization{T, M})(matprop::M) where {T, N, M <: VpRhoAcousticVDMaterialProperties{T, N}} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp @@ -20,16 +20,29 @@ function (regularization::ZerothOrderTikhonovRegularization{T, VpRhoAcousticVDMa return regularization.alpha / 2 * (vp_norm_sq + rho_norm_sq) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{T, VpAcousticCDMaterialProperties{T, N}}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +function (regularization::ZerothOrderTikhonovRegularization{T, M})(matprop::M) where {T, N, M <: ElasticIsoMaterialProperties{T, N}} + ρ, λ, μ = matprop.ρ, matprop.λ, matprop.μ + ρ_prior, λ_prior, μ_prior = regularization.matprop_prior.ρ, regularization.matprop_prior.λ, regularization.matprop_prior.μ + ρ_norm_sq, λ_norm_sq, μ_norm_sq = norm(ρ - ρ_prior)^2, norm(λ - λ_prior)^2, norm(μ - μ_prior)^2 + return regularization.alpha / 2 * (ρ_norm_sq + λ_norm_sq + μ_norm_sq) +end + +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{T, M}, matprop::M) where {T, N, M <: VpAcousticCDMaterialProperties{T, N}} vp = matprop.vp vp_prior = regularization.matprop_prior.vp - return regularization.alpha * (vp - vp_prior) + return @. regularization.alpha * (vp - vp_prior) end -function dχ_dm(regularization::ZerothOrderTikhonovRegularization{T, VpRhoAcousticVDMaterialProperties{T, N}}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{T, M}, matprop::M) where {T, N, M <: VpRhoAcousticVDMaterialProperties{T, N}} vp = matprop.vp rho = matprop.rho vp_prior = regularization.matprop_prior.vp rho_prior = regularization.matprop_prior.rho - return regularization.alpha * (vp - vp_prior), regularization.alpha * (rho - rho_prior) + return @. regularization.alpha * (vp - vp_prior), regularization.alpha * (rho - rho_prior) +end + +function dχ_dm(regularization::ZerothOrderTikhonovRegularization{T, M}, matprop::M) where {T, N, M <: ElasticIsoMaterialProperties{T, N}} + ρ, λ, μ = matprop.ρ, matprop.λ, matprop.μ + ρ_prior, λ_prior, μ_prior = regularization.matprop_prior.ρ, regularization.matprop_prior.λ, regularization.matprop_prior.μ + return @. regularization.alpha * (ρ - ρ_prior), regularization.alpha * (λ - λ_prior), regularization.alpha * (μ - μ_prior) end \ No newline at end of file diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index c68d5b1..5de9337 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -181,9 +181,10 @@ end # Get gradients copyto!(gradient_m0, grid.fields["grad_m0"].value) for i in eachindex(grid.fields["grad_m1_stag"].value) - # Accumulate and interpolate staggered gradients - gradient_m1[CartesianIndices(Tuple(j == i ? (2:grid.size[j]-1) : (1:grid.size[j]) for j in 1:N))] .+= - interp(model.matprop.interp_method, Array(grid.fields["grad_m1_stag"].value[i]), i) + # Accumulate and back interpolate staggered gradients + gradient_m1 .+= back_interp(model.matprop.interp_method, 1 ./ model.matprop.rho, Array(grid.fields["grad_m1_stag"].value[i]), i) + # gradient_m1[CartesianIndices(Tuple(j == i ? (2:grid.size[j]-1) : (1:grid.size[j]) for j in 1:N))] .+= + # interp(model.matprop.interp_method, Array(grid.fields["grad_m1_stag"].value[i]), i) end # Smooth gradients backend.smooth_gradient!(gradient_m0, possrcs, model.smooth_radius) diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 2e153f5..db5c361 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -47,7 +47,7 @@ end precompute_fact!(model::AcousticCDWaveSimulation) = copyto!(model.grid.fields["fact"].value, (model.dt^2) .* (model.matprop.vp .^ 2)) -init_gradient(model::AcousticCDWaveSimulation{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp)) +init_gradient(model::AcousticCDWaveSimulation) = Dict("vp" => zero(model.matprop.vp)) accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticCDWaveSimulation{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} = totgrad["vp"] .+= curgrad["vp"] @@ -137,7 +137,10 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac addfield!( grid, "ψ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat( + [[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; + dims=1 + ) ) ) addfield!( @@ -150,13 +153,21 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac addfield!( grid, "ψ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat( + [ + [backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N + ]...; + dims=1 + ) ) ) addfield!( grid, "ξ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat( + [[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; + dims=1 + ) ) ) end @@ -293,7 +304,7 @@ end end end -init_gradient(model::AcousticVDStaggeredWaveSimulation{N, T}) where {N, T} = Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) +init_gradient(model::AcousticVDStaggeredWaveSimulation) = Dict("vp" => zero(model.matprop.vp), "rho" => zero(model.matprop.rho)) function accumulate_gradient!(totgrad::D, curgrad::D, ::AcousticVDStaggeredWaveSimulation{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} totgrad["vp"] .+= curgrad["vp"] @@ -394,7 +405,10 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < addfield!( grid, "ψ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat( + [[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; + dims=1 + ) ) ) addfield!( @@ -407,13 +421,21 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < addfield!( grid, "ψ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat( + [ + [backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N + ]...; + dims=1 + ) ) ) addfield!( grid, "ξ_adj" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + cat( + [[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; + dims=1 + ) ) ) end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index d149bdd..748bd9e 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -259,10 +259,10 @@ function update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, # vx derivative only in x so no problem ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd - ∂vz∂z_bkd = -(1.0 - 2.0 * μ_ihalf[i, j] / λ_ihalf[i, j]) * ∂vx∂x_fwd + ∂vz∂z_bkd = -(λ_ihalf[i, j] / (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j])) * ∂vx∂x_fwd # σxx - # σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd - σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] - λ_ihalf[i, j] / (λ_ihalf[i, j] + 2 + μ_ihalf[i, j]) + 2 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i, j] * dt * ∂vz∂z_bkd # σzz σzz[i, j] = 0.0 # we are on the free surface! end @@ -535,6 +535,16 @@ function adjoint_onestep_CPML!( factx = 1.0 / (24.0 * dx) factz = 1.0 / (24.0 * dz) + # update stresses σxx and σzz + update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, + ψ_∂vx∂x, ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + # update stress σxz + update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + # update velocity vx update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x, b_z, a_x, a_z, freetop) @@ -545,15 +555,6 @@ function adjoint_onestep_CPML!( # inject sources (external body force) inject_vel_sources2D!(vx, vz, residuals_bk, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, it) - # update stresses σxx and σzz - update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, - vx, vz, dt, λ_ihalf, μ_ihalf, - ψ_∂vx∂x, ψ_∂vz∂z, - b_x_half, b_z, a_x_half, a_z, freetop) - # update stress σxz - update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, - μ_jhalf, b_x, b_z_half, - ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) return end @@ -574,9 +575,9 @@ function inject_momten_sources2D!(σxx, σzz, σxz, Mxx, Mzz, Mxz, srctf_bk, dt, s, isrc, jsrc = srccoeij_bk[p, :] # update stresses on points computed from sinc interpolation # scaled with the coefficients' values - σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] * dt - σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] * dt - σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] + σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] + σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] end # for s in axes(possrcs_bk, 1) @@ -594,8 +595,8 @@ function inject_vel_sources2D!(vx, vz, f, srccoeij_bk, srccoeval_bk, ρ, ρ_ihal nsrcpts = size(srccoeij_bk, 1) for p in 1:nsrcpts s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] - vx[isrc, jsrc] += srccoeval_bk[s] * f[it, 1, s] * dt / ρ[isrc, jsrc] - vz[isrc, jsrc] += srccoeval_bk[s] * f[it, 2, s] * dt / ρ_ihalf_jhalf[isrc, jsrc] + vx[isrc, jsrc] += srccoeval_bk[p] * f[it, 1, s] * dt / ρ[isrc, jsrc] + vz[isrc, jsrc] += srccoeval_bk[p] * f[it, 2, s] * dt / ρ_ihalf_jhalf[isrc, jsrc] end return nothing end @@ -624,27 +625,87 @@ function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) return end -function correlate_gradient_ρ_kernel!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, _dt2) - @. curgrad_ρ += adjv * (v_curr - 2 * v_old + v_veryold) * _dt2 +function correlate_gradient_ρ_kernel!(grad_ρ, adjv, v_curr, v_old, _dt) + @. grad_ρ = grad_ρ + adjv * (v_old - v_curr) * _dt + + return nothing +end + +function correlate_gradient_ihalf_kernel!(grad_λ_ihalf, grad_μ_ihalf, adjσxx, adjσzz, vx, vz, λ_ihalf, μ_ihalf, factx, factz, freetop, nx, nz) + for j in 1:nz-1 + for i in 2:nx-2 + ∂vx∂x_fwd = ∂vz∂z_bkd = 0 + if freetop == true + # j=1: we are on the free surface! + if j == 1 + # vx derivative only in x so no problem + ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx + # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd + ∂vz∂z_bkd = -(λ_ihalf[i, j] / (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j])) * ∂vx∂x_fwd + end + # j=2: we are just below the surface (1/2) + if j == 2 + # vx derivative only in x so no problem + ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx + # zero velocity above the free surface + ∂vz∂z_bkd = (0.0 - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) * factz + end + end + if j >= 3 + ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx + ∂vz∂z_bkd = (vz[i, j-2] - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) * factz + end + # correlate + grad_λ_ihalf[i, j] += -((∂vx∂x_fwd + ∂vz∂z_bkd) * (adjσxx[i, j] + adjσzz[i, j])) + grad_μ_ihalf[i, j] += (-2 * ∂vx∂x_fwd * adjσxx[i, j]) + (-2 * ∂vz∂z_bkd * adjσzz[i, j]) + end + end + return nothing end -function correlate_gradient_ρ!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, dt) - _dt2 = 1 / dt^2 - adjvx = adjv[1] - vx_curr = v_curr[1] - vx_old = v_old[1] - vx_veryold = v_veryold[1] - correlate_gradient_ρ_kernel!(curgrad_ρ, adjvx, vx_curr, vx_old, vx_veryold, _dt2) +function correlate_gradient_jhalf_kernel!(grad_μ_jhalf, adjσxz, vx, vz, factx, factz, freetop, nx, nz) + for j in 1:nz-2 + for i in 3:nx-1 + ∂vx∂z_fwd = ∂vz∂x_bkd = 0 + if freetop + if j == 1 + # zero velocity above the free surface + ∂vx∂z_fwd = factz * (0.0 - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) + # vz derivative only in x so no problem + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) + end + end + if j >= 2 + ∂vx∂z_fwd = factz * (vx[i, j-1] - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) + end + # correlate + grad_μ_jhalf[i, j] += (-∂vx∂z_fwd-∂vz∂x_bkd) * adjσxz[i, j] + end + end + + return nothing end -function correlate_gradient_ρ_ihalf_jhalf!(curgrad_ρ_ihalf_jhalf, adjv, v_curr, v_old, v_veryold, dt) - _dt2 = 1 / dt^2 - adjvz = adjv[2] - vz_curr = v_curr[2] - vz_old = v_old[2] - vz_veryold = v_veryold[2] - correlate_gradient_ρ_kernel!(curgrad_ρ_ihalf_jhalf, adjvz, vz_curr, vz_old, vz_veryold, _dt2) +@views function correlate_gradients!(grid, vcurr, vold, dt, freetop) + nx, nz = grid.size + correlate_gradient_ρ_kernel!(grid.fields["grad_ρ"].value, grid.fields["adjv"].value[1], vcurr[1], vold[1], 1 / dt) + correlate_gradient_ρ_kernel!(grid.fields["grad_ρ_ihalf_jhalf"].value, grid.fields["adjv"].value[2], vcurr[2], vold[2], 1 / dt) + correlate_gradient_ihalf_kernel!( + grid.fields["grad_λ_ihalf"].value, + grid.fields["grad_μ_ihalf"].value, + grid.fields["adjσ"].value[1], grid.fields["adjσ"].value[2], vcurr..., + grid.fields["λ_ihalf"].value, grid.fields["μ_ihalf"].value, + (1.0 ./ (24.0 .* grid.spacing))..., + freetop, nx, nz + ) + correlate_gradient_jhalf_kernel!( + grid.fields["grad_μ_jhalf"].value, + grid.fields["adjσ"].value[3], vcurr..., + (1.0 ./ (24.0 .* grid.spacing))..., + freetop, nx, nz + ) end ######################################### diff --git a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl index bab247e..6427222 100644 --- a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl +++ b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl @@ -1,23 +1,74 @@ -@parallel function correlate_gradient_ρ_kernel!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, _dt2) - @all(curgrad_ρ) = @all(curgrad_ρ) + (@all(adjv) * (@all(v_curr) - 2 * @all(v_old) + @all(v_veryold)) * _dt2) +@parallel function correlate_gradient_ρ_kernel!(grad_ρ, adjv, v_curr, v_old, _dt) + @all(grad_ρ) = @all(grad_ρ) + (@all(adjv) * (@all(v_old) - @all(v_curr)) * _dt) return nothing end -@views function correlate_gradient_ρ!(curgrad_ρ, adjv, v_curr, v_old, v_veryold, dt) - _dt2 = 1 / dt^2 - adjvx = adjv[1] - vx_curr = v_curr[1] - vx_old = v_old[1] - vx_veryold = v_veryold[1] - @parallel correlate_gradient_ρ_kernel!(curgrad_ρ, adjvx, vx_curr, vx_old, vx_veryold, _dt2) +@parallel_indices (i, j) function correlate_gradient_ihalf_kernel!(grad_λ_ihalf, grad_μ_ihalf, adjσxx, adjσzz, vx, vz, λ_ihalf, μ_ihalf, factx, factz, freetop) + ∂vx∂x_fwd = ∂vz∂z_bkd = 0 + if freetop == true + # j=1: we are on the free surface! + if j == 1 + # vx derivative only in x so no problem + ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx + # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd + ∂vz∂z_bkd = -(λ_ihalf[i, j] / (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j])) * ∂vx∂x_fwd + end + # j=2: we are just below the surface (1/2) + if j == 2 + # vx derivative only in x so no problem + ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx + # zero velocity above the free surface + ∂vz∂z_bkd = (0.0 - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) * factz + end + end + if j >= 3 + ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx + ∂vz∂z_bkd = (vz[i, j-2] - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) * factz + end + # correlate + grad_λ_ihalf[i, j] += -((∂vx∂x_fwd + ∂vz∂z_bkd) * (adjσxx[i, j] + adjσzz[i, j])) + grad_μ_ihalf[i, j] += (-2 * ∂vx∂x_fwd * adjσxx[i, j]) + (-2 * ∂vz∂z_bkd * adjσzz[i, j]) + + return nothing end -@views function correlate_gradient_ρ_ihalf_jhalf!(curgrad_ρ_ihalf_jhalf, adjv, v_curr, v_old, v_veryold, dt) - _dt2 = 1 / dt^2 - adjvz = adjv[2] - vz_curr = v_curr[2] - vz_old = v_old[2] - vz_veryold = v_veryold[2] - @parallel correlate_gradient_ρ_kernel!(curgrad_ρ_ihalf_jhalf, adjvz, vz_curr, vz_old, vz_veryold, _dt2) +@parallel_indices (i, j) function correlate_gradient_jhalf_kernel!(grad_μ_jhalf, adjσxz, vx, vz, factx, factz, freetop) + ∂vx∂z_fwd = ∂vz∂x_bkd = 0 + if freetop + if j == 1 + # zero velocity above the free surface + ∂vx∂z_fwd = factz * (0.0 - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) + # vz derivative only in x so no problem + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) + end + end + if j >= 2 + ∂vx∂z_fwd = factz * (vx[i, j-1] - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) + ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) + end + # correlate + grad_μ_jhalf[i, j] += (-∂vx∂z_fwd-∂vz∂x_bkd) * adjσxz[i, j] + + return nothing end + +@views function correlate_gradients!(grid, vcurr, vold, dt, freetop) + nx, nz = grid.size + @parallel correlate_gradient_ρ_kernel!(grid.fields["grad_ρ"].value, grid.fields["adjv"].value[1], vcurr[1], vold[1], 1 / dt) + @parallel correlate_gradient_ρ_kernel!(grid.fields["grad_ρ_ihalf_jhalf"].value, grid.fields["adjv"].value[2], vcurr[2], vold[2], 1 / dt) + @parallel (2:nx-2, 1:nz-1) correlate_gradient_ihalf_kernel!( + grid.fields["grad_λ_ihalf"].value, + grid.fields["grad_μ_ihalf"].value, + grid.fields["adjσ"].value[1], grid.fields["adjσ"].value[2], vcurr..., + grid.fields["λ_ihalf"].value, grid.fields["μ_ihalf"].value, + (1.0 ./ (24.0 .* grid.spacing))..., + freetop + ) + @parallel (3:nx-1, 1:nz-2) correlate_gradient_jhalf_kernel!( + grid.fields["grad_μ_jhalf"].value, + grid.fields["adjσ"].value[3], vcurr..., + (1.0 ./ (24.0 .* grid.spacing))..., + freetop + ) +end \ No newline at end of file diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 5366485..cd70da0 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -48,7 +48,25 @@ return nothing end -@parallel_indices (i, j) function update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) +@parallel_indices (i, j) function update_4thord_vz!( + nx, + nz, + halo, + vz, + factx, + factz, + σxz, + σzz, + dt, + ρ_ihalf_jhalf, + ψ_∂σxz∂x, + ψ_∂σzz∂z, + b_x_half, + b_z_half, + a_x_half, + a_z_half, + freetop +) if freetop && j <= 2 # σxz derivative only in x so no problem ∂σxz∂x_fwd = factx * (σxz[i-1, j] - 27.0 * σxz[i, j] + 27.0 * σxz[i+1, j] - σxz[i+2, j]) @@ -116,10 +134,10 @@ end # vx derivative only in x so no problem ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd - ∂vz∂z_bkd = -(1.0 - 2.0 * μ_ihalf[i, j] / λ_ihalf[i, j]) * ∂vx∂x_fwd + ∂vz∂z_bkd = -(λ_ihalf[i, j] / (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j])) * ∂vx∂x_fwd # σxx - # σxx[i,j] = σxx[i,j] + (λ_ihalf[i,j]+2.0*μ_ihalf[i,j]) * dt * ∂vx∂x_fwd + λ_ihalf[i,j] * dt * ∂vz∂z_bkd - σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] - λ_ihalf[i, j] / (λ_ihalf[i, j] + 2 + μ_ihalf[i, j]) + 2 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + + λ_ihalf[i, j] * dt * ∂vz∂z_bkd # σzz σzz[i, j] = 0.0 # we are on the free surface! end @@ -243,30 +261,28 @@ end @parallel_indices (p) function inject_momten_sources2D!(σxx, σzz, σxz, Mxx, Mzz, Mxz, srctf_bk, dt, srccoeij_bk, srccoeval_bk, it) s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] - σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] * dt - σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] * dt - σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] * dt + σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] + σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] + σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] return nothing end -@parallel_indices (p) function inject_vel_sources2D!(vx, vz, f, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, it) +@parallel_indices (p) function inject_vel_sources2D!(vx, vz, f, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, dt, it) s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] - vx[isrc, jsrc] += srccoeval_bk[s] * f[it, 1, s] * dt / ρ[isrc, jsrc] - vz[isrc, jsrc] += srccoeval_bk[s] * f[it, 2, s] * dt / ρ_ihalf_jhalf[isrc, jsrc] + vx[isrc, jsrc] += srccoeval_bk[p] * f[it, 1, s] * dt / ρ[isrc, jsrc] + vz[isrc, jsrc] += srccoeval_bk[p] * f[it, 2, s] * dt / ρ_ihalf_jhalf[isrc, jsrc] return nothing end - @parallel_indices (p) function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) - r, irec, jrec = reccoeij_bk[p, 1], reccoeij_bk[p, 2], reccoeij_bk[p, 3] + r, irec, jrec = reccoeij_bk[p, 1], reccoeij_bk[p, 2], reccoeij_bk[p, 3] traces_bk[it, 1, r] += reccoeval_bk[p] * vx[irec, jrec] traces_bk[it, 2, r] += reccoeval_bk[p] * vz[irec, jrec] - + return nothing end - function forward_onestep_CPML!( model, srccoeij_bk, @@ -393,17 +409,6 @@ function adjoint_onestep_CPML!( # Precomputing divisions factx = 1.0 / (24.0 * dx) factz = 1.0 / (24.0 * dz) - - # update velocity vx - @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, - b_x, b_z, a_x, a_z, freetop) - # update velocity vz - @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, - ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) - - # inject sources (residuals as velocities) - nsrcpts = size(srccoeij_bk, 1) - @parallel (1:nsrcpts) inject_vel_sources2D!(vx, vz, residuals_bk, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, it) # update stresses σxx and σzz @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, @@ -415,5 +420,17 @@ function adjoint_onestep_CPML!( μ_jhalf, b_x, b_z_half, ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + # update velocity vx + @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, + b_x, b_z, a_x, a_z, freetop) + # update velocity vz + @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, + ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + + # inject sources (residuals as velocities) + nsrcpts = size(srccoeij_bk, 1) + @parallel (1:nsrcpts) inject_vel_sources2D!(vx, vz, residuals_bk, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, dt, it) + + return end \ No newline at end of file diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 3945ccf..e6295a0 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -6,23 +6,8 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound model::ElasticIsoCPMLWaveSimulation{T, 2}, shot::MomentTensorShot{T, 2, MomentTensor2D{T}} ) where {T} - - # scale source time function, etc. - # find nearest grid points indexes for both sources and receivers - # possrcs = find_nearest_grid_points(model, shot.srcs.positions) - # posrecs = find_nearest_grid_points(model, shot.recs.positions) - - # interpolation coefficients for sources - srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.srcs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - # interpolation coefficients for receivers - reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - - # source time function - srctf = shot.srcs.tf + # scale source time function + srccoeij, srccoeval, reccoeij, reccoeval, srctf = possrcrec_scaletf(model, shot) # moment tensors momtens = shot.srcs.momtens @@ -37,9 +22,9 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound srccoeval_bk = backend.Data.Array(srccoeval) reccoeij_bk = backend.Data.Array(reccoeij) reccoeval_bk = backend.Data.Array(reccoeval) - + srctf_bk = backend.Data.Array(srctf) - traces_bk = backend.Data.Array(shot.recs.seismograms) + traces_bk = backend.zeros(T, size(shot.recs.seismograms)) ## ONLY 2D for now!!! nsrcs = length(momtens) @@ -53,15 +38,15 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound # Time loop for it in 1:nt backend.forward_onestep_CPML!(model, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, - srctf_bk, - traces_bk, - it, - Mxx_bk, Mzz_bk, Mxz_bk; - save_trace=true) + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + traces_bk, + it, + Mxx_bk, Mzz_bk, Mxz_bk; + save_trace=true) # Print timestep info if it % model.infoevery == 0 diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index 9823ecc..efdd57f 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -1,21 +1,14 @@ +swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = + swgradient_1shot!(BoundaryConditionTrait(model), model, args...; kwargs...) + @views function swgradient_1shot!( ::CPMLBoundaryCondition, model::ElasticIsoCPMLWaveSimulation{T, 2}, shot::MomentTensorShot{T, 2, MomentTensor2D{T}}, - misfit + misfit::AbstractMisfit )::Dict{String, Array{T, 2}} where {T} - - # interpolation coefficients for sources - srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.srcs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - # interpolation coefficients for receivers - reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - - # source time function - srctf = shot.srcs.tf + # scale source time function + srccoeij, srccoeval, reccoeij, reccoeval, srctf = possrcrec_scaletf(model, shot) # moment tensors momtens = shot.srcs.momtens @@ -31,9 +24,9 @@ srccoeval_bk = backend.Data.Array(srccoeval) reccoeij_bk = backend.Data.Array(reccoeij) reccoeval_bk = backend.Data.Array(reccoeval) - + srctf_bk = backend.Data.Array(srctf) - traces_bk = backend.Data.Array(shot.recs.seismograms) + traces_bk = backend.zeros(T, size(shot.recs.seismograms)) ## ONLY 2D for now!!! nsrcs = length(momtens) @@ -48,15 +41,15 @@ for it in 1:nt # Compute one forward step backend.forward_onestep_CPML!(model, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, - srctf_bk, - traces_bk, - it, - Mxx_bk, Mzz_bk, Mxz_bk; - save_trace=true) + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + traces_bk, + it, + Mxx_bk, Mzz_bk, Mxz_bk; + save_trace=true) # Print timestep info if it % model.infoevery == 0 @@ -89,17 +82,19 @@ # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step - backend.adjoint_onestep_CPML!(model, - reccoeij_bk, - reccoeval_bk, - residuals_bk, - it) + backend.adjoint_onestep_CPML!( + model, + reccoeij_bk, + reccoeval_bk, + residuals_bk, + it + ) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Backward iteration: %d", it) end # Check if out of save buffer - if !issaved(checkpointer, "v", it - 2) + if !issaved(checkpointer, "v", it - 1) @debug @sprintf("Out of save buffer at iteration: %d", it) initrecover!(checkpointer) copyto!(grid.fields["σ"], getsaved(checkpointer, "σ", checkpointer.curr_checkpoint)) @@ -111,16 +106,16 @@ recover!( checkpointer, recit -> begin - backend.forward_onestep_CPML!(model, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, - srctf_bk, - nothing, - it, - Mxx_bk, Mzz_bk, Mxz_bk; - save_trace=false) + backend.forward_onestep_CPML!(model, + srccoeij_bk, + srccoeval_bk, + reccoeij_bk, + reccoeval_bk, + srctf_bk, + nothing, + it, + Mxx_bk, Mzz_bk, Mxz_bk; + save_trace=false) return ["v" => grid.fields["v"]] end ) @@ -128,11 +123,8 @@ # Get velocity fields from saved buffer v_curr = getsaved(checkpointer, "v", it).value v_old = getsaved(checkpointer, "v", it - 1).value - v_veryold = getsaved(checkpointer, "v", it - 2).value # Correlate for gradient computation - backend.correlate_gradient_ρ!(grid.fields["grad_ρ"].value, grid.fields["adjv"].value, v_curr, v_old, v_veryold, dt) - backend.correlate_gradient_ρ_ihalf_jhalf!(grid.fields["grad_ρ_ihalf_jhalf"].value, grid.fields["adjv"].value, v_curr, v_old, v_veryold, dt) - # TODO add other correlations + backend.correlate_gradients!(grid, v_curr, v_old, model.dt, model.cpmlparams.freeboundtop) end # Allocate gradients gradient_ρ = zeros(T, grid.size...) @@ -140,15 +132,20 @@ gradient_μ = zeros(T, grid.size...) # Get gradients copyto!(gradient_ρ, grid.fields["grad_ρ"].value) - # TODO compute chain rule for ρ_ihalf_jhalf to ρ - gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, Array(grid.fields["grad_ρ_ihalf_jhalf"].value), [1, 2]) + # Compute chain rules for back interpolations + gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf_jhalf"].value), [1, 2]) + gradient_λ .+= back_interp(model.matprop.interp_method_λ, model.matprop.λ, Array(grid.fields["grad_λ_ihalf"].value), 1) + gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf"].value), 1) .+ + back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_jhalf"].value), 2) + + @show maximum(gradient_ρ), maximum(gradient_λ), maximum(gradient_μ) # TODO smooth gradients # Compute regularization if needed - ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) + ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) # Return gradients return Dict( "rho" => gradient_ρ .+ ∂χ_∂ρ, "lambda" => gradient_λ .+ ∂χ_∂λ, - "mu" => gradient_μ .+ ∂χ_∂μ, + "mu" => gradient_μ .+ ∂χ_∂μ ) end \ No newline at end of file diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl index 7d53d0f..aa85256 100644 --- a/src/models/elastic/ela_init_bc.jl +++ b/src/models/elastic/ela_init_bc.jl @@ -14,7 +14,7 @@ init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimulation, srcs::Sou #@show n,typeof(model.cpmlcoeffs[n]) compute_CPML_coefficientsAxis!( model.cpmlcoeffs[n], - get_maximum_func(model)(sqrt.((model.matprop.λ + 2.0 * model.matprop.μ) ./ model.matprop.ρ)), + get_maximum_func(model)(sqrt.((model.matprop.λ .+ 2.0 .* model.matprop.μ) ./ model.matprop.ρ)), model.dt, model.cpmlparams.halo, model.cpmlparams.rcoef, diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index a1c4dd2..db2d563 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -6,7 +6,7 @@ Material properties for elastic isotropic simulation. $(TYPEDFIELDS) """ -Base.@kwdef struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIsoMaterialProperties{T, N} +Base.@kwdef mutable struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIsoMaterialProperties{T, N} "First Lamé parameter" λ::Array{T, N} "Second Lamé parameter (shear modulus)" @@ -15,4 +15,8 @@ Base.@kwdef struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIsoMaterial ρ::Array{T, N} "Interpolation method for density" interp_method_ρ::InterpolationMethod = ArithmeticAverageInterpolation(2) + "Interpolation method for density" + interp_method_λ::InterpolationMethod = ArithmeticAverageInterpolation(2) + "Interpolation method for density" + interp_method_μ::InterpolationMethod = ArithmeticAverageInterpolation(2) end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 9cc9d17..3c929e7 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,21 +2,37 @@ # Functions for all ElasticIsoWaveSimulation subtypes +# Scaling for ElasticIsoWaveSimulation +@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T}) where {T} + # interpolation coefficients for sources + srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, + shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for receivers + reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, + shot.recs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # scale source time function with boxcar and timestep size + scal_srctf = shot.srcs.tf ./ prod(model.grid.spacing) .* model.dt + + return srccoeij, srccoeval, reccoeij, reccoeval, scal_srctf +end + @views function check_matprop(model::ElasticIsoWaveSimulation{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Checks - vp = sqrt.((matprop.λ .+ 2.0 * matprop.μ) ./ matprop.ρ) - @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" - @assert size(vp) == model.grid.size "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.size)" @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" @assert all(matprop.ρ .> 0) "Density must be positive!" + vp = sqrt.((matprop.λ .+ 2.0 .* matprop.μ) ./ matprop.ρ) + @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" + @assert size(vp) == model.grid.size "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.size)" # Check courant condition vel_max = get_maximum_func(model)(vp) tmp = sqrt.(sum(1 ./ model.grid.spacing .^ 2)) - courant = vel_max * model.dt * tmp + courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil @info "Courant number: $(courant)" - if courant > 1.0 + if courant > 1 @warn "Courant condition not satisfied! [$(courant)]" end @@ -47,12 +63,14 @@ end copyto!(model.matprop.λ, matprop.λ) copyto!(model.matprop.μ, matprop.μ) copyto!(model.matprop.ρ, matprop.ρ) - - # the following on device? + model.matprop.interp_method_ρ = matprop.interp_method_ρ + model.matprop.interp_method_λ = matprop.interp_method_λ + model.matprop.interp_method_μ = matprop.interp_method_μ + # Precompute factors precomp_elaprop!(model) end -function precomp_elaprop!(model::ElasticIsoWaveSimulation{T, 2}; harmonicaver_μ=true) where {T} +function precomp_elaprop!(model::ElasticIsoWaveSimulation{T, 2}) where {T} # Excract fields ρ, λ, μ = model.grid.fields["ρ"].value, model.grid.fields["λ"].value, model.grid.fields["μ"].value ρ_ihalf_jhalf = model.grid.fields["ρ_ihalf_jhalf"].value @@ -66,23 +84,10 @@ function precomp_elaprop!(model::ElasticIsoWaveSimulation{T, 2}; harmonicaver_μ #------------------------------------------------------------- # pre-interpolate properties at half distances between nodes #------------------------------------------------------------- - # ρ_ihalf_jhalf (nx-1,nz-1) ?? - # arithmetic mean for ρ copyto!(ρ_ihalf_jhalf, interp(model.matprop.interp_method_ρ, model.matprop.ρ, [1, 2])) - # μ_ihalf (nx-1,nz) ?? - # μ_ihalf (nx,nz-1) ?? - if harmonicaver_μ == true - # harmonic mean for μ - @. μ_ihalf = 1.0 ./ (1.0 ./ μ[2:end, :] .+ 1.0 ./ μ[1:end-1, :]) - @. μ_jhalf = 1.0 ./ (1.0 ./ μ[:, 2:end] .+ 1.0 ./ μ[:, 1:end-1]) - else - # arithmetic mean for μ - @. μ_ihalf = (μ[2:end, :] + μ[1:end-1, :]) / 2.0 - @. μ_jhalf = (μ[:, 2:end] + μ[:, 1:end-1]) / 2.0 - end - # λ_ihalf (nx-1,nz) ?? - # arithmetic mean for λ - @. λ_ihalf = (λ[2:end, :] + λ[1:end-1, :]) / 2.0 + copyto!(λ_ihalf, interp(model.matprop.interp_method_λ, model.matprop.λ, 1)) + copyto!(μ_ihalf, interp(model.matprop.interp_method_μ, model.matprop.μ, 1)) + copyto!(μ_jhalf, interp(model.matprop.interp_method_μ, model.matprop.μ, 2)) return end @@ -146,7 +151,7 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac cpmlcoeffs = tuple([CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N]...) # Populate computational grid - if N==2 + if N == 2 # Stress and velocity addfield!(grid, "σ" => MultiVariableField( [backend.zeros(T, gridsize...) for _ in 1:3] @@ -155,26 +160,26 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac [backend.zeros(T, gridsize...) for _ in 1:2] )) # Material properties - addfield!(grid, "λ" => ScalarVariableField( + addfield!(grid, "ρ" => ScalarVariableField( backend.zeros(T, gridsize...) )) - addfield!(grid, "μ" => ScalarVariableField( + addfield!(grid, "λ" => ScalarVariableField( backend.zeros(T, gridsize...) )) - addfield!(grid, "ρ" => ScalarVariableField( + addfield!(grid, "μ" => ScalarVariableField( backend.zeros(T, gridsize...) )) addfield!(grid, "λ_ihalf" => ScalarVariableField( - backend.zeros(T, (gridsize.-[1,0])...) + backend.zeros(T, (gridsize .- [1, 0])...) )) addfield!(grid, "μ_ihalf" => ScalarVariableField( - backend.zeros(T, (gridsize.-[1,0])...) + backend.zeros(T, (gridsize .- [1, 0])...) )) addfield!(grid, "μ_jhalf" => ScalarVariableField( - backend.zeros(T, (gridsize.-[0,1])...) + backend.zeros(T, (gridsize .- [0, 1])...) )) addfield!(grid, "ρ_ihalf_jhalf" => ScalarVariableField( - backend.zeros(T, (gridsize.-1)...) + backend.zeros(T, (gridsize .- 1)...) )) # CPML memory variables grds = [gridsize...] @@ -195,8 +200,6 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac )) # Initialize gradient arrays if needed if gradient - error("Gradient for elastic calculations not yet implemented!") - # Stress and velocity addfield!(grid, "adjσ" => MultiVariableField( [backend.zeros(T, gridsize...) for _ in 1:3] @@ -222,9 +225,17 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac backend.zeros(T, gridsize...) )) addfield!(grid, "grad_ρ_ihalf_jhalf" => ScalarVariableField( - backend.zeros(T, gridsize...) + backend.zeros(T, (gridsize .- 1)...) + )) + addfield!(grid, "grad_λ_ihalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- [1, 0])...) + )) + addfield!(grid, "grad_μ_ihalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- [1, 0])...) + )) + addfield!(grid, "grad_μ_jhalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- [0, 1])...) )) - # TODO add other gradient fields # Initialize checkpointer checkpointer = LinearCheckpointer( @@ -232,11 +243,10 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac check_freq === nothing ? 1 : check_freq, filter(p -> p.first in ["σ", "v", "ψ_∂σ∂x", "ψ_∂σ∂z", "ψ_∂v∂x", "ψ_∂v∂z"], grid.fields), ["v"]; - widths=Dict("v" => 2) + widths=Dict("v" => 1) ) # Save first two timesteps savecheckpoint!(checkpointer, "σ" => grid.fields["σ"], 0) - savecheckpoint!(checkpointer, "v" => grid.fields["v"], -1) savecheckpoint!(checkpointer, "v" => grid.fields["v"], 0) savecheckpoint!(checkpointer, "ψ_∂σ∂x" => grid.fields["ψ_∂σ∂x"], 0) savecheckpoint!(checkpointer, "ψ_∂σ∂z" => grid.fields["ψ_∂σ∂z"], 0) @@ -263,7 +273,6 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac else @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end - return new{T, N, A, V}( params, @@ -293,6 +302,19 @@ end reset!(model.checkpointer) end end + +init_gradient(model::ElasticIsoCPMLWaveSimulation) = Dict( + "rho" => zero(model.matprop.ρ), + "lambda" => zero(model.matprop.λ), + "mu" => zero(model.matprop.μ), +) + +function accumulate_gradient!(totgrad::D, curgrad::D, ::ElasticIsoCPMLWaveSimulation{T, N}) where {T, N, D <: Dict{String, Array{T, N}}} + totgrad["rho"] .+= curgrad["rho"] + totgrad["lambda"] .+= curgrad["lambda"] + totgrad["mu"] .+= curgrad["mu"] +end + ########################################################### # Traits for ElasticIsoCPMLWaveSimulation diff --git a/src/shots/receivers.jl b/src/shots/receivers.jl index 36b4178..b80c225 100644 --- a/src/shots/receivers.jl +++ b/src/shots/receivers.jl @@ -76,13 +76,16 @@ struct VectorReceivers{T, N} <: Receivers{T} observed::Array{T, 3} "Inverse of the covariance matrix" invcov::AbstractMatrix{T} + "Windows of data used for misfit calculations" + windows::Vector{Pair{Int, Int}} function VectorReceivers( positions::Matrix{T}, nt::Int, ndim::Int=2; observed::Union{Array{T}, Nothing}=nothing, - invcov::Union{AbstractMatrix{T}, Nothing}=nothing + invcov::Union{AbstractMatrix{T}, Nothing}=nothing, + windows::Union{Vector{Pair{Int,Int}}, Nothing}=nothing ) where {T} @assert size(positions, 1) > 0 "There must be at least one receiver!" seismograms = zeros(T, nt, ndim, size(positions, 1)) ## N+1 !!! <<<<<<<<--------------<<<< @@ -96,6 +99,13 @@ struct VectorReceivers{T, N} <: Receivers{T} else invcov = zeros(T, 0, 0) end - return new{T, ndim}(positions, seismograms, observed, invcov) + if windows !== nothing + for wnd in windows + @assert 1 <= wnd.first <= wnd.second <= nt "Window $(wnd) is not consistent!" + end + else + windows = [] + end + return new{T, ndim}(positions, seismograms, observed, invcov, windows) end end diff --git a/src/shots/shot.jl b/src/shots/shot.jl index eb0033d..7c7eb94 100644 --- a/src/shots/shot.jl +++ b/src/shots/shot.jl @@ -27,8 +27,6 @@ Base.@kwdef struct MomentTensorShot{T, N, M <: MomentTensor{T, N}} <: Shot{T} recs::VectorReceivers{T, N} end - - ################################################## function init_shot!(model::WaveSimulation{T}, shot::Shot{T}; kwargs...) where {T} diff --git a/src/utils/abstract_types.jl b/src/utils/abstract_types.jl index 2ff5a1a..61edf92 100644 --- a/src/utils/abstract_types.jl +++ b/src/utils/abstract_types.jl @@ -11,7 +11,6 @@ Currently implemented concrete parameters are [`InputParametersAcoustic`](@ref) """ abstract type InputParameters{T, N} end - @doc """ $(TYPEDEF) diff --git a/src/utils/fields.jl b/src/utils/fields.jl index 725b69a..9eeddca 100644 --- a/src/utils/fields.jl +++ b/src/utils/fields.jl @@ -35,7 +35,6 @@ Base.copyto!(dest::MultiVariableField, src::MultiVariableField) = begin end end - setzero!(field::ScalarConstantField{T}) where {T} = (field.value = zero(T); return field) setzero!(field::MultiConstantField{T}) where {T} = (field.value .= zero(T); return field) setzero!(field::ScalarVariableField{T}) where {T} = (field.value .= zero(T); return field) diff --git a/src/utils/interpolations.jl b/src/utils/interpolations.jl new file mode 100644 index 0000000..ffaaade --- /dev/null +++ b/src/utils/interpolations.jl @@ -0,0 +1,52 @@ +interpolate(m::Array{T, N}, interp_method) where {T, N} = collect(interp(interp_method, m, i) for i in 1:N) + +interp(method, m::Array{<:Real, N}, dim::Int) where {N} = interp(method, m, [dim]) +interp(method, m::Array{<:Real, N}, dims::Vector{Int}) where {N} = method(m, dims) + +back_interp(method, m::Array{T, N}, ∂χ∂m_interp::Array{T, N}, dim::Int) where {T, N} = back_interp(method, m, ∂χ∂m_interp, [dim]) +back_interp(method, m::Array{T, N}, ∂χ∂m_interp::Array{T, N}, dims::Vector{Int}) where {T, N} = begin + res = zeros(T, size(m)) + for k in 1:method.width + m_idxs = CartesianIndices(Tuple( + i in dims ? (k:size(res, i)+k-method.width) : (1:size(res, i)) for i in 1:N + )) + res[m_idxs] .+= ∂χ∂m_interp .* ∂f∂m(method, m, k, dims) + end + return res +end + +# Arithmetic average interpolation + +struct ArithmeticAverageInterpolation <: InterpolationMethod + width::Int +end + +@views function (itp::ArithmeticAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} + return sum( + m[CartesianIndices(Tuple(i in dims ? (j:size(m, i)+j-itp.width) : (1:size(m, i)) for i in 1:N))] for j in 1:itp.width + ) ./ (itp.width^length(dims)) +end + +∂f∂m(itp::ArithmeticAverageInterpolation, m::Array{T, N}, _::Int, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (itp.width^length(dims)) + +# Armonic average interpolation + +struct ArmonicAverageInterpolation <: InterpolationMethod + width::Int +end + +@views function (itp::ArmonicAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} + return (itp.width^length(dims)) ./ sum( + 1 ./ m[CartesianIndices(Tuple(i in dims ? (j:size(m, i)+j-itp.width) : (1:size(m, i)) for i in 1:N))] for j in 1:itp.width + ) +end + +function ∂f∂m(itp::ArmonicAverageInterpolation, m::Array{T, N}, k::Int, dims::Vector{Int}) where {T, N} + m_idxs = CartesianIndices(Tuple( + i in dims ? (k:size(m, i)+k-itp.width) : (1:size(m, i)) for i in 1:N + )) + return (itp.width^length(dims)) ./ + sum( + 1 ./ m[CartesianIndices(Tuple(i in dims ? (j:size(m, i)+j-itp.width) : (1:size(m, i)) for i in 1:N))] for j in 1:itp.width + ) .^ 2 .* m[m_idxs] +end \ No newline at end of file diff --git a/src/utils/utils.jl b/src/utils/utils.jl index ad54623..370146b 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -19,44 +19,6 @@ Gaussian source time function for current time `t`, activation time `t0` and dom """ gaussstf(t::Real, t0::Real, f0::Real)::Real = -exp(-(pi * f0 * (t - t0))^2) / (2 * (pi * f0)^2) -struct ArithmeticAverageInterpolation <: InterpolationMethod - width::Int -end - -interpolate(a::Array{T, N}, interp_method) where {T, N} = collect(interp(interp_method, a, i) for i in 1:N) - -@views function interp(method::ArithmeticAverageInterpolation, a::Array{<:Real, N}, dim::Int) where {N} - return sum( - a[CartesianIndices(Tuple(i == dim ? (j:size(a, i)+j-method.width) : (1:size(a, i)) for i in 1:N))] for j in 1:method.width - ) ./ method.width -end - -@views function interp(method::ArithmeticAverageInterpolation, a::Array{<:Real, N}, dims::Vector{Int}) where {N} - return sum( - a[CartesianIndices(Tuple(i in dims ? (j:size(a, i)+j-method.width) : (1:size(a, i)) for i in 1:N))] for j in 1:method.width - ) ./ method.width -end - -@views function back_interp(method::ArithmeticAverageInterpolation, a::Array{T, N}, dim::Int) where {T, N} - res = zeros(T, size(a) .+ [i == dim ? 1 : 0 for i in 1:N]) - for k in 1:method.width - res[CartesianIndices(Tuple( - i == dim ? (k:size(res, i)*k-method.width) : (1:size(res, i)) for i in 1:N - ))] .+= a - end - return res ./ method.width -end - -@views function back_interp(method::ArithmeticAverageInterpolation, a::Array{T, N}, dims::Vector{Int}) where {T, N} - res = zeros(T, size(a) .+ [i in dim ? 1 : 0 for i in 1:N]) - for k in 1:method.width - res[CartesianIndices(Tuple( - i in dims ? (k:size(res, i)*k-method.width) : (1:size(res, i)) for i in 1:N - ))] .+= a - end - return res ./ method.width -end - """ $(TYPEDSIGNATURES) @@ -95,7 +57,6 @@ end return idx_positions end - #################################################################### """ diff --git a/test/runtests.jl b/test/runtests.jl index 58d4d97..a3f4079 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,11 +11,12 @@ using SeismicWaves # Load CUDA only if requested for testing if "CUDA" in ARGS using CUDA + filter!(e -> e != "CUDA", ARGS) end include("utils/setup_models.jl") # Run all tests @testset ExtendedTestSet "SeismicWaves Tests" begin - @includetests + @includetests ARGS end diff --git a/test/test_analytical_vs_numerical_acoustic_constant_density.jl b/test/test_analytical_vs_numerical_acoustic_constant_density.jl index a398ceb..8c6cf74 100644 --- a/test/test_analytical_vs_numerical_acoustic_constant_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_constant_density.jl @@ -5,7 +5,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :CUDA) end if @isdefined(AMDGPU) && AMDGPU.functional() - push!(test_backends, :AMDGPU) + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_analytical_vs_numerical_acoustic_variable_density.jl b/test/test_analytical_vs_numerical_acoustic_variable_density.jl index a548efe..113e667 100644 --- a/test/test_analytical_vs_numerical_acoustic_variable_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_variable_density.jl @@ -11,7 +11,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :CUDA) end if @isdefined(AMDGPU) && AMDGPU.functional() - push!(test_backends, :AMDGPU) + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index b750bb8..ceebbcb 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -11,7 +11,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :CUDA) end if @isdefined(AMDGPU) && AMDGPU.functional() - push!(test_backends, :AMDGPU) + push!(test_backends, :AMDGPU) end for parall in test_backends @@ -38,7 +38,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do # test integral of absolute difference over time is less then a constant 1% error relative to the peak analytical solution @test integrate(times, abs.(numerical_trace .- Gc)) <= maximum(abs.(Gc)) * 0.01 * (dt * nt) end - + @testset "Test 1D $(parall) single-source multiple-receivers CPML" begin # velocity setup c0 = 1000.0 diff --git a/test/test_gradient_acoustic_constant_density.jl b/test/test_gradient_acoustic_constant_density.jl index cf10cde..7a906ae 100644 --- a/test/test_gradient_acoustic_constant_density.jl +++ b/test/test_gradient_acoustic_constant_density.jl @@ -11,7 +11,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :CUDA) end if @isdefined(AMDGPU) && AMDGPU.functional() - push!(test_backends, :AMDGPU) + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_gradient_acoustic_variable_density.jl b/test/test_gradient_acoustic_variable_density.jl index 799952c..ce2c2d3 100644 --- a/test/test_gradient_acoustic_variable_density.jl +++ b/test/test_gradient_acoustic_variable_density.jl @@ -11,7 +11,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :CUDA) end if @isdefined(AMDGPU) && AMDGPU.functional() - push!(test_backends, :AMDGPU) + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_gradient_elastic_constant_density.jl b/test/test_gradient_elastic_constant_density.jl new file mode 100644 index 0000000..93e25a7 --- /dev/null +++ b/test/test_gradient_elastic_constant_density.jl @@ -0,0 +1,61 @@ +using Test +using DSP, NumericalIntegration, LinearAlgebra +using CUDA: CUDA +using Logging +using SeismicWaves + +with_logger(ConsoleLogger(stderr, Logging.Info)) do + test_backends = [:threads] + # test GPU backend only if CUDA is functional + if @isdefined(CUDA) && CUDA.functional() + push!(test_backends, :CUDA) + end + if @isdefined(AMDGPU) && AMDGPU.functional() + push!(test_backends, :AMDGPU) + end + + for parall in test_backends + @testset "Test 2D (P-SV) $(parall) swgradient! with compute misfit" begin + # Physics + ρ0 = 2100.0 + vp0 = 3210.5 + vs0 = vp0 / sqrt(3) + λ0 = ρ0 * (vp0^2 - 2 * vs0^2) + μ0 = ρ0 * vs0^2 + f0 = 12.0 + T = 0.075 + # Numerics + nx = 380 # 211 + nz = 270 # 120 + dx = dz = 4.5 # meters + dt = 0.0005 + nt = ceil(Int, T / dt) + halo = 20 + rcoef = 0.0001 + params, shots, matprop = setup_constant_elastic_2D_CPML(nt, dt, nx, nz, dx, dz, ρ0, λ0, μ0, halo, rcoef, f0) + + # Compute gradient and misfit + grad, misfit = swgradient!( + params, + matprop, + shots; + parall=parall, + check_freq=nothing, + compute_misfit=true + ) + # Compute only misfit + misfit_check = swmisfit!(params, matprop, shots; parall=parall) + + # Check that gradient is non zero + @test !all(g -> g == 0.0, grad["rho"]) + @test !all(g -> g == 0.0, grad["lambda"]) + @test !all(g -> g == 0.0, grad["mu"]) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) + # Check that misfits are equivalent + @show misfit, misfit_check + @test misfit ≈ misfit_check + end + end +end diff --git a/test/test_misfit_acoustic_constant_density.jl b/test/test_misfit_acoustic_constant_density.jl index ec0f6b0..ca922f2 100644 --- a/test/test_misfit_acoustic_constant_density.jl +++ b/test/test_misfit_acoustic_constant_density.jl @@ -11,7 +11,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :CUDA) end if @isdefined(AMDGPU) && AMDGPU.functional() - push!(test_backends, :AMDGPU) + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/test_snapshotting_constant_density.jl b/test/test_snapshotting_constant_density.jl index c9e6371..61ce3b4 100644 --- a/test/test_snapshotting_constant_density.jl +++ b/test/test_snapshotting_constant_density.jl @@ -11,7 +11,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :CUDA) end if @isdefined(AMDGPU) && AMDGPU.functional() - push!(test_backends, :AMDGPU) + push!(test_backends, :AMDGPU) end for parall in test_backends diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index 76f17a1..e622a59 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -39,7 +39,7 @@ function setup_constant_vel_1D_CPML(nt, dt, nx, dx, c0, f0, halo, rcoef) posrecs = zeros(1, 1) posrecs[1, :] = [lx / 3] srcs = ScalarSources(possrcs, srctf, f0) - recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) + recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=1.0 * I(nt)) shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, vel end @@ -62,7 +62,7 @@ function setup_constant_vel_rho_1D_CPML(nt, dt, nx, dx, c0, ρ0, t0, f0, halo, r posrecs = zeros(1, 1) posrecs[1, :] = [lx / 3] srcs = ScalarSources(possrcs, srctf, f0) - recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) + recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=1.0 * I(nt)) shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, matprop, refsrctf end @@ -86,7 +86,7 @@ function setup_constant_vel_2D_CPML(nt, dt, nx, ny, dx, dy, c0, f0, halo, rcoef) posrecs = zeros(1, 2) posrecs[1, :] = [lx / 3, ly / 2] srcs = ScalarSources(possrcs, srctf, f0) - recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) + recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=1.0 * I(nt)) shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, vel end @@ -109,11 +109,39 @@ function setup_constant_vel_rho_2D_CPML(nt, dt, nx, ny, dx, dy, c0, ρ0, t0, f0, posrecs = zeros(1, 2) posrecs[1, :] = [lx / 3, ly / 2] srcs = ScalarSources(possrcs, srctf, f0) - recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) + recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=1.0 * I(nt)) shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, matprop end +function setup_constant_elastic_2D_CPML(nt, dt, nx, ny, dx, dy, ρ0, λ0, μ0, halo, rcoef, f0) + # constant velocity setup + lx = (nx - 1) * dx + ly = (ny - 1) * dy + matprop = ElasticIsoMaterialProperties(; ρ=ρ0 .* ones(nx, ny), λ=λ0 .* ones(nx, ny), μ=μ0 .* ones(nx, ny)) + # input parameters + params = InputParametersElastic(nt, dt, (nx, ny), (dx, dy), + CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) + # sources + t0 = 2 / f0 + times = collect(range(0.0; step=dt, length=nt)) + possrcs = zeros(1, 2) + possrcs[1, :] = [lx / 2, ly / 2] + srctf = zeros(nt, 1) + srctf[:, 1] .= rickerstf.(times, t0, f0) + # receivers + posrecs = zeros(1, 2) + posrecs[1, :] = [lx / 3, ly / 2] + + srcs = MomentTensorSources(possrcs, srctf, [MomentTensor2D(; Mxx=5e10, Mzz=5e10, Mxz=0.98e10)], f0) + observed = zeros(nt, 2, 1) + observed[:,1,1] .= srctf[:,1] + observed[:,2,1] .= srctf[:,1] + recs = VectorReceivers(posrecs, nt, 2; observed=observed, invcov=1.0 * I(nt)) + shots = [MomentTensorShot(; srcs=srcs, recs=recs)] + return params, shots, matprop +end + function setup_constant_vel_3D_CPML(nt, dt, nx, ny, nz, dx, dy, dz, c0, f0, halo, rcoef) # constant velocity setup lx = (nx - 1) * dx @@ -134,7 +162,7 @@ function setup_constant_vel_3D_CPML(nt, dt, nx, ny, nz, dx, dy, dz, c0, f0, halo posrecs = zeros(1, 3) posrecs[1, :] = [lx / 3, ly / 2, lz / 2] srcs = ScalarSources(possrcs, srctf, f0) - recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(nt))) + recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=1.0 * I(nt)) shots = [ScalarShot(; srcs=srcs, recs=recs)] return params, shots, vel end @@ -248,15 +276,15 @@ function setup_constant_vel_1D_CPML_Float32(nt, dt, nx, dx, c0, f0, halo, rcoef) params = InputParametersAcoustic(nt, dt, (nx,), (dx,), CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false)) # sources - t0 = 2f0 / f0 + t0 = 2.0f0 / f0 times = convert.(Float32, collect(range(0.0; step=dt, length=nt))) possrcs = zeros(Float32, 1, 1) srctf = zeros(Float32, nt, 1) srctf[:, 1] .= rickerstf.(times, t0, f0) - possrcs[1, :] = [lx / 2f0] + possrcs[1, :] = [lx / 2.0f0] # receivers posrecs = zeros(Float32, 1, 1) - posrecs[1, :] = [lx / 3f0] + posrecs[1, :] = [lx / 3.0f0] srcs = ScalarSources(possrcs, srctf, f0) recs = ScalarReceivers(posrecs, nt; observed=copy(srctf), invcov=Diagonal(ones(Float32, nt))) shots = [ScalarShot(; srcs=srcs, recs=recs)] From 91974de31491d9771a74e0e82a8f6055d50a3317 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 2 Oct 2024 14:31:55 +0200 Subject: [PATCH 077/111] Elastic gradients WIP 2 --- Project.toml | 1 + docs/make.jl | 4 +- .../constant_density/gradient_check_fd.jl | 8 +- .../variable_density/gradient_check_fd.jl | 8 +- .../variable_density/plot_gradient.jl | 6 +- .../elastic/gradient_check_fd.jl | 318 ++++++++++++++++++ examples/simple_example_acoustic.jl | 16 +- examples/simple_example_wavesim.jl | 2 +- ext/SeismicWaves_AMDGPUBackendExt.jl | 18 +- ext/SeismicWaves_CUDABackendExt.jl | 18 +- src/SeismicWaves.jl | 5 +- .../acoustic/acou_material_properties.jl | 6 +- src/models/acoustic/acou_models.jl | 6 + .../backends/shared/elastic2D_iso_xPU.jl | 161 +++++++-- src/models/elastic/ela_forward.jl | 140 +++++--- src/models/elastic/ela_gradient.jl | 203 ++++++++++- src/models/elastic/ela_material_properties.jl | 6 +- src/models/elastic/ela_models.jl | 107 +++++- src/shots/shot.jl | 15 + src/shots/sources.jl | 16 +- src/utils/abstract_types.jl | 2 +- src/utils/checks.jl | 6 + src/utils/interpolations.jl | 63 ++-- src/utils/utils.jl | 3 +- .../test_gradient_elastic_constant_density.jl | 1 - test/test_interpolations.jl | 210 ++++++++++++ 26 files changed, 1173 insertions(+), 176 deletions(-) rename examples/gradient_check_fd/{ => acoustic}/constant_density/gradient_check_fd.jl (98%) rename examples/gradient_check_fd/{ => acoustic}/variable_density/gradient_check_fd.jl (98%) rename examples/gradient_check_fd/{ => acoustic}/variable_density/plot_gradient.jl (98%) create mode 100644 examples/gradient_check_fd/elastic/gradient_check_fd.jl create mode 100644 test/test_interpolations.jl diff --git a/Project.toml b/Project.toml index 546f53c..39fd916 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.7.0" [deps] DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" ParallelStencil = "94395366-693c-11ea-3b26-d9b7aac5d958" diff --git a/docs/make.jl b/docs/make.jl index b2ba61c..7b3f314 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,14 +1,14 @@ using SeismicWaves -import Literate +using Literate: Literate using Documenter println("Converting examples...") Literate.markdown( joinpath(@__DIR__, "src", "examples.jl"), joinpath(@__DIR__, "src"); - credit = false + credit=false ) println("Building documentation...") diff --git a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl b/examples/gradient_check_fd/acoustic/constant_density/gradient_check_fd.jl similarity index 98% rename from examples/gradient_check_fd/constant_density/gradient_check_fd.jl rename to examples/gradient_check_fd/acoustic/constant_density/gradient_check_fd.jl index edacabc..e0829e3 100644 --- a/examples/gradient_check_fd/constant_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/acoustic/constant_density/gradient_check_fd.jl @@ -14,9 +14,9 @@ warn_logger = ConsoleLogger(stderr, Logging.Warn) error_logger = ConsoleLogger(stderr, Logging.Error) debug_logger = ConsoleLogger(stderr, Logging.Debug) -include("../../models.jl") -include("../../geometries.jl") -include("../../plotting_utils.jl") +include("../../../models.jl") +include("../../../geometries.jl") +include("../../../plotting_utils.jl") function setup(nt, c0, c0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) ##======================================== @@ -81,7 +81,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss; compute copy(shots[i].recs.positions), nt; observed=copy(shots[i].recs.seismograms), - invcov=Diagonal(ones(nt)) + invcov=1.0 * I(nt) ) # add pair as shot push!(shots_obs, ScalarShot(; srcs=shots[i].srcs, recs=recs)) # srcs => recs) diff --git a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl b/examples/gradient_check_fd/acoustic/variable_density/gradient_check_fd.jl similarity index 98% rename from examples/gradient_check_fd/variable_density/gradient_check_fd.jl rename to examples/gradient_check_fd/acoustic/variable_density/gradient_check_fd.jl index 80e5fc6..e190ed3 100644 --- a/examples/gradient_check_fd/variable_density/gradient_check_fd.jl +++ b/examples/gradient_check_fd/acoustic/variable_density/gradient_check_fd.jl @@ -14,9 +14,9 @@ warn_logger = ConsoleLogger(stderr, Logging.Warn) error_logger = ConsoleLogger(stderr, Logging.Error) debug_logger = ConsoleLogger(stderr, Logging.Debug) -include("../../models.jl") -include("../../geometries.jl") -include("../../plotting_utils.jl") +include("../../../models.jl") +include("../../../geometries.jl") +include("../../../plotting_utils.jl") function setup(nt, c0, c0max, rho0, rho0max, r, dx, dy, dt, halo, rcoef, nx, ny, parall) ##======================================== @@ -96,7 +96,7 @@ function gradient_fd_check(wavesim, shots, matprop_const, matprop_gauss) copy(shots[i].recs.positions), nt; observed=copy(shots[i].recs.seismograms), - invcov=Diagonal(ones(nt)) + invcov=1.0 * I(nt) ) # add pair as shot push!(shots_obs, ScalarShot(; srcs=shots[i].srcs, recs=recs)) # srcs => recs) diff --git a/examples/gradient_check_fd/variable_density/plot_gradient.jl b/examples/gradient_check_fd/acoustic/variable_density/plot_gradient.jl similarity index 98% rename from examples/gradient_check_fd/variable_density/plot_gradient.jl rename to examples/gradient_check_fd/acoustic/variable_density/plot_gradient.jl index 815ef06..a87fa64 100644 --- a/examples/gradient_check_fd/variable_density/plot_gradient.jl +++ b/examples/gradient_check_fd/acoustic/variable_density/plot_gradient.jl @@ -1,8 +1,8 @@ using Serialization -include("../../models.jl") -include("../../geometries.jl") -include("../../plotting_utils.jl") +include("../../../models.jl") +include("../../../geometries.jl") +include("../../../plotting_utils.jl") # Numerical parameters nt = 1000 diff --git a/examples/gradient_check_fd/elastic/gradient_check_fd.jl b/examples/gradient_check_fd/elastic/gradient_check_fd.jl new file mode 100644 index 0000000..cb967b5 --- /dev/null +++ b/examples/gradient_check_fd/elastic/gradient_check_fd.jl @@ -0,0 +1,318 @@ +using Revise +using SeismicWaves +using LinearAlgebra +using GLMakie +using Logging +using Serialization +using Printf + +function gaussian_vel_2D(nx, ny, c0, c0max, r, origin=[(nx + 1) / 2, (ny + 1) / 2]) + sigma = r / 3 + amp = c0max - c0 + f(x, y) = amp * exp(-(0.5 * ((x - origin[1])^2 + (y - origin[2])^2) / sigma^2)) + return c0 .+ [f(x, y) for x in 1:nx, y in 1:ny] +end + +function create_constant_velocity_model(nx, nz, ρ0, vp0, vs0=vp0 / sqrt(3)) + vp = vp0 .* ones(nx, nz) + vs = vs0 .* ones(nx, nz) + ρ = ρ0 .* ones(nx, nz) + μ = vs .^ 2 .* ρ + λ = (vp .^ 2 .* ρ) .- (2 .* μ) + matprop = ElasticIsoMaterialProperties(; λ=λ, μ=μ, ρ=ρ) + return matprop +end + +function create_gaussian_velocity_model(nx, nz, ρ0, vp0, vs0=vp0 / sqrt(3)) + vp = gaussian_vel_2D(nx, nz, vp0, vp0 * 1.2, nz/5) + vs = vs0 .* ones(nx, nz) + ρ = ρ0 .* ones(nx, nz) + μ = vs .^ 2 .* ρ + λ = (vp .^ 2 .* ρ) .- (2 .* μ) + matprop = ElasticIsoMaterialProperties(; λ=λ, μ=μ, ρ=ρ) + return matprop +end + +# Function to define shots +function define_shots(nx, nz, nt, dt, dh) + nsrc = 1 + possrcs = zeros(nsrc, 2) + for s in 1:nsrc + possrcs[s, :] .= [(s / (nsrc+1) * nx) * dh, (nz / 6) * dh] + end + f0 = 150.0 + t0 = 1.20 / f0 + # srcstf = zeros(nt, nsrc) + # Mxx = fill(5e10, nsrc) + # Mzz = fill(0.0, nsrc) + # Mxz = fill(0.0, nsrc) + # srcstf[:, 1] .= rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) + srcstf = zeros(nt, 2, nsrc) + for s in 1:nsrc + srcstf[:, 1, s] .= 0.0 .* rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) + srcstf[:, 2, s] .= 1e10 .* rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) + end + srcs = ExternalForceSources(possrcs, srcstf, f0) + # srcs = MomentTensorSources(possrcs, srcstf, [MomentTensor2D(; Mxx=Mxx[s], Mzz=Mzz[s], Mxz=Mxz[s]) for s in 1:nsrc], f0) + nrecs = 1 + posrecs = zeros(nrecs, 2) + for r in 1:nrecs + posrecs[r, :] .= [(r / (nrecs+1) * nx) * dh, (5nz / 6) * dh] + end + + recs = VectorReceivers(posrecs, nt) + shots = [ExternalForceShot(; srcs=srcs, recs=recs)] + # shots = [MomentTensorShot(; srcs=srcs, recs=recs)] + return shots +end + +# Function to compute the forward simulation +function compute_forward_simulation(params, matprop, shots) + model = build_wavesim(params, matprop; parall=:threads, gradient=true, check_freq=nothing, snapevery=5) + snaps = swforward!(model, matprop, shots) + return model, snaps +end + +# Function to compute the gradient +function compute_gradient(model, matprop_grad, shots_grad) + grad, misfit = swgradient!(model, matprop_grad, shots_grad; compute_misfit=true) + return grad, misfit +end + +# Function to compute the FD gradient +function compute_fd_gradient!(grad_FD, param_name, Δparam, model, matprop_grad, shots_grad, misfit, halo, nx, nz) + for i in halo:nx-halo + for j in halo:nz-halo + new_param = copy(getfield(matprop_grad, param_name)) + new_param[i, j] += Δparam + matpropnew = ElasticIsoMaterialProperties(; ρ=matprop_grad.ρ, μ=matprop_grad.μ, λ=matprop_grad.λ) + setfield!(matpropnew, param_name, new_param) + misfit_right = swmisfit!(model, matpropnew, shots_grad; logger=ConsoleLogger(stderr, Logging.Warn)) + grad_FD[i, j] = (misfit_right - misfit) / Δparam + @printf("Parameter: %s, Indices: (%d, %d), Gradient: %.6e\n", param_name, i, j, grad_FD[i, j]) + end + end +end + +# Main function to orchestrate the workflow +function main() + # Time and grid parameters + nt = 1000 + dt = 0.00008 + halo = 20 + nx = 200 + halo*2 + nz = 200 + halo*2 + dh = 0.5 + rcoef = 0.0001 + + # Create velocity model + matprop_const = create_constant_velocity_model(nx, nz, 2100.0, 3100.0, 0.0) + matprop_gauss = create_gaussian_velocity_model(nx, nz, 2100.0, 3100.0, 0.0) + + # Define shots + shots = define_shots(nx, nz, nt, dt, dh) + + # Input parameters for elastic simulation + boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false) + params = InputParametersElastic(nt, dt, (nx, nz), (dh, dh), boundcond) + + # Compute forward simulation + model, snapshots = compute_forward_simulation(params, matprop_gauss, shots) + + # Compute the gradient + shots_grad = Vector{ExternalForceShot{Float64, 2}}() + # shots_grad = Vector{MomentTensorShot{Float64, 2, MomentTensor2D{Float64}}}() + for i in eachindex(shots) + recs_grad = VectorReceivers(shots[i].recs.positions, nt; observed=copy(shots[i].recs.seismograms), invcov=1.0 * I(nt)) + push!(shots_grad, ExternalForceShot(; srcs=shots[i].srcs, recs=recs_grad)) + # push!(shots_grad, MomentTensorShot(; srcs=shots[i].srcs, recs=recs_grad)) + end + + grad, misfit = compute_gradient(model, matprop_const, shots_grad) + serialize("grads_adj.jls", grad) + + # # Compute FD gradients + # Δρ = minimum(ρ) * 1e-4 + # grad_ρ_FD = zeros(nx, nz) + # compute_fd_gradient!(grad_ρ_FD, :ρ, Δρ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) + # serialize("grad_ρ_FD.jls", grad_ρ_FD) + + # Δλ = minimum(λ) * 1e-4 + # grad_λ_FD = zeros(nx, nz) + # compute_fd_gradient!(grad_λ_FD, :λ, Δλ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) + # serialize("grad_λ_FD.jls", grad_λ_FD) + + # Δμ = minimum(λ) * 1e-4 + # grad_μ_FD = zeros(nx, nz) + # compute_fd_gradient!(grad_μ_FD, :μ, Δμ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) + # serialize("grad_μ_FD.jls", grad_μ_FD) + + return params, matprop_gauss, shots, snapshots +end + +# Function to load and plot gradients +function load_and_plot_gradients(params, shots) + grads = deserialize("grads_adj.jls") + grad_ρ_FD = deserialize("grad_ρ_FD.jls") + grad_λ_FD = deserialize("grad_λ_FD.jls") + grad_μ_FD = deserialize("grad_μ_FD.jls") + + # Plot gradients + plotgrad(params, grads, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) +end + +function plotgrad(par, grad, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) + xgrd = [par.gridspacing[1] * (i - 1) for i in 1:par.gridsize[1]] + ygrd = [par.gridspacing[2] * (i - 1) for i in 1:par.gridsize[2]] + + fig = Figure(; size=(1000, 1000)) + + axes = [ + (Axis(fig[1, 1]; aspect=DataAspect(), title="grad ρ", xlabel="x [m]", ylabel="z [m]"), grad["rho"], "∂χ/∂ρ", [1,2]), + # (Axis(fig[1, 3]; aspect=DataAspect(), title="grad ρ (FD)", xlabel="x [m]", ylabel="z [m]"), grad_ρ_FD, "∂χ/∂ρ", [1,4]), + (Axis(fig[2, 1]; aspect=DataAspect(), title="grad λ", xlabel="x [m]", ylabel="z [m]"), grad["lambda"], "∂χ/∂λ", [2,2]), + # (Axis(fig[2, 3]; aspect=DataAspect(), title="grad λ (FD)", xlabel="x [m]", ylabel="z [m]"), grad_λ_FD, "∂χ/∂λ", [2,4]), + (Axis(fig[3, 1]; aspect=DataAspect(), title="grad μ", xlabel="x [m]", ylabel="z [m]"), grad["mu"], "∂χ/∂μ", [3,2]), + # (Axis(fig[3, 3]; aspect=DataAspect(), title="grad μ (FD)", xlabel="x [m]", ylabel="z [m]"), grad_μ_FD, "∂χ/∂μ", [3,4]) + ] + + radius = 5 + + for (ax, grad_data, label, cbarpos) in axes + grad2 = copy(grad_data) + for s in 1:size(shots[1].srcs.positions, 1) + srcx, srcy = ceil.(Int, shots[1].srcs.positions[s, :] ./ par.gridspacing) + grad2[srcx-radius:srcx+radius, srcy-radius:srcy+radius] .= 0 + end + for r in 1:size(shots[1].recs.positions, 1) + recx, recy = ceil.(Int, shots[1].recs.positions[r, :] ./ par.gridspacing) + grad2[recx-radius:recx+radius, recy-radius:recy+radius] .= 0 + end + maxabsgrad = maximum(abs.(grad2)) + hm = heatmap!(ax, xgrd, ygrd, grad_data; colormap=:vik, colorrange=(-maxabsgrad, maxabsgrad)) + Colorbar(fig[cbarpos[1], cbarpos[2]], hm; label=label) + ax.yreversed = true + end + + save("grads.png", fig) + return fig +end + +function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) + xgrd = [par.gridspacing[1] * (i - 1) for i in 1:par.gridsize[1]] + ygrd = [par.gridspacing[2] * (i - 1) for i in 1:par.gridsize[2]] + xrec = shots[1].recs.positions[:, 1] + yrec = shots[1].recs.positions[:, 2] + xsrc = shots[1].srcs.positions[:, 1] + ysrc = shots[1].srcs.positions[:, 2] + + vxsnap = [snapsh[1][kk]["v"].value[1] for kk in sort(keys(snapsh[1]))] + vzsnap = [snapsh[1][kk]["v"].value[2] for kk in sort(keys(snapsh[1]))] + + curvx = Observable(vxsnap[1]) + curvz = Observable(vzsnap[1]) + + vp = sqrt.((matprop.λ + 2 .* matprop.μ) ./ matprop.ρ) + + dx = par.gridspacing[1] + dz = par.gridspacing[2] + nx = par.gridsize[1] + nz = par.gridsize[2] + halo = par.boundcond.halo + rcoef = par.boundcond.rcoef + freetop = par.boundcond.freeboundtop + + if freetop + rectpml = [dx * (halo - 1), 0.0, + dx * (nx - 2 * halo - 1), dz * (nz - halo - 1)] + else + rectpml = [dx * (halo - 1), dz * (halo - 1), + dx * (nx - 2 * halo - 1), dz * (nz - 2 * halo - 1)] + end + + ##===================================== + fig = Figure(; size=(800, 1500÷2 * 3)) + + nframes = length(vxsnap) + + cmapwavefield = :vik #:cyclic_grey_15_85_c0_n256_s25 #:balance + + ax1 = Axis(fig[1, 1]; aspect=DataAspect(), + xlabel="x [m]", ylabel="z [m]", title="Vx, clip at $scalamp of max amplitude, iteration 0 of $(snapevery*nframes)") + #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) + extx = extrema.([vxsnap[i] for i in eachindex(vxsnap)]) + extx = map(p -> max(abs(p[1]), abs(p[2])), extx) + vmax = max(extx...) + vminmax = scalamp .* (-vmax, vmax) + hm = heatmap!(ax1, xgrd, ygrd, curvx; colormap=cmapwavefield, + colorrange=vminmax) #,alpha=0.7) + Colorbar(fig[1, 2], hm; label="x partic. vel.") + + lines!(ax1, Rect(rectpml...); color=:green) + scatter!(ax1, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + scatter!(ax1, xsrc, ysrc; label="Sources", markersize=15) + # axislegend(ax1) + ax1.yreversed = true + + ax2 = Axis(fig[2, 1]; aspect=DataAspect(), + xlabel="x [m]", ylabel="z [m]", title="Vz, clip at $scalamp of max amplitude, iteration 0 of $(snapevery*nframes)") + #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) + extx = extrema.([vzsnap[i] for i in eachindex(vzsnap)]) + extx = map(p -> max(abs(p[1]), abs(p[2])), extx) + vmax = max(extx...) + vminmax = scalamp .* (-vmax, vmax) + hm = heatmap!(ax2, xgrd, ygrd, curvz; colormap=cmapwavefield, + colorrange=vminmax) #,alpha=0.7) + Colorbar(fig[2, 2], hm; label="z partic. vel.") + + lines!(ax2, Rect(rectpml...); color=:green) + scatter!(ax2, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + scatter!(ax2, xsrc, ysrc; label="Sources", markersize=15) + # axislegend(ax2) + ax2.yreversed = true + + ax3 = Axis(fig[3, 1]; aspect=DataAspect(), + xlabel="x [m]", ylabel="z [m]") + hm = heatmap!(ax3, xgrd, ygrd, vp; colormap=:Reds) #,alpha=0.7) + Colorbar(fig[3, 2], hm; label="Vp") + + scatter!(ax3, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) + scatter!(ax3, xsrc, ysrc; label="Sources", markersize=15) + axislegend(ax3) + ax3.yreversed = true + + ## + save("first_frame.png", fig) + ##===================================== + + function updatefunction(curax1, curax2, vxsnap, vzsnap, it) + cvx = vxsnap[it] + cvz = vzsnap[it] + curax1.title = "Vx, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" + curax2.title = "Vz, clip at $scalamp of max amplitude, iteration $(snapevery*it) of $(snapevery*nframes)" + return cvx, cvz + end + + fps = 30 + + # live plot + # for j in 1:1 + # for it=1:nframes + # curvx[],curvz[] = updatefunction(ax1,ax2,vxsnap,vzsnap,it) + # sleep(1/fps) + # end + # end + + ## + record(fig, "snapshots_halo_$(halo)_rcoef_$(rcoef).mp4", 1:nframes; framerate=fps) do it + curvx[], curvz[] = updatefunction(ax1, ax2, vxsnap, vzsnap, it) + # yield() -> not required with record + end +end + +# Run the main function +params, matprop_gauss, shots, snapshots = main() +# Plot animation +snapanimate(params, matprop_gauss, shots, snapshots) +# Load and plot gradients +load_and_plot_gradients(params, shots) diff --git a/examples/simple_example_acoustic.jl b/examples/simple_example_acoustic.jl index f713425..0d9bc80 100644 --- a/examples/simple_example_acoustic.jl +++ b/examples/simple_example_acoustic.jl @@ -100,6 +100,20 @@ function exacouprob(parall=:serial) logger=logger) #snapevery=snapevery) + seis = copy(shots[1].recs.seismograms) + + @time snapshots = swforward!(params, + matprop, + shots; + parall=parall, + infoevery=infoevery, + logger=logger) + #snapevery=snapevery) + + seis2 = copy(shots[1].recs.seismograms) + + @assert all(seis .== seis2) + ##=============================================== ## compute the gradient shots_grad = Vector{ScalarShot{Float64}}() @@ -107,7 +121,7 @@ function exacouprob(parall=:serial) seis = shots[i].recs.seismograms nt = size(seis, 1) recs_grad = ScalarReceivers(shots[i].recs.positions, nt; observed=seis, - invcov=Diagonal(ones(nt))) + invcov=1.0 * I(nt)) push!(shots_grad, ScalarShot(; srcs=shots[i].srcs, recs=recs_grad)) end diff --git a/examples/simple_example_wavesim.jl b/examples/simple_example_wavesim.jl index b1da963..995fd1e 100644 --- a/examples/simple_example_wavesim.jl +++ b/examples/simple_example_wavesim.jl @@ -131,7 +131,7 @@ function exacouprob_wavsim(parall=:serial) seis = shots[i].recs.seismograms nt = size(seis, 1) recs_grad = ScalarReceivers(shots[i].recs.positions, nt; observed=seis, - invcov=Diagonal(ones(nt))) + invcov=1.0 * I(nt)) push!(shots_grad, ScalarShot(; srcs=shots[i].srcs, recs=recs_grad)) end diff --git a/ext/SeismicWaves_AMDGPUBackendExt.jl b/ext/SeismicWaves_AMDGPUBackendExt.jl index 99f9adc..83f3cf7 100644 --- a/ext/SeismicWaves_AMDGPUBackendExt.jl +++ b/ext/SeismicWaves_AMDGPUBackendExt.jl @@ -12,11 +12,17 @@ include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl") include("../src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl") # Overload backend selection -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = Acoustic1D_CD_CPML_AMDGPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Acoustic2D_CD_CPML_AMDGPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:AMDGPU}}) = Acoustic3D_CD_CPML_AMDGPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = Acoustic1D_VD_CPML_AMDGPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Acoustic2D_VD_CPML_AMDGPU -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = Elastic2D_Iso_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = + Acoustic1D_CD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = + Acoustic2D_CD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:AMDGPU}}) = + Acoustic3D_CD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:AMDGPU}}) = + Acoustic1D_VD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = + Acoustic2D_VD_CPML_AMDGPU +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:AMDGPU}}) = + Elastic2D_Iso_CPML_AMDGPU end \ No newline at end of file diff --git a/ext/SeismicWaves_CUDABackendExt.jl b/ext/SeismicWaves_CUDABackendExt.jl index a03d3e7..1abe407 100644 --- a/ext/SeismicWaves_CUDABackendExt.jl +++ b/ext/SeismicWaves_CUDABackendExt.jl @@ -12,10 +12,16 @@ include("../src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl") include("../src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl") # Overload backend selection -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = Acoustic1D_CD_CPML_CUDA -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Acoustic2D_CD_CPML_CUDA -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:CUDA}}) = Acoustic3D_CD_CPML_CUDA -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = Acoustic1D_VD_CPML_CUDA -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Acoustic2D_VD_CPML_CUDA -SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = Elastic2D_Iso_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = + Acoustic1D_CD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = + Acoustic2D_CD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticCDCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 3}}, ::Type{Val{:CUDA}}) = + Acoustic3D_CD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 1}}, ::Type{Val{:CUDA}}) = + Acoustic1D_VD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:AcousticVDStaggeredCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = + Acoustic2D_VD_CPML_CUDA +SeismicWaves.select_backend(::CPMLBoundaryCondition, ::LocalGrid, ::Type{<:ElasticIsoCPMLWaveSimulation{<:Union{Float16, Float32, Float64}, 2}}, ::Type{Val{:CUDA}}) = + Elastic2D_Iso_CPML_CUDA end \ No newline at end of file diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index dffd047..ba7c3d3 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -6,6 +6,7 @@ using Printf using ParallelStencil using Logging using DocStringExtensions +using Interpolations # main struct for wave simulation export WaveSimulation @@ -19,8 +20,8 @@ export MaterialProperties export VpAcousticCDMaterialProperties, VpRhoAcousticVDMaterialProperties export ElasticIsoMaterialProperties # export sources, receivers and shots -export Shot, ScalarShot, MomentTensorShot -export Sources, ScalarSources, MomentTensorSources +export Shot, ScalarShot, MomentTensorShot, ExternalForceShot +export Sources, ScalarSources, MomentTensorSources, ExternalForceSources export MomentTensor2D, MomentTensor3D export Receivers, ScalarReceivers, VectorReceivers # forward, misfit and gradient functions diff --git a/src/models/acoustic/acou_material_properties.jl b/src/models/acoustic/acou_material_properties.jl index 542c6bc..d8edd7a 100644 --- a/src/models/acoustic/acou_material_properties.jl +++ b/src/models/acoustic/acou_material_properties.jl @@ -25,13 +25,13 @@ mutable struct VpRhoAcousticVDMaterialProperties{T, N} <: MaterialProperties{T, "Density" rho::Array{T, N} "Interpolation method" - interp_method::InterpolationMethod + interp_method::AbstractInterpolationMethod @doc """ VpRhoAcousticVDMaterialProperties( vp::Array{T, N}, rho::Array{T, N}; - interp_method::InterpolationMethod=ArithmeticAverageInterpolation(2) + interp_method::InterpolationMethod=ArithmeticAverageInterpolation() ) where {T, N} Constructor for material properties for acoustic variable-density simulation. @@ -39,7 +39,7 @@ mutable struct VpRhoAcousticVDMaterialProperties{T, N} <: MaterialProperties{T, function VpRhoAcousticVDMaterialProperties( vp::Array{T, N}, rho::Array{T, N}; - interp_method::InterpolationMethod=ArithmeticAverageInterpolation(2) + interp_method::AbstractInterpolationMethod=ArithmeticAverageInterpolation() ) where {T, N} return new{T, N}(vp, rho, interp_method) end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index db5c361..8c93720 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -199,6 +199,9 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end + # Deep copy material properties + matprop = deepcopy(matprop) + new{T, N, A, V}( params, cpmlparams, @@ -468,6 +471,9 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end + # Deep copy material properties + matprop = deepcopy(matprop) + return new{T, N, A, V}( params, cpmlparams, diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index cd70da0..a9d7b51 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -259,36 +259,55 @@ end return nothing end -@parallel_indices (p) function inject_momten_sources2D!(σxx, σzz, σxz, Mxx, Mzz, Mxz, srctf_bk, dt, srccoeij_bk, srccoeval_bk, it) +@parallel_indices (p) function inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx, Mzz, srctf_bk, srccoeij_bk, srccoeval_bk, it) s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] - σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it] - σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it] - σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it] + σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it, s] + σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it, s] return nothing end -@parallel_indices (p) function inject_vel_sources2D!(vx, vz, f, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, dt, it) +@parallel_indices (p) function inject_momten_sources2D_σxz!(σxz, Mxz, srctf_bk, srccoeij_bk, srccoeval_bk, it) s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] - vx[isrc, jsrc] += srccoeval_bk[p] * f[it, 1, s] * dt / ρ[isrc, jsrc] - vz[isrc, jsrc] += srccoeval_bk[p] * f[it, 2, s] * dt / ρ_ihalf_jhalf[isrc, jsrc] + σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it, s] + + return nothing +end + +@parallel_indices (p) function inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_bk, srccoeval_bk, ρ, it) + s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] + vx[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 1, s] / ρ[isrc, jsrc] return nothing end -@parallel_indices (p) function record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) - r, irec, jrec = reccoeij_bk[p, 1], reccoeij_bk[p, 2], reccoeij_bk[p, 3] - traces_bk[it, 1, r] += reccoeval_bk[p] * vx[irec, jrec] - traces_bk[it, 2, r] += reccoeval_bk[p] * vz[irec, jrec] +@parallel_indices (p) function inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_bk, srccoeval_bk, ρ_ihalf_jhalf, it) + s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] + vz[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 2, s] / ρ_ihalf_jhalf[isrc, jsrc] + return nothing +end + +@parallel_indices (p) function record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it) + r, irec, jrec = reccoeij_vx[p, 1], reccoeij_vx[p, 2], reccoeij_vx[p, 3] + traces_bk[it, 1, r] += reccoeval_vx[p] * vx[irec, jrec] + return nothing +end +@parallel_indices (p) function record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it) + r, irec, jrec = reccoeij_vz[p, 1], reccoeij_vz[p, 2], reccoeij_vz[p, 3] + traces_bk[it, 2, r] += reccoeval_vz[p] * vz[irec, jrec] return nothing end function forward_onestep_CPML!( model, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, + srccoeij_xx, + srccoeval_xx, + srccoeij_xz, + srccoeval_xz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, srctf_bk, traces_bk, it::Int, @@ -342,6 +361,14 @@ function forward_onestep_CPML!( @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + # record receivers + if save_trace + nrecpts_vx = size(reccoeij_vx, 1) + nrecpts_vz = size(reccoeij_vz, 1) + @parallel (1:nrecpts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it) + @parallel (1:nrecpts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it) + end + # update stresses σxx and σzz @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ_ihalf, μ_ihalf, @@ -353,22 +380,107 @@ function forward_onestep_CPML!( ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) # inject sources (moment tensor type of internal force) - nsrcpts = size(srccoeij_bk, 1) - @parallel (1:nsrcpts) inject_momten_sources2D!(σxx, σzz, σxz, Mxx_bk, Mzz_bk, Mxz_bk, srctf_bk, dt, srccoeij_bk, srccoeval_bk, it) + nsrcpts_xx = size(srccoeij_xx, 1) + nsrcpts_xz = size(srccoeij_xz, 1) + @parallel (1:nsrcpts_xx) inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx_bk, Mzz_bk, srctf_bk, srccoeij_xx, srccoeval_xx, it) + @parallel (1:nsrcpts_xz) inject_momten_sources2D_σxz!(σxz, Mxz_bk, srctf_bk, srccoeij_xz, srccoeval_xz, it) + + return +end + +function forward_onestep_CPML!( + model, + srccoeij_vx, + srccoeval_vx, + srccoeij_vz, + srccoeval_vz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, + srctf_bk, + traces_bk, + it::Int; + save_trace::Bool=true +) + # Extract info from grid + freetop = model.cpmlparams.freeboundtop + cpmlcoeffs = model.cpmlcoeffs + dx = model.grid.spacing[1] + dz = model.grid.spacing[2] + dt = model.dt + nx, nz = model.grid.size[1:2] + halo = model.cpmlparams.halo + grid = model.grid + + vx, vz = grid.fields["v"].value + σxx, σzz, σxz = grid.fields["σ"].value + + ψ_∂σxx∂x, ψ_∂σxz∂x = grid.fields["ψ_∂σ∂x"].value + ψ_∂σzz∂z, ψ_∂σxz∂z = grid.fields["ψ_∂σ∂z"].value + ψ_∂vx∂x, ψ_∂vz∂x = grid.fields["ψ_∂v∂x"].value + ψ_∂vx∂z, ψ_∂vz∂z = grid.fields["ψ_∂v∂z"].value + + a_x = cpmlcoeffs[1].a + a_x_half = cpmlcoeffs[1].a_h + b_x = cpmlcoeffs[1].b + b_x_half = cpmlcoeffs[1].b_h + + a_z = cpmlcoeffs[2].a + a_z_half = cpmlcoeffs[2].a_h + b_z = cpmlcoeffs[2].b + b_z_half = cpmlcoeffs[2].b_h + + ρ = grid.fields["ρ"].value + ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value + λ_ihalf = grid.fields["λ_ihalf"].value + μ_ihalf = grid.fields["μ_ihalf"].value + μ_jhalf = grid.fields["μ_jhalf"].value + + # Precomputing divisions + factx = 1.0 / (24.0 * dx) + factz = 1.0 / (24.0 * dz) + + # update velocity vx + @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, + b_x, b_z, a_x, a_z, freetop) + # update velocity vz + @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, + ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + + # inject sources (residuals as velocities) + nsrcpts_vx = size(srccoeij_vx, 1) + nsrcpts_vz = size(srccoeij_vz, 1) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_vx, srccoeval_vx, ρ, it) + @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_vz, srccoeval_vz, ρ_ihalf_jhalf, it) # record receivers if save_trace - nrecpts = size(reccoeij_bk, 1) - @parallel (1:nrecpts) record_receivers2D!(vx, vz, traces_bk, reccoeij_bk, reccoeval_bk, it) + nrecpts_vx = size(reccoeij_vx, 1) + nrecpts_vz = size(reccoeij_vz, 1) + @parallel (1:nrecpts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it) + @parallel (1:nrecpts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it) end + # update stresses σxx and σzz + @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ_ihalf, μ_ihalf, + ψ_∂vx∂x, ψ_∂vz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + # update stress σxz + @parallel (3:nx-1, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, + μ_jhalf, b_x, b_z_half, + ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + return end function adjoint_onestep_CPML!( model, - srccoeij_bk, - srccoeval_bk, + srccoeij_vx, + srccoeval_vx, + srccoeij_vz, + srccoeval_vz, residuals_bk, it ) @@ -428,9 +540,10 @@ function adjoint_onestep_CPML!( ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # inject sources (residuals as velocities) - nsrcpts = size(srccoeij_bk, 1) - @parallel (1:nsrcpts) inject_vel_sources2D!(vx, vz, residuals_bk, srccoeij_bk, srccoeval_bk, ρ, ρ_ihalf_jhalf, dt, it) - + nsrcpts_vx = size(srccoeij_vx, 1) + nsrcpts_vz = size(srccoeij_vz, 1) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, residuals_bk, srccoeij_vx, srccoeval_vx, ρ, it) + @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, residuals_bk, srccoeij_vz, srccoeval_vz, ρ_ihalf_jhalf, it) return end \ No newline at end of file diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index e6295a0..12d5935 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -7,7 +7,9 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound shot::MomentTensorShot{T, 2, MomentTensor2D{T}} ) where {T} # scale source time function - srccoeij, srccoeval, reccoeij, reccoeval, srctf = possrcrec_scaletf(model, shot) + srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, + reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, + scal_srctf = possrcrec_scaletf(model, shot) # moment tensors momtens = shot.srcs.momtens @@ -18,12 +20,16 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound nt = model.nt # Wrap sources and receivers arrays - srccoeij_bk = backend.Data.Array(srccoeij) - srccoeval_bk = backend.Data.Array(srccoeval) - reccoeij_bk = backend.Data.Array(reccoeij) - reccoeval_bk = backend.Data.Array(reccoeval) - - srctf_bk = backend.Data.Array(srctf) + srccoeij_xx = backend.Data.Array(srccoeij_xx) + srccoeval_xx = backend.Data.Array(srccoeval_xx) + srccoeij_xz = backend.Data.Array(srccoeij_xz) + srccoeval_xz = backend.Data.Array(srccoeval_xz) + reccoeij_vx = backend.Data.Array(reccoeij_vx) + reccoeval_vx = backend.Data.Array(reccoeval_vx) + reccoeij_vz = backend.Data.Array(reccoeij_vz) + reccoeval_vz = backend.Data.Array(reccoeval_vz) + + srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) ## ONLY 2D for now!!! @@ -38,10 +44,14 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound # Time loop for it in 1:nt backend.forward_onestep_CPML!(model, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, + srccoeij_xx, + srccoeval_xx, + srccoeij_xz, + srccoeval_xz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, srctf_bk, traces_bk, it, @@ -72,44 +82,76 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound return end -function spreadsrcrecinterp2D( - gridspacing::NTuple{N, T}, - gridsize::NTuple{N, Int}, - positions::Matrix{T}; - nptssinc::Int=4, xstart::T=0.0, zstart::T=0.0 -) where {T, N} - nloc = size(positions, 1) - Ndim = size(positions, 2) - @assert Ndim == 2 - @assert N == Ndim - - Δx = gridspacing[1] - Δz = gridspacing[2] - nx, nz = gridsize[1:2] - - maxnumcoeff = nloc * (2 * nptssinc + 1)^Ndim - coeij_tmp = zeros(Int, maxnumcoeff, Ndim + 1) - coeval_tmp = zeros(T, maxnumcoeff) - l = 0 - for p in 1:nloc - # extract x and z position for source or receiver p - xpos, zpos = positions[p, :] - # compute grid indices and values of sinc coefficients - xidx, zidx, xzcoeff = coeffsinc2D(xstart, zstart, Δx, Δz, xpos, zpos, - nx, nz, [:monopole, :monopole]; npts=nptssinc) - for j in eachindex(zidx) - for i in eachindex(xidx) - l += 1 - # id, i, j indices - coeij_tmp[l, :] .= (p, xidx[i], zidx[j]) - # coefficients value - coeval_tmp[l] = xzcoeff[i, j] - end +@views function swforward_1shot!( + ::CPMLBoundaryCondition, + model::ElasticIsoCPMLWaveSimulation{T, 2}, + shot::ExternalForceShot{T, 2} +) where {T} + # scale source time function + srccoeij_vx, srccoeval_vx, + srccoeij_vz, srccoeval_vz, + reccoeij_vx, reccoeval_vx, + reccoeij_vz, reccoeval_vz, + scal_srctf = possrcrec_scaletf(model, shot) + + # Get computational grid and backend + backend = select_backend(typeof(model), model.parall) + + # Numerics + nt = model.nt + + # Wrap sources and receivers arrays + srccoeij_vx = backend.Data.Array(srccoeij_vx) + srccoeval_vx = backend.Data.Array(srccoeval_vx) + srccoeij_vz = backend.Data.Array(srccoeij_vz) + srccoeval_vz = backend.Data.Array(srccoeval_vz) + reccoeij_vx = backend.Data.Array(reccoeij_vx) + reccoeval_vx = backend.Data.Array(reccoeval_vx) + reccoeij_vz = backend.Data.Array(reccoeij_vz) + reccoeval_vz = backend.Data.Array(reccoeval_vz) + srctf_bk = backend.Data.Array(scal_srctf) + traces_bk = backend.zeros(T, size(shot.recs.seismograms)) + + # Reset wavesim + reset!(model) + + # Time loop + for it in 1:nt + backend.forward_onestep_CPML!( + model, + srccoeij_vx, + srccoeval_vx, + srccoeij_vz, + srccoeval_vz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, + srctf_bk, + traces_bk, + it; + save_trace=true) + + # Print timestep info + if it % model.infoevery == 0 + # Move the cursor to the beginning to overwrite last line + # ter = REPL.Terminals.TTYTerminal("", stdin, stdout, stderr) + # REPL.Terminals.clear_line(ter) + # REPL.Terminals.cmove_line_up(ter) + @info @sprintf( + "Iteration: %d/%d, simulation time: %g s", + it, nt, + model.dt * (it - 1) + ) + end + + # Save snapshot + if snapenabled(model) + savesnapshot!(model.snapshotter, "v" => model.grid.fields["v"], it) end end - # keep only the valid part of the arrays - coeij = coeij_tmp[1:l, :] - coeval = coeval_tmp[1:l] - return coeij, coeval -end + # Save traces + copyto!(shot.recs.seismograms, traces_bk) + return +end \ No newline at end of file diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index efdd57f..a60b06f 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -8,7 +8,9 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = misfit::AbstractMisfit )::Dict{String, Array{T, 2}} where {T} # scale source time function - srccoeij, srccoeval, reccoeij, reccoeval, srctf = possrcrec_scaletf(model, shot) + srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, + reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, + scal_srctf = possrcrec_scaletf(model, shot) # moment tensors momtens = shot.srcs.momtens @@ -20,12 +22,16 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = # Numerics nt = model.nt # Wrap sources and receivers arrays - srccoeij_bk = backend.Data.Array(srccoeij) - srccoeval_bk = backend.Data.Array(srccoeval) - reccoeij_bk = backend.Data.Array(reccoeij) - reccoeval_bk = backend.Data.Array(reccoeval) + srccoeij_xx = backend.Data.Array(srccoeij_xx) + srccoeval_xx = backend.Data.Array(srccoeval_xx) + srccoeij_xz = backend.Data.Array(srccoeij_xz) + srccoeval_xz = backend.Data.Array(srccoeval_xz) + reccoeij_vx = backend.Data.Array(reccoeij_vx) + reccoeval_vx = backend.Data.Array(reccoeval_vx) + reccoeij_vz = backend.Data.Array(reccoeij_vz) + reccoeval_vz = backend.Data.Array(reccoeval_vz) - srctf_bk = backend.Data.Array(srctf) + srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) ## ONLY 2D for now!!! @@ -41,10 +47,14 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = for it in 1:nt # Compute one forward step backend.forward_onestep_CPML!(model, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, + srccoeij_xx, + srccoeval_xx, + srccoeij_xz, + srccoeval_xz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, srctf_bk, traces_bk, it, @@ -84,8 +94,10 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = # Compute one adjoint step backend.adjoint_onestep_CPML!( model, - reccoeij_bk, - reccoeval_bk, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, residuals_bk, it ) @@ -107,10 +119,14 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = checkpointer, recit -> begin backend.forward_onestep_CPML!(model, - srccoeij_bk, - srccoeval_bk, - reccoeij_bk, - reccoeval_bk, + srccoeij_xx, + srccoeval_xx, + srccoeij_xz, + srccoeval_xz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, srctf_bk, nothing, it, @@ -137,8 +153,161 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = gradient_λ .+= back_interp(model.matprop.interp_method_λ, model.matprop.λ, Array(grid.fields["grad_λ_ihalf"].value), 1) gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf"].value), 1) .+ back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_jhalf"].value), 2) + # TODO smooth gradients + # Compute regularization if needed + ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) + # Return gradients + return Dict( + "rho" => gradient_ρ .+ ∂χ_∂ρ, + "lambda" => gradient_λ .+ ∂χ_∂λ, + "mu" => gradient_μ .+ ∂χ_∂μ + ) +end + +@views function swgradient_1shot!( + ::CPMLBoundaryCondition, + model::ElasticIsoCPMLWaveSimulation{T, 2}, + shot::ExternalForceShot{T, 2}, + misfit::AbstractMisfit +)::Dict{String, Array{T, 2}} where {T} + # scale source time function + srccoeij_vx, srccoeval_vx, + srccoeij_vz, srccoeval_vz, + reccoeij_vx, reccoeval_vx, + reccoeij_vz, reccoeval_vz, + scal_srctf = possrcrec_scaletf(model, shot) + + # Get computational grid, checkpointer and backend + grid = model.grid + checkpointer = model.checkpointer + backend = select_backend(typeof(model), model.parall) + + # Numerics + nt = model.nt + # Wrap sources and receivers arrays + srccoeij_vx = backend.Data.Array(srccoeij_vx) + srccoeval_vx = backend.Data.Array(srccoeval_vx) + srccoeij_vz = backend.Data.Array(srccoeij_vz) + srccoeval_vz = backend.Data.Array(srccoeval_vz) + reccoeij_vx = backend.Data.Array(reccoeij_vx) + reccoeval_vx = backend.Data.Array(reccoeval_vx) + reccoeij_vz = backend.Data.Array(reccoeij_vz) + reccoeval_vz = backend.Data.Array(reccoeval_vz) + srctf_bk = backend.Data.Array(scal_srctf) + traces_bk = backend.zeros(T, size(shot.recs.seismograms)) + + # Reset wavesim + reset!(model) + + # Forward time loop + for it in 1:nt + # Compute one forward step + backend.forward_onestep_CPML!(model, + srccoeij_vx, + srccoeval_vx, + srccoeij_vz, + srccoeval_vz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, + srctf_bk, + traces_bk, + it; + save_trace=true) + + # Print timestep info + if it % model.infoevery == 0 + # Move the cursor to the beginning to overwrite last line + # ter = REPL.Terminals.TTYTerminal("", stdin, stdout, stderr) + # REPL.Terminals.clear_line(ter) + # REPL.Terminals.cmove_line_up(ter) + @info @sprintf( + "Iteration: %d/%d, simulation time: %g s", + it, nt, + model.dt * (it - 1) + ) + end + # Save checkpoint + savecheckpoint!(checkpointer, "σ" => grid.fields["σ"], it) + savecheckpoint!(checkpointer, "v" => grid.fields["v"], it) + savecheckpoint!(checkpointer, "ψ_∂σ∂x" => grid.fields["ψ_∂σ∂x"], it) + savecheckpoint!(checkpointer, "ψ_∂σ∂z" => grid.fields["ψ_∂σ∂z"], it) + savecheckpoint!(checkpointer, "ψ_∂v∂x" => grid.fields["ψ_∂v∂x"], it) + savecheckpoint!(checkpointer, "ψ_∂v∂z" => grid.fields["ψ_∂v∂z"], it) + end - @show maximum(gradient_ρ), maximum(gradient_λ), maximum(gradient_μ) + @info "Saving seismograms" + copyto!(shot.recs.seismograms, traces_bk) + + @debug "Computing residuals" + residuals_bk = backend.Data.Array(dχ_du(misfit, shot.recs)) + + @debug "Computing gradients" + # Adjoint time loop (backward in time) + for it in nt:-1:1 + # Compute one adjoint step + backend.adjoint_onestep_CPML!( + model, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, + residuals_bk, + it + ) + # Print timestep info + if it % model.infoevery == 0 + @info @sprintf("Backward iteration: %d", it) + end + # Check if out of save buffer + if !issaved(checkpointer, "v", it - 1) + @debug @sprintf("Out of save buffer at iteration: %d", it) + initrecover!(checkpointer) + copyto!(grid.fields["σ"], getsaved(checkpointer, "σ", checkpointer.curr_checkpoint)) + copyto!(grid.fields["v"], getsaved(checkpointer, "v", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂σ∂x"], getsaved(checkpointer, "ψ_∂σ∂x", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂σ∂z"], getsaved(checkpointer, "ψ_∂σ∂z", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂v∂x"], getsaved(checkpointer, "ψ_∂v∂x", checkpointer.curr_checkpoint)) + copyto!(grid.fields["ψ_∂v∂z"], getsaved(checkpointer, "ψ_∂v∂z", checkpointer.curr_checkpoint)) + recover!( + checkpointer, + recit -> begin + backend.forward_onestep_CPML!(model, + srccoeij_vx, + srccoeval_vx, + srccoeij_vz, + srccoeval_vz, + reccoeij_vx, + reccoeval_vx, + reccoeij_vz, + reccoeval_vz, + srctf_bk, + nothing, + it, + fx_bk, fz_bk; + save_trace=false) + return ["v" => grid.fields["v"]] + end + ) + end + # Get velocity fields from saved buffer + v_curr = getsaved(checkpointer, "v", it).value + v_old = getsaved(checkpointer, "v", it - 1).value + # Correlate for gradient computation + backend.correlate_gradients!(grid, v_curr, v_old, model.dt, model.cpmlparams.freeboundtop) + end + # Allocate gradients + gradient_ρ = zeros(T, grid.size...) + gradient_λ = zeros(T, grid.size...) + gradient_μ = zeros(T, grid.size...) + # Get gradients + copyto!(gradient_ρ, grid.fields["grad_ρ"].value) + # Compute chain rules for back interpolations + gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf_jhalf"].value), [1, 2]) + gradient_λ .+= back_interp(model.matprop.interp_method_λ, model.matprop.λ, Array(grid.fields["grad_λ_ihalf"].value), 1) + gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf"].value), 1) .+ + back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_jhalf"].value), 2) # TODO smooth gradients # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) diff --git a/src/models/elastic/ela_material_properties.jl b/src/models/elastic/ela_material_properties.jl index db2d563..9c7016f 100644 --- a/src/models/elastic/ela_material_properties.jl +++ b/src/models/elastic/ela_material_properties.jl @@ -14,9 +14,9 @@ Base.@kwdef mutable struct ElasticIsoMaterialProperties{T, N} <: AbstrElasticIso "Density" ρ::Array{T, N} "Interpolation method for density" - interp_method_ρ::InterpolationMethod = ArithmeticAverageInterpolation(2) + interp_method_ρ::AbstractInterpolationMethod = ArithmeticAverageInterpolation() "Interpolation method for density" - interp_method_λ::InterpolationMethod = ArithmeticAverageInterpolation(2) + interp_method_λ::AbstractInterpolationMethod = HarmonicAverageInterpolation() "Interpolation method for density" - interp_method_μ::InterpolationMethod = ArithmeticAverageInterpolation(2) + interp_method_μ::AbstractInterpolationMethod = ArithmeticAverageInterpolation() end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 3c929e7..bc8fee9 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,26 +2,102 @@ # Functions for all ElasticIsoWaveSimulation subtypes +function spreadsrcrecinterp2D( + gridspacing::NTuple{N, T}, + gridsize::NTuple{N, Int}, + positions::Matrix{T}; + nptssinc::Int=4, xstart::T=0.0, zstart::T=0.0 +) where {T, N} + nloc = size(positions, 1) + Ndim = size(positions, 2) + @assert Ndim == 2 + @assert N == Ndim + + Δx = gridspacing[1] + Δz = gridspacing[2] + nx, nz = gridsize[1:2] + + maxnumcoeff = nloc * (2 * nptssinc + 1)^Ndim + coeij_tmp = zeros(Int, maxnumcoeff, Ndim + 1) + coeval_tmp = zeros(T, maxnumcoeff) + l = 0 + for p in 1:nloc + # extract x and z position for source or receiver p + xpos, zpos = positions[p, :] + # compute grid indices and values of sinc coefficients + xidx, zidx, xzcoeff = coeffsinc2D(xstart, zstart, Δx, Δz, xpos, zpos, + nx, nz, [:monopole, :monopole]; npts=nptssinc) + for j in eachindex(zidx) + for i in eachindex(xidx) + l += 1 + # id, i, j indices + coeij_tmp[l, :] .= (p, xidx[i], zidx[j]) + # coefficients value + coeval_tmp[l] = xzcoeff[i, j] + end + end + end + # keep only the valid part of the arrays + coeij = coeij_tmp[1:l, :] + coeval = coeval_tmp[1:l] + + return coeij, coeval +end + # Scaling for ElasticIsoWaveSimulation -@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T}) where {T} - # interpolation coefficients for sources - srccoeij, srccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.srcs.positions; +@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalForceShot{T, 2}) where {T} + # interpolation coefficients for sources in vx + srccoeij_vx, srccoeval_vx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for sources in vz + srccoeij_vz, srccoeval_vz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + # interpolation coefficients for receivers in vx + reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for receivers in vz + reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + # scale source time function with boxcar and timestep size + scal_srctf = shot.srcs.tf ./ prod(model.grid.spacing) .* model.dt + + return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf +end + +@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}) where {T} + # interpolation coefficients for sources in σxx and σzz + srccoeij_xx, srccoeval_xx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=0.0) + # interpolation coefficients for sources in σxz + srccoeij_xz, srccoeval_xz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=model.grid.spacing[2]/2) + # interpolation coefficients for receivers in vx + reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; nptssinc=4, xstart=0.0, zstart=0.0) - # interpolation coefficients for receivers - reccoeij, reccoeval = spreadsrcrecinterp2D(model.grid.spacing, model.grid.size, - shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for receivers in vz + reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + # scale source time function with boxcar and timestep size scal_srctf = shot.srcs.tf ./ prod(model.grid.spacing) .* model.dt - return srccoeij, srccoeval, reccoeij, reccoeval, scal_srctf + return srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf end + + @views function check_matprop(model::ElasticIsoWaveSimulation{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Checks - @assert all(matprop.λ .> 0) "Lamè coefficient λ must be positive!" - @assert all(matprop.μ .> 0) "Lamè coefficient μ must be positive!" + @assert all(matprop.λ .>= 0) "Lamè coefficient λ must be positive!" + @assert all(matprop.μ .>= 0) "Lamè coefficient μ must be positive!" @assert all(matprop.ρ .> 0) "Density must be positive!" vp = sqrt.((matprop.λ .+ 2.0 .* matprop.μ) ./ matprop.ρ) @assert ndims(vp) == N "Material property dimensionality must be the same as the wavesim!" @@ -41,12 +117,16 @@ end function check_numerics( model::ElasticIsoWaveSimulation{T}, - shot::MomentTensorShot{T}; + shot::Union{MomentTensorShot{T}, ExternalForceShot{T}}; min_ppw::Int=10 ) where {T} # Check points per wavelengh # min Vs vel_min = get_minimum_func(model)(sqrt.(model.matprop.μ ./ model.matprop.ρ)) + if vel_min == 0 + # compute minimum vp + vel_min = get_minimum_func(model)(sqrt.((model.matprop.λ .+ 2.0 .* model.matprop.μ) ./ model.matprop.ρ)) + end h_max = maximum(model.grid.spacing) fmax = shot.srcs.domfreq * 2.0 ppw = vel_min / (fmax * h_max) @@ -274,6 +354,9 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac @assert infoevery >= 1 && infoevery <= nt "Infoevery parameter must be positive and less then nt!" end + # Deep copy the material properties + matprop = deepcopy(matprop) + return new{T, N, A, V}( params, cpmlparams, diff --git a/src/shots/shot.jl b/src/shots/shot.jl index 7c7eb94..e4d8f46 100644 --- a/src/shots/shot.jl +++ b/src/shots/shot.jl @@ -27,6 +27,21 @@ Base.@kwdef struct MomentTensorShot{T, N, M <: MomentTensor{T, N}} <: Shot{T} recs::VectorReceivers{T, N} end + +""" +$(TYPEDEF) + +Type representing a shot with external force sources and multi-component receivers. + +$(TYPEDFIELDS) +""" +Base.@kwdef struct ExternalForceShot{T, N} <: Shot{T} + "Structure containing the ExternalForcesSources for a given simulation." + srcs::ExternalForceSources{T, N} + "Structure containing the VectorReceivers for a given simulation." + recs::VectorReceivers{T, N} +end + ################################################## function init_shot!(model::WaveSimulation{T}, shot::Shot{T}; kwargs...) where {T} diff --git a/src/shots/sources.jl b/src/shots/sources.jl index edcc7ed..ca7d763 100644 --- a/src/shots/sources.jl +++ b/src/shots/sources.jl @@ -70,9 +70,23 @@ struct MomentTensorSources{T, N, M <: MomentTensor{T, N}} <: Sources{T} function MomentTensorSources(positions::Matrix{T}, tf::Matrix{T}, momtens::Vector{M}, domfreq::T) where {T, N, M <: MomentTensor{T, N}} @assert size(positions, 1) > 0 "There must be at least one source!" @assert size(positions, 1) == size(tf, 2) "Number of sources do not match between positions and time-functions!" - @assert length(momtens) == size(positions, 1) + @assert length(momtens) == size(positions, 1) "Number of moment tensors must match number of sources!" return new{T, N, M}(positions, tf, momtens, domfreq) end end +struct ExternalForceSources{T, N} <: Sources{T} + positions::Matrix{T} + tf::Array{T, 3} + domfreq::T + + function ExternalForceSources(positions::Matrix{T}, tf::Array{T, 3}, domfreq::T) where {T} + @assert size(positions, 1) > 0 "There must be at least one source!" + @assert size(positions, 1) == size(tf, 3) "Number of sources do not match between positions and time-functions!" + @assert size(tf, 2) == size(positions, 2) "Number of components do not match between time-functions and positions!" + N = size(tf, 2) + return new{T, N}(positions, tf, domfreq) + end +end + #################################################### diff --git a/src/utils/abstract_types.jl b/src/utils/abstract_types.jl index 61edf92..a6f251a 100644 --- a/src/utils/abstract_types.jl +++ b/src/utils/abstract_types.jl @@ -77,7 +77,7 @@ abstract type Receivers{T} end abstract type MomentTensor{T, N} end -abstract type InterpolationMethod end +abstract type AbstractInterpolationMethod end abstract type AbstractMisfit end diff --git a/src/utils/checks.jl b/src/utils/checks.jl index a9a0a1e..d21b1c3 100644 --- a/src/utils/checks.jl +++ b/src/utils/checks.jl @@ -28,6 +28,12 @@ function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialPro tysource <: MomentTensorSources{T, 2, MomentTensor2D{T}} && tyreceiver <: VectorReceivers{T, N} return + + elseif model isa ElasticIsoCPMLWaveSimulation{T, 2} && # <<<<<---------<<<< + matprop isa ElasticIsoMaterialProperties{T, 2} && + tysource <: ExternalForceSources{T, 2} && + tyreceiver <: VectorReceivers{T, N} + return end return error("Types of WaveSimulation, MaterialProperties and Sources/Receivers are inconsistent \ diff --git a/src/utils/interpolations.jl b/src/utils/interpolations.jl index ffaaade..341d5c4 100644 --- a/src/utils/interpolations.jl +++ b/src/utils/interpolations.jl @@ -1,52 +1,47 @@ -interpolate(m::Array{T, N}, interp_method) where {T, N} = collect(interp(interp_method, m, i) for i in 1:N) +interpolate(m::Array{T, N}, interp_method::AbstractInterpolationMethod) where {T, N} = collect(interp(interp_method, m, i) for i in 1:N) -interp(method, m::Array{<:Real, N}, dim::Int) where {N} = interp(method, m, [dim]) -interp(method, m::Array{<:Real, N}, dims::Vector{Int}) where {N} = method(m, dims) +interp(method::AbstractInterpolationMethod, m::Array{<:Real, N}, dim::Int) where {N} = interp(method, m, [dim]) +interp(method::AbstractInterpolationMethod, m::Array{<:Real, N}, dims::Vector{Int}) where {N} = method(m, dims) + +function binary_permutations(N::Int) + permutations = [] + for i in 0:(2^N - 1) + binary_str = bitstring(i)[end-N+1:end] + push!(permutations, [parse(Int, c) for c in binary_str]) + end + return permutations +end back_interp(method, m::Array{T, N}, ∂χ∂m_interp::Array{T, N}, dim::Int) where {T, N} = back_interp(method, m, ∂χ∂m_interp, [dim]) back_interp(method, m::Array{T, N}, ∂χ∂m_interp::Array{T, N}, dims::Vector{Int}) where {T, N} = begin res = zeros(T, size(m)) - for k in 1:method.width - m_idxs = CartesianIndices(Tuple( - i in dims ? (k:size(res, i)+k-method.width) : (1:size(res, i)) for i in 1:N + perms = binary_permutations(length(dims)) + for p in perms + pp = zeros(Int, N) + pp[dims] .= p + idxs = CartesianIndices(Tuple( + i in dims ? (1:size(m, i) - 1) .+ pp[i] : (1:size(m, i)) for i in 1:N )) - res[m_idxs] .+= ∂χ∂m_interp .* ∂f∂m(method, m, k, dims) + res[idxs] .+= ∂χ∂m_interp .* ∂f∂m(method, m, idxs, dims) end return res end # Arithmetic average interpolation - -struct ArithmeticAverageInterpolation <: InterpolationMethod - width::Int -end +struct ArithmeticAverageInterpolation <: AbstractInterpolationMethod end +# Harmonic average interpolation +struct HarmonicAverageInterpolation <: AbstractInterpolationMethod end @views function (itp::ArithmeticAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} - return sum( - m[CartesianIndices(Tuple(i in dims ? (j:size(m, i)+j-itp.width) : (1:size(m, i)) for i in 1:N))] for j in 1:itp.width - ) ./ (itp.width^length(dims)) + itp = Interpolations.interpolate(m, BSpline(Linear())) + return itp([i in dims ? (1.5:size(m,i)-0.5) : (1:size(m,i)) for i in 1:N]...) end -∂f∂m(itp::ArithmeticAverageInterpolation, m::Array{T, N}, _::Int, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (itp.width^length(dims)) - -# Armonic average interpolation - -struct ArmonicAverageInterpolation <: InterpolationMethod - width::Int +@views function (itp::HarmonicAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} + itp = Interpolations.interpolate(1 ./ m, BSpline(Linear())) + return 1 ./ itp([i in dims ? (1.5:size(m,i)-0.5) : (1:size(m,i)) for i in 1:N]...) end -@views function (itp::ArmonicAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} - return (itp.width^length(dims)) ./ sum( - 1 ./ m[CartesianIndices(Tuple(i in dims ? (j:size(m, i)+j-itp.width) : (1:size(m, i)) for i in 1:N))] for j in 1:itp.width - ) -end +∂f∂m(_::ArithmeticAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (2^length(dims)) -function ∂f∂m(itp::ArmonicAverageInterpolation, m::Array{T, N}, k::Int, dims::Vector{Int}) where {T, N} - m_idxs = CartesianIndices(Tuple( - i in dims ? (k:size(m, i)+k-itp.width) : (1:size(m, i)) for i in 1:N - )) - return (itp.width^length(dims)) ./ - sum( - 1 ./ m[CartesianIndices(Tuple(i in dims ? (j:size(m, i)+j-itp.width) : (1:size(m, i)) for i in 1:N))] for j in 1:itp.width - ) .^ 2 .* m[m_idxs] -end \ No newline at end of file +∂f∂m(itp::HarmonicAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = (itp(m, dims).^2) ./ (m[idxs] .^2) ./ (2^length(dims)) \ No newline at end of file diff --git a/src/utils/utils.jl b/src/utils/utils.jl index 370146b..47b9d5b 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -79,8 +79,7 @@ function kaiser(x::Vector, x0::T, b::T, r::T) where {T} for i in 1:length(x) xcur = x[i] - x0 if -r <= xcur <= r - den = 1.0 / besseli(0, b) - w[i] = den * besseli(0, b * (sqrt.(1 - (xcur / r)^2))) + w[i] = besseli(0, b * (sqrt(1 - (xcur / r)^2))) / besseli(0, b) else w[i] = 0.0 end diff --git a/test/test_gradient_elastic_constant_density.jl b/test/test_gradient_elastic_constant_density.jl index 93e25a7..d931739 100644 --- a/test/test_gradient_elastic_constant_density.jl +++ b/test/test_gradient_elastic_constant_density.jl @@ -54,7 +54,6 @@ with_logger(ConsoleLogger(stderr, Logging.Info)) do @test !(misfit ≈ 0.0) @test !(misfit_check ≈ 0.0) # Check that misfits are equivalent - @show misfit, misfit_check @test misfit ≈ misfit_check end end diff --git a/test/test_interpolations.jl b/test/test_interpolations.jl new file mode 100644 index 0000000..a5922aa --- /dev/null +++ b/test/test_interpolations.jl @@ -0,0 +1,210 @@ +using Test +using SeismicWaves: interpolate, interp, ArithmeticAverageInterpolation, HarmonicAverageInterpolation +using SeismicWaves: ∂f∂m, back_interp + +# Test ArithmeticAverageInterpolation for 1D array +function test_arithmetic_average_interpolation_1d() + m = [1.0, 2.0, 3.0, 4.0] + itp = ArithmeticAverageInterpolation() + @test interpolate(m, itp)[1] == [1.5, 2.5, 3.5] + @test interp(itp, m, 1) == [1.5, 2.5, 3.5] + @test ∂f∂m(itp, m, [1, 2, 3], [1]) == [0.5, 0.5, 0.5] + @test ∂f∂m(itp, m, [2, 3, 4], [1]) == [0.5, 0.5, 0.5] +end + +# Test HarmonicAverageInterpolation for 1D array +function test_harmonic_average_interpolation_1d() + m = [1.0, 2.0, 3.0, 4.0] + dims = [1] + itp = HarmonicAverageInterpolation() + + g = [1/m[1] + 1/m[2], 1/m[2] + 1/m[3], 1/m[3] + 1/m[4]] + + @test interpolate(m, itp)[1] ≈ [1.333, 2.4, 3.428] atol=1e-3 + @test interp(itp, m, 1) ≈ [1.333, 2.4, 3.428] atol=1e-3 + @test ∂f∂m(itp, m, [1, 2, 3], dims) ≈ (-2 ./ (g.^2)) .* (-1 ./ (m[1:end-1].^2)) atol=1e-3 + @test ∂f∂m(itp, m, [2, 3, 4], dims) ≈ (-2 ./ (g.^2)) .* (-1 ./ (m[2:end ].^2)) atol=1e-3 +end + +# Test back_interp for 1D array +function test_back_interp_1d() + m = [1.0, 2.0, 3.0, 4.0] + ∂χ∂m_interp = [0.1, 0.2, 0.3] + dims = [1] + itp = ArithmeticAverageInterpolation() + expected = zeros(4) + expected[1:end-1] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, 1, dims) + expected[2:end] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, 2, dims) + + @test back_interp(itp, m, ∂χ∂m_interp, dims) ≈ expected +end + +# Test back_interp for HarmonicAverageInterpolation for 1D array +function test_back_interp_harmonic_1d() + m = [1.0, 2.0, 3.0, 4.0] + ∂χ∂m_interp = [0.1, 0.2, 0.3] + dims = [1] + itp = HarmonicAverageInterpolation() + expected = zeros(4) + expected[1:end-1] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, [1,2,3], dims) + expected[2:end] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, [2,3,4], dims) + + @test back_interp(itp, m, ∂χ∂m_interp, dims) ≈ expected +end + +# Test ArithmeticAverageInterpolation for 2D array +function test_arithmetic_average_interpolation_2d() + m = [1.0 2.0 3.0; + 4.0 5.0 6.0; + 7.0 8.0 9.0] + itp = ArithmeticAverageInterpolation() + + @test interpolate(m, itp)[1] == [ + 2.5 3.5 4.5; + 5.5 6.5 7.5 + ] + @test interpolate(m, itp)[2] == [ + 1.5 2.5; + 4.5 5.5; + 7.5 8.5 + ] + @test interp(itp, m, [1, 2]) == [ + 3.0 4.0; + 6.0 7.0 + ] + @test ∂f∂m(itp, m, [1:2, 1:2], [1, 2]) == [ + 0.25 0.25; + 0.25 0.25 + ] + @test ∂f∂m(itp, m, [1:2, 2:3], [1, 2]) == [ + 0.25 0.25; + 0.25 0.25 + ] + @test ∂f∂m(itp, m, [2:3, 1:2], [1, 2]) == [ + 0.25 0.25; + 0.25 0.25 + ] + @test ∂f∂m(itp, m, [2:3, 2:3], [1, 2]) == [ + 0.25 0.25; + 0.25 0.25 + ] +end + +# Test HarmonicAverageInterpolation for 2D array +function test_harmonic_average_interpolation_2d() + m = [1.0 2.0 3.0; + 4.0 5.0 6.0; + 7.0 8.0 9.0] + itp = HarmonicAverageInterpolation() + + g1 = 1/m[1,1] + 1/m[1,2] + 1/m[2,1] + 1/m[2,2] + g2 = 1/m[1,2] + 1/m[1,3] + 1/m[2,2] + 1/m[2,3] + g3 = 1/m[2,1] + 1/m[2,2] + 1/m[3,1] + 1/m[3,2] + g4 = 1/m[2,2] + 1/m[2,3] + 1/m[3,2] + 1/m[3,3] + g = [g1 g2; g3 g4] + + @test interpolate(m, itp)[1] ≈ [ + 2/(1/m[1,1] + 1/m[2,1]) 2/(1/m[1,2] + 1/m[2,2]) 2/(1/m[1,3] + 1/m[2,3]); + 2/(1/m[2,1] + 1/m[3,1]) 2/(1/m[2,2] + 1/m[3,2]) 2/(1/m[2,3] + 1/m[3,3]) + ] + @test interpolate(m, itp)[2] ≈ [ + 2/(1/m[1,1] + 1/m[1,2]) 2/(1/m[1,2] + 1/m[1,3]); + 2/(1/m[2,1] + 1/m[2,2]) 2/(1/m[2,2] + 1/m[2,3]); + 2/(1/m[3,1] + 1/m[3,2]) 2/(1/m[3,2] + 1/m[3,3]) + ] + @test interp(itp, m, [1,2]) ≈ 4 ./ g + @test ∂f∂m(itp, m, CartesianIndices((1:2, 1:2)), [1, 2]) ≈ (-4 ./ g.^2) .* (-1 ./ (m[1:2,1:2].^2)) + @test ∂f∂m(itp, m, CartesianIndices((1:2, 2:3)), [1, 2]) ≈ (-4 ./ g.^2) .* (-1 ./ (m[1:2,2:3].^2)) + @test ∂f∂m(itp, m, CartesianIndices((2:3, 1:2)), [1, 2]) ≈ (-4 ./ g.^2) .* (-1 ./ (m[2:3,1:2].^2)) + @test ∂f∂m(itp, m, CartesianIndices((2:3, 2:3)), [1, 2]) ≈ (-4 ./ g.^2) .* (-1 ./ (m[2:3,2:3].^2)) + + g151 = 1/m[1,1] + 1/m[2,1] + g152 = 1/m[1,2] + 1/m[2,2] + g153 = 1/m[1,3] + 1/m[2,3] + g251 = 1/m[2,1] + 1/m[3,1] + g252 = 1/m[2,2] + 1/m[3,2] + g253 = 1/m[2,3] + 1/m[3,3] + g15 = [g151 g152 g153; g251 g252 g253] + @test interp(itp, m, 1) ≈ [ + 2/(1/m[1,1] + 1/m[2,1]) 2/(1/m[1,2] + 1/m[2,2]) 2/(1/m[1,3] + 1/m[2,3]); + 2/(1/m[2,1] + 1/m[3,1]) 2/(1/m[2,2] + 1/m[3,2]) 2/(1/m[2,3] + 1/m[3,3]) + ] + @test ∂f∂m(itp, m, CartesianIndices((1:2, 1:3)), [1]) ≈ (-2 ./ (g15.^2)) .* (-1 ./ (m[1:2,1:3].^2)) + @test ∂f∂m(itp, m, CartesianIndices((2:3, 1:3)), [1]) ≈ (-2 ./ (g15.^2)) .* (-1 ./ (m[2:3,1:3].^2)) + + g115 = 1/m[1,1] + 1/m[1,2] + g125 = 1/m[1,2] + 1/m[1,3] + g215 = 1/m[2,1] + 1/m[2,2] + g225 = 1/m[2,2] + 1/m[2,3] + g315 = 1/m[3,1] + 1/m[3,2] + g325 = 1/m[3,2] + 1/m[3,3] + g25 = [g115 g125; g215 g225; g315 g325] + @test interp(itp, m, 2) ≈ [ + 2/(1/m[1,1] + 1/m[1,2]) 2/(1/m[1,2] + 1/m[1,3]); + 2/(1/m[2,1] + 1/m[2,2]) 2/(1/m[2,2] + 1/m[2,3]); + 2/(1/m[3,1] + 1/m[3,2]) 2/(1/m[3,2] + 1/m[3,3]) + ] + @test ∂f∂m(itp, m, CartesianIndices((1:3, 1:2)), [2]) ≈ (-2 ./ (g25.^2)) .* (-1 ./ (m[1:3,1:2].^2)) + @test ∂f∂m(itp, m, CartesianIndices((1:3, 2:3)), [2]) ≈ (-2 ./ (g25.^2)) .* (-1 ./ (m[1:3,2:3].^2)) +end + +# Test back_interp for 2D array +function test_back_interp_2d() + m = [1.0 2.0 3.0; + 4.0 5.0 6.0; + 7.0 8.0 9.0] + ∂χ∂m_interp = [0.1 0.2; 0.3 0.4] + dims = [1, 2] + itp = ArithmeticAverageInterpolation() + expected = zeros(3, 3) + expected[1:2, 1:2] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((1:2, 1:2)), dims) + expected[1:2, 2:3] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((1:2, 2:3)), dims) + expected[2:3, 1:2] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((2:3, 1:2)), dims) + expected[2:3, 2:3] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((2:3, 2:3)), dims) + + @test back_interp(itp, m, ∂χ∂m_interp, dims) ≈ expected +end + +# Test back_interp for HarmonicAverageInterpolation for 2D array +function test_back_interp_harmonic_2d() + m = [1.0 2.0 3.0; + 4.0 5.0 6.0; + 7.0 8.0 9.0] + ∂χ∂m_interp = [0.1 0.2; 0.3 0.4] + dims = [1, 2] + itp = HarmonicAverageInterpolation() + expected = zeros(3, 3) + expected[1:2, 1:2] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((1:2, 1:2)), dims) + expected[1:2, 2:3] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((1:2, 2:3)), dims) + expected[2:3, 1:2] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((2:3, 1:2)), dims) + expected[2:3, 2:3] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((2:3, 2:3)), dims) + + @test back_interp(itp, m, ∂χ∂m_interp, dims) ≈ expected + + dims = [1] + expected = zeros(3, 3) + ∂χ∂m_interp = [0.1 0.2 0.3; 0.4 0.5 0.6] + expected[1:2, 1:3] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((1:2, 1:3)), dims) + expected[2:3, 1:3] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((2:3, 1:3)), dims) + @test back_interp(itp, m, ∂χ∂m_interp, dims) ≈ expected + + dims = [2] + expected = zeros(3, 3) + ∂χ∂m_interp = [0.1 0.2; 0.3 0.4; 0.5 0.6] + expected[1:3, 1:2] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((1:3, 1:2)), dims) + expected[1:3, 2:3] .+= ∂χ∂m_interp .* ∂f∂m(itp, m, CartesianIndices((1:3, 2:3)), dims) + @test back_interp(itp, m, ∂χ∂m_interp, dims) ≈ expected + +end + +# Run tests +@testset "Interpolation Tests" begin + test_arithmetic_average_interpolation_1d() + test_harmonic_average_interpolation_1d() + test_back_interp_1d() + test_back_interp_harmonic_1d() + test_arithmetic_average_interpolation_2d() + test_harmonic_average_interpolation_2d() + test_back_interp_2d() + test_back_interp_harmonic_2d() +end \ No newline at end of file From 8d575e4b43da3c5944046c998e3b8f79ad72d487 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 21 Oct 2024 19:00:17 +0200 Subject: [PATCH 078/111] Disable sinc interpolation with flag --- src/models/elastic/ela_forward.jl | 4 +- src/models/elastic/ela_gradient.jl | 4 +- src/models/elastic/ela_models.jl | 129 ++++++++++++++++++++--------- 3 files changed, 96 insertions(+), 41 deletions(-) diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 12d5935..4c3da72 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -9,7 +9,7 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound # scale source time function srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, - scal_srctf = possrcrec_scaletf(model, shot) + scal_srctf = possrcrec_scaletf(model, shot; sincinterp=model.sincinterp) # moment tensors momtens = shot.srcs.momtens @@ -92,7 +92,7 @@ end srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, - scal_srctf = possrcrec_scaletf(model, shot) + scal_srctf = possrcrec_scaletf(model, shot; sincinterp=model.sincinterp) # Get computational grid and backend backend = select_backend(typeof(model), model.parall) diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index a60b06f..4b5b601 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -10,7 +10,7 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = # scale source time function srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, - scal_srctf = possrcrec_scaletf(model, shot) + scal_srctf = possrcrec_scaletf(model, shots; sincinterp=model.sincinterp) # moment tensors momtens = shot.srcs.momtens @@ -175,7 +175,7 @@ end srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, - scal_srctf = possrcrec_scaletf(model, shot) + scal_srctf = possrcrec_scaletf(model, shot; sincinterp=model.sincinterp) # Get computational grid, checkpointer and backend grid = model.grid diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index bc8fee9..bf1839f 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -45,49 +45,100 @@ function spreadsrcrecinterp2D( end # Scaling for ElasticIsoWaveSimulation -@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalForceShot{T, 2}) where {T} - # interpolation coefficients for sources in vx - srccoeij_vx, srccoeval_vx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - # interpolation coefficients for sources in vz - srccoeij_vz, srccoeval_vz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) - # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) +@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalForceShot{T, 2}; sincinterp=false) where {T} + if sincinterp + # interpolation coefficients for sources in vx + srccoeij_vx, srccoeval_vx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for sources in vz + srccoeij_vz, srccoeval_vz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + # interpolation coefficients for receivers in vx + reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for receivers in vz + reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + else + src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) + rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) + nsrcs = size(shot.srcs.positions, 1) + nrecs = size(shot.recs.positions, 1) + srccoeij_vx = zeros(Int, nsrcs, 3) + srccoeval_vx = ones(T, nsrcs) + srccoeij_vz = zeros(Int, nsrcs, 3) + srccoeval_vz = ones(T, nsrcs) + reccoeij_vx = zeros(Int, nrecs, 3) + reccoeval_vx = ones(T, nrecs) + reccoeij_vz = zeros(Int, nrecs, 3) + reccoeval_vz = ones(T, nrecs) + for p in 1:nsrcs + srccoeij_vx[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) + srccoeij_vz[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) + end + for p in 1:nrecs + reccoeij_vx[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) + reccoeij_vz[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) + end + @show srccoeij_vx, srccoeval_vx + @show srccoeij_vz, srccoeval_vz + @show reccoeij_vx, reccoeval_vx + @show reccoeij_vz, reccoeval_vz + end + # scale source time function with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(model.grid.spacing) .* model.dt + scal_srctf = shot.srcs.tf .* model.dt return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf end -@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}) where {T} - # interpolation coefficients for sources in σxx and σzz - srccoeij_xx, srccoeval_xx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=0.0) - # interpolation coefficients for sources in σxz - srccoeij_xz, srccoeval_xz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=0.0, zstart=model.grid.spacing[2]/2) - # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) - # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) +@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}; sincinterp=false) where {T} + if sincinterp + # interpolation coefficients for sources in σxx and σzz + srccoeij_xx, srccoeval_xx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=0.0) + # interpolation coefficients for sources in σxz + srccoeij_xz, srccoeval_xz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.srcs.positions; + nptssinc=4, xstart=0.0, zstart=model.grid.spacing[2]/2) + # interpolation coefficients for receivers in vx + reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; + nptssinc=4, xstart=0.0, zstart=0.0) + # interpolation coefficients for receivers in vz + reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( + model.grid.spacing, model.grid.size, shot.recs.positions; + nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + else + src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) + rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) + nsrcs = size(shot.srcs.positions, 1) + nrecs = size(shot.recs.positions, 1) + srccoeij_xx = zeros(Int, nsrcs, 3) + srccoeval_xx = ones(T, nsrcs) + srccoeij_xz = zeros(Int, nsrcs, 3) + srccoeval_xz = ones(T, nsrcs) + reccoeij_vx = zeros(Int, nrecs, 3) + reccoeval_vx = ones(T, nrecs) + reccoeij_vz = zeros(Int, nrecs, 3) + reccoeval_vz = ones(T, nrecs) + for p in 1:nsrcs + srccoeij_xx[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) + srccoeij_xz[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) + end + for p in 1:nrecs + reccoeij_vx[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) + reccoeij_vz[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) + end + end # scale source time function with boxcar and timestep size - scal_srctf = shot.srcs.tf ./ prod(model.grid.spacing) .* model.dt + scal_srctf = shot.srcs.tf .* model.dt return srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf end @@ -193,6 +244,8 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac checkpointer::Union{Nothing, LinearCheckpointer{T}} # Smooth radius for gradient smooth_radius::Int + # Sinc source receiver interpolation + sincinterp::Bool # Snapshotter setup snapshotter::Union{Nothing, LinearSnapshotter{T, N, Array{T, N}}} # Parallelization type @@ -207,7 +260,8 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac check_freq::Union{Int, Nothing}=nothing, snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, - smooth_radius::Int=5 + smooth_radius::Int=5, + sincinterp::Bool=false ) where {T, N} # Extract params nt = params.ntimesteps @@ -368,6 +422,7 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac cpmlcoeffs, gradient ? checkpointer : nothing, smooth_radius, + sincinterp, snapevery === nothing ? nothing : snapshotter, parall ) From 52bf989f609ec0ad773e8fd05059cf2902770261 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 21 Oct 2024 20:18:28 +0200 Subject: [PATCH 079/111] Fix sinc interpolation (WIP) --- .../backends/shared/elastic2D_iso_xPU.jl | 80 ++++++--- src/models/elastic/ela_forward.jl | 33 ++-- src/models/elastic/ela_gradient.jl | 33 ++-- src/models/elastic/ela_models.jl | 165 ++++++++---------- 4 files changed, 154 insertions(+), 157 deletions(-) diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index a9d7b51..2cfe8c6 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -259,41 +259,41 @@ end return nothing end -@parallel_indices (p) function inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx, Mzz, srctf_bk, srccoeij_bk, srccoeval_bk, it) - s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] +@parallel_indices (p) function inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx, Mzz, srctf_bk, srccoeij_bk, srccoeval_bk, it, s) + isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it, s] σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it, s] return nothing end -@parallel_indices (p) function inject_momten_sources2D_σxz!(σxz, Mxz, srctf_bk, srccoeij_bk, srccoeval_bk, it) - s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] +@parallel_indices (p) function inject_momten_sources2D_σxz!(σxz, Mxz, srctf_bk, srccoeij_bk, srccoeval_bk, it, s) + isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it, s] return nothing end -@parallel_indices (p) function inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_bk, srccoeval_bk, ρ, it) - s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] +@parallel_indices (p) function inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_bk, srccoeval_bk, ρ, it, s) + isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] vx[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 1, s] / ρ[isrc, jsrc] return nothing end -@parallel_indices (p) function inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_bk, srccoeval_bk, ρ_ihalf_jhalf, it) - s, isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2], srccoeij_bk[p, 3] +@parallel_indices (p) function inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_bk, srccoeval_bk, ρ_ihalf_jhalf, it, s) + isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] vz[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 2, s] / ρ_ihalf_jhalf[isrc, jsrc] return nothing end -@parallel_indices (p) function record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it) - r, irec, jrec = reccoeij_vx[p, 1], reccoeij_vx[p, 2], reccoeij_vx[p, 3] +@parallel_indices (p) function record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it, r) + irec, jrec = reccoeij_vx[p, 1], reccoeij_vx[p, 2] traces_bk[it, 1, r] += reccoeval_vx[p] * vx[irec, jrec] return nothing end -@parallel_indices (p) function record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it) - r, irec, jrec = reccoeij_vz[p, 1], reccoeij_vz[p, 2], reccoeij_vz[p, 3] +@parallel_indices (p) function record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it, r) + irec, jrec = reccoeij_vz[p, 1], reccoeij_vz[p, 2] traces_bk[it, 2, r] += reccoeval_vz[p] * vz[irec, jrec] return nothing end @@ -363,10 +363,16 @@ function forward_onestep_CPML!( # record receivers if save_trace - nrecpts_vx = size(reccoeij_vx, 1) - nrecpts_vz = size(reccoeij_vz, 1) - @parallel (1:nrecpts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it) - @parallel (1:nrecpts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it) + nrecs_vx = size(reccoeij_vx, 1) + nrecs_vz = size(reccoeij_vz, 1) + for r in 1:nrecs_vx + nrecspts_vx = size(reccoeij_vx[r], 1) + @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx[r], reccoeval_vx[r], it, r) + end + for r in 1:nrecs_vz + nrecspts_vz = size(reccoeij_vz[r], 1) + @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz[r], reccoeval_vz[r], it, r) + end end # update stresses σxx and σzz @@ -380,10 +386,16 @@ function forward_onestep_CPML!( ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) # inject sources (moment tensor type of internal force) - nsrcpts_xx = size(srccoeij_xx, 1) - nsrcpts_xz = size(srccoeij_xz, 1) - @parallel (1:nsrcpts_xx) inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx_bk, Mzz_bk, srctf_bk, srccoeij_xx, srccoeval_xx, it) - @parallel (1:nsrcpts_xz) inject_momten_sources2D_σxz!(σxz, Mxz_bk, srctf_bk, srccoeij_xz, srccoeval_xz, it) + nrecs_xx = size(srccoeij_xx, 1) + nrecs_xz = size(srccoeij_xz, 1) + for s in 1:nrecs_xx + nsrcpts_xx = size(srccoeij_xx[s], 1) + @parallel (1:nsrcpts_xx) inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx_bk, Mzz_bk, srctf_bk, srccoeij_xx[s], srccoeval_xx[s], it, s) + end + for s in 1:nrecs_xz + nsrcpts_xz = size(srccoeij_xz[s], 1) + @parallel (1:nsrcpts_xz) inject_momten_sources2D_σxz!(σxz, Mxz_bk, srctf_bk, srccoeij_xz[s], srccoeval_xz[s], it, s) + end return end @@ -449,17 +461,29 @@ function forward_onestep_CPML!( ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # inject sources (residuals as velocities) - nsrcpts_vx = size(srccoeij_vx, 1) - nsrcpts_vz = size(srccoeij_vz, 1) - @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_vx, srccoeval_vx, ρ, it) - @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_vz, srccoeval_vz, ρ_ihalf_jhalf, it) + nsrcs_vx = size(srccoeij_vx, 1) + nsrcs_vz = size(srccoeij_vz, 1) + for s in 1:nsrcs_vx + nsrcpts_vx = size(srccoeij_vx[s], 1) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_vx[s], srccoeval_vx[s], ρ, it, s) + end + for s in 1:nsrcs_vz + nsrcpts_vz = size(srccoeij_vz[s], 1) + @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_ihalf_jhalf, it, s) + end # record receivers if save_trace - nrecpts_vx = size(reccoeij_vx, 1) - nrecpts_vz = size(reccoeij_vz, 1) - @parallel (1:nrecpts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it) - @parallel (1:nrecpts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it) + nrecs_vx = size(reccoeij_vx, 1) + nrecs_vz = size(reccoeij_vz, 1) + for r in 1:nrecs_vx + nrecspts_vx = size(reccoeij_vx[r], 1) + @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx[r], reccoeval_vx[r], it, r) + end + for r in 1:nrecs_vz + nrecspts_vz = size(reccoeij_vz[r], 1) + @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz[r], reccoeval_vz[r], it, r) + end end # update stresses σxx and σzz diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 4c3da72..f5d7a78 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -20,14 +20,14 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound nt = model.nt # Wrap sources and receivers arrays - srccoeij_xx = backend.Data.Array(srccoeij_xx) - srccoeval_xx = backend.Data.Array(srccoeval_xx) - srccoeij_xz = backend.Data.Array(srccoeij_xz) - srccoeval_xz = backend.Data.Array(srccoeval_xz) - reccoeij_vx = backend.Data.Array(reccoeij_vx) - reccoeval_vx = backend.Data.Array(reccoeval_vx) - reccoeij_vz = backend.Data.Array(reccoeij_vz) - reccoeval_vz = backend.Data.Array(reccoeval_vz) + srccoeij_xx = [backend.Data.Array(srccoeij_xx[i]) for i in eachindex(srccoeij_xx)] + srccoeval_xx = [backend.Data.Array(srccoeval_xx[i]) for i in eachindex(srccoeval_xx)] + srccoeij_xz = [backend.Data.Array(srccoeij_xz[i]) for i in eachindex(srccoeij_xz)] + srccoeval_xz = [backend.Data.Array(srccoeval_xz[i]) for i in eachindex(srccoeval_xz)] + reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] + reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) @@ -101,14 +101,15 @@ end nt = model.nt # Wrap sources and receivers arrays - srccoeij_vx = backend.Data.Array(srccoeij_vx) - srccoeval_vx = backend.Data.Array(srccoeval_vx) - srccoeij_vz = backend.Data.Array(srccoeij_vz) - srccoeval_vz = backend.Data.Array(srccoeval_vz) - reccoeij_vx = backend.Data.Array(reccoeij_vx) - reccoeval_vx = backend.Data.Array(reccoeval_vx) - reccoeij_vz = backend.Data.Array(reccoeij_vz) - reccoeval_vz = backend.Data.Array(reccoeval_vz) + srccoeij_vx = [backend.Data.Array(srccoeij_vx[i]) for i in eachindex(srccoeij_vx)] + srccoeval_vx = [backend.Data.Array(srccoeval_vx[i]) for i in eachindex(srccoeval_vx)] + srccoeij_vz = [backend.Data.Array(srccoeij_vz[i]) for i in eachindex(srccoeij_vz)] + srccoeval_vz = [backend.Data.Array(srccoeval_vz[i]) for i in eachindex(srccoeval_vz)] + reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] + reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] + srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index 4b5b601..fedf13f 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -22,14 +22,14 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = # Numerics nt = model.nt # Wrap sources and receivers arrays - srccoeij_xx = backend.Data.Array(srccoeij_xx) - srccoeval_xx = backend.Data.Array(srccoeval_xx) - srccoeij_xz = backend.Data.Array(srccoeij_xz) - srccoeval_xz = backend.Data.Array(srccoeval_xz) - reccoeij_vx = backend.Data.Array(reccoeij_vx) - reccoeval_vx = backend.Data.Array(reccoeval_vx) - reccoeij_vz = backend.Data.Array(reccoeij_vz) - reccoeval_vz = backend.Data.Array(reccoeval_vz) + srccoeij_xx = [backend.Data.Array(srccoeij_xx[i]) for i in eachindex(srccoeij_xx)] + srccoeval_xx = [backend.Data.Array(srccoeval_xx[i]) for i in eachindex(srccoeval_xx)] + srccoeij_xz = [backend.Data.Array(srccoeij_xz[i]) for i in eachindex(srccoeij_xz)] + srccoeval_xz = [backend.Data.Array(srccoeval_xz[i]) for i in eachindex(srccoeval_xz)] + reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] + reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) @@ -185,14 +185,15 @@ end # Numerics nt = model.nt # Wrap sources and receivers arrays - srccoeij_vx = backend.Data.Array(srccoeij_vx) - srccoeval_vx = backend.Data.Array(srccoeval_vx) - srccoeij_vz = backend.Data.Array(srccoeij_vz) - srccoeval_vz = backend.Data.Array(srccoeval_vz) - reccoeij_vx = backend.Data.Array(reccoeij_vx) - reccoeval_vx = backend.Data.Array(reccoeval_vx) - reccoeij_vz = backend.Data.Array(reccoeij_vz) - reccoeval_vz = backend.Data.Array(reccoeval_vz) + srccoeij_vx = [backend.Data.Array(srccoeij_vx[i]) for i in eachindex(srccoeij_vx)] + srccoeval_vx = [backend.Data.Array(srccoeval_vx[i]) for i in eachindex(srccoeval_vx)] + srccoeij_vz = [backend.Data.Array(srccoeij_vz[i]) for i in eachindex(srccoeij_vz)] + srccoeval_vz = [backend.Data.Array(srccoeval_vz[i]) for i in eachindex(srccoeval_vz)] + reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] + reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] + srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index bf1839f..b7a4c26 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,45 +2,48 @@ # Functions for all ElasticIsoWaveSimulation subtypes -function spreadsrcrecinterp2D( - gridspacing::NTuple{N, T}, - gridsize::NTuple{N, Int}, - positions::Matrix{T}; - nptssinc::Int=4, xstart::T=0.0, zstart::T=0.0 -) where {T, N} - nloc = size(positions, 1) - Ndim = size(positions, 2) - @assert Ndim == 2 - @assert N == Ndim - - Δx = gridspacing[1] - Δz = gridspacing[2] - nx, nz = gridsize[1:2] - - maxnumcoeff = nloc * (2 * nptssinc + 1)^Ndim - coeij_tmp = zeros(Int, maxnumcoeff, Ndim + 1) - coeval_tmp = zeros(T, maxnumcoeff) - l = 0 - for p in 1:nloc - # extract x and z position for source or receiver p - xpos, zpos = positions[p, :] - # compute grid indices and values of sinc coefficients - xidx, zidx, xzcoeff = coeffsinc2D(xstart, zstart, Δx, Δz, xpos, zpos, - nx, nz, [:monopole, :monopole]; npts=nptssinc) - for j in eachindex(zidx) - for i in eachindex(xidx) - l += 1 - # id, i, j indices - coeij_tmp[l, :] .= (p, xidx[i], zidx[j]) - # coefficients value - coeval_tmp[l] = xzcoeff[i, j] - end +function modd_2D_grid(x0::T, y0::T, dx::T, dy::T, nx::Int, ny::Int, r::Int=4, β::Int=10, xstart::T=0, ystart::T=0) where {T} + xs = range(xstart, length=nx, step=dx) + ys = range(ystart, length=ny, step=dy) + dd_coeffs = Vector{Tuple{Int, Int, T}}() + + kaiser(x, r, β) = (-r <= x <= r ? besseli(0, β * sqrt(1 - (x / r)^2)) / besseli(0, β) : 0.0) + modd_(x, x0, r, β, Δx) = 1/Δx * kaiser(x - x0, r, β) * sinc((x - x0)/Δx) + modd(x, x0, r, β, Δx) = begin + res = modd_(x, x0, r * Δx, β, Δx) + return res ≈ 0 ? 0.0 : res + end + modd_2D(x, y, x0, y0, r, β, Δx, Δy) = modd(x, x0, r, β, Δx) * modd(y, y0, r, β, Δy) + findnearest(x, xs) = argmin(abs.(x .- xs)) + + i0 = findnearest(x0, xs) + j0 = findnearest(y0, ys) + for i in i0-r-1:i0+r+1, j in j0-r-1:j0+r+1 + if i < 1 || i > nx || j < 1 || j > ny + continue + end + ddij = modd_2D(xs[i], ys[j], x0, y0, r, β, dx, dy) + if ddij != 0.0 + push!(dd_coeffs, (i, j, ddij)) end end - # keep only the valid part of the arrays - coeij = coeij_tmp[1:l, :] - coeval = coeval_tmp[1:l] + return dd_coeffs +end + +function spread2D(spacing::NTuple{2, T}, size::NTuple{2, Int}, positions::Matrix{T}, npositions; r::Int=4, β::Int=10, xstart::T=0, zstart::T=0) where {T} + coeij = Vector{Matrix{Int}}(undef, npositions) + coeval = Vector{Vector{T}}(undef, npositions) + for p in 1:npositions + x0, y0 = positions[p, 1], positions[p, 2] + dd_coeffs = modd_2D_grid(x0, y0, spacing[1], spacing[2], size[1], size[2], r, β, xstart, zstart) + coeij[p] = zeros(Int, length(dd_coeffs), 2) + coeval[p] = zeros(T, length(dd_coeffs)) + for (idx, (i, j, val)) in enumerate(dd_coeffs) + coeij[p][idx, :] .= (i, j) + coeval[p][idx] = val + end + end return coeij, coeval end @@ -48,46 +51,28 @@ end @views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalForceShot{T, 2}; sincinterp=false) where {T} if sincinterp # interpolation coefficients for sources in vx - srccoeij_vx, srccoeval_vx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) + nsrcs = size(shot.srcs.positions, 1) + srccoeij_vx, srccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=0.0) # interpolation coefficients for sources in vz - srccoeij_vz, srccoeval_vz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + srccoeij_vz, srccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + nrecs = size(shot.recs.positions, 1) # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) + reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=0.0) # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) else src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) nsrcs = size(shot.srcs.positions, 1) nrecs = size(shot.recs.positions, 1) - srccoeij_vx = zeros(Int, nsrcs, 3) - srccoeval_vx = ones(T, nsrcs) - srccoeij_vz = zeros(Int, nsrcs, 3) - srccoeval_vz = ones(T, nsrcs) - reccoeij_vx = zeros(Int, nrecs, 3) - reccoeval_vx = ones(T, nrecs) - reccoeij_vz = zeros(Int, nrecs, 3) - reccoeval_vz = ones(T, nrecs) - for p in 1:nsrcs - srccoeij_vx[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) - srccoeij_vz[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) - end - for p in 1:nrecs - reccoeij_vx[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) - reccoeij_vz[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) - end - @show srccoeij_vx, srccoeval_vx - @show srccoeij_vz, srccoeval_vz - @show reccoeij_vx, reccoeval_vx - @show reccoeij_vz, reccoeval_vz + srccoeij_vx = [[src_idx_positions[s, 1] src_idx_positions[s, 2]] for s in 1:nsrcs] + srccoeval_vx = [ones(T, 1) for _ in 1:nsrcs] + srccoeij_vz = [[src_idx_positions[s, 1] src_idx_positions[s, 2]] for s in 1:nsrcs] + srccoeval_vz = [ones(T, 1) for _ in 1:nsrcs] + reccoeij_vx = [[rec_idx_positions[r, 1] rec_idx_positions[r, 2]] for r in 1:nrecs] + reccoeval_vx = [ones(T, 1) for _ in 1:nrecs] + reccoeij_vz = [[rec_idx_positions[r, 1] rec_idx_positions[r, 2]] for r in 1:nrecs] + reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end # scale source time function with boxcar and timestep size @@ -98,43 +83,29 @@ end @views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}; sincinterp=false) where {T} if sincinterp + nsrcs = size(shot.srcs.positions, 1) # interpolation coefficients for sources in σxx and σzz - srccoeij_xx, srccoeval_xx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=0.0) + srccoeij_xx, srccoeval_xx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=0.0) # interpolation coefficients for sources in σxz - srccoeij_xz, srccoeval_xz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.srcs.positions; - nptssinc=4, xstart=0.0, zstart=model.grid.spacing[2]/2) + srccoeij_xz, srccoeval_xz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=model.grid.spacing[2]/2) + nrecs = size(shot.recs.positions, 1) # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=0.0, zstart=0.0) + reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=0.0) # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spreadsrcrecinterp2D( - model.grid.spacing, model.grid.size, shot.recs.positions; - nptssinc=4, xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) else src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) nsrcs = size(shot.srcs.positions, 1) nrecs = size(shot.recs.positions, 1) - srccoeij_xx = zeros(Int, nsrcs, 3) - srccoeval_xx = ones(T, nsrcs) - srccoeij_xz = zeros(Int, nsrcs, 3) - srccoeval_xz = ones(T, nsrcs) - reccoeij_vx = zeros(Int, nrecs, 3) - reccoeval_vx = ones(T, nrecs) - reccoeij_vz = zeros(Int, nrecs, 3) - reccoeval_vz = ones(T, nrecs) - for p in 1:nsrcs - srccoeij_xx[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) - srccoeij_xz[p, :] .= (p, src_idx_positions[p, 1], src_idx_positions[p, 2]) - end - for p in 1:nrecs - reccoeij_vx[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) - reccoeij_vz[p, :] .= (p, rec_idx_positions[p, 1], rec_idx_positions[p, 2]) - end + srccoeij_xx = [[src_idx_positions[s, 1] src_idx_positions[s, 2]] for s in 1:nsrcs] + srccoeval_xx = [ones(T, 1) for _ in 1:nsrcs] + srccoeij_xz = [[src_idx_positions[s, 1] src_idx_positions[s, 2]] for s in 1:nsrcs] + srccoeval_xz = [ones(T, 1) for _ in 1:nsrcs] + reccoeij_vx = [[rec_idx_positions[r, 1] rec_idx_positions[r, 2]] for r in 1:nrecs] + reccoeval_vx = [ones(T, 1) for _ in 1:nrecs] + reccoeij_vz = [[rec_idx_positions[r, 1] rec_idx_positions[r, 2]] for r in 1:nrecs] + reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end # scale source time function with boxcar and timestep size @@ -261,7 +232,7 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac snapevery::Union{Int, Nothing}=nothing, infoevery::Union{Int, Nothing}=nothing, smooth_radius::Int=5, - sincinterp::Bool=false + sincinterp::Bool=true ) where {T, N} # Extract params nt = params.ntimesteps From ac8359bf71ea2a3b356ed3f578941a0936ca4cf3 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 22 Oct 2024 09:47:40 +0200 Subject: [PATCH 080/111] Move things in utils --- src/models/elastic/ela_models.jl | 49 ++------------------------------ src/utils/utils.jl | 45 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index b7a4c26..9cf69b5 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -2,51 +2,6 @@ # Functions for all ElasticIsoWaveSimulation subtypes -function modd_2D_grid(x0::T, y0::T, dx::T, dy::T, nx::Int, ny::Int, r::Int=4, β::Int=10, xstart::T=0, ystart::T=0) where {T} - xs = range(xstart, length=nx, step=dx) - ys = range(ystart, length=ny, step=dy) - dd_coeffs = Vector{Tuple{Int, Int, T}}() - - kaiser(x, r, β) = (-r <= x <= r ? besseli(0, β * sqrt(1 - (x / r)^2)) / besseli(0, β) : 0.0) - modd_(x, x0, r, β, Δx) = 1/Δx * kaiser(x - x0, r, β) * sinc((x - x0)/Δx) - modd(x, x0, r, β, Δx) = begin - res = modd_(x, x0, r * Δx, β, Δx) - return res ≈ 0 ? 0.0 : res - end - modd_2D(x, y, x0, y0, r, β, Δx, Δy) = modd(x, x0, r, β, Δx) * modd(y, y0, r, β, Δy) - findnearest(x, xs) = argmin(abs.(x .- xs)) - - i0 = findnearest(x0, xs) - j0 = findnearest(y0, ys) - for i in i0-r-1:i0+r+1, j in j0-r-1:j0+r+1 - if i < 1 || i > nx || j < 1 || j > ny - continue - end - ddij = modd_2D(xs[i], ys[j], x0, y0, r, β, dx, dy) - if ddij != 0.0 - push!(dd_coeffs, (i, j, ddij)) - end - end - - return dd_coeffs -end - -function spread2D(spacing::NTuple{2, T}, size::NTuple{2, Int}, positions::Matrix{T}, npositions; r::Int=4, β::Int=10, xstart::T=0, zstart::T=0) where {T} - coeij = Vector{Matrix{Int}}(undef, npositions) - coeval = Vector{Vector{T}}(undef, npositions) - for p in 1:npositions - x0, y0 = positions[p, 1], positions[p, 2] - dd_coeffs = modd_2D_grid(x0, y0, spacing[1], spacing[2], size[1], size[2], r, β, xstart, zstart) - coeij[p] = zeros(Int, length(dd_coeffs), 2) - coeval[p] = zeros(T, length(dd_coeffs)) - for (idx, (i, j, val)) in enumerate(dd_coeffs) - coeij[p][idx, :] .= (i, j) - coeval[p][idx] = val - end - end - return coeij, coeval -end - # Scaling for ElasticIsoWaveSimulation @views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalForceShot{T, 2}; sincinterp=false) where {T} if sincinterp @@ -75,7 +30,7 @@ end reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end - # scale source time function with boxcar and timestep size + # scale source time function with timestep size scal_srctf = shot.srcs.tf .* model.dt return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf @@ -108,7 +63,7 @@ end reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end - # scale source time function with boxcar and timestep size + # scale source time function with timestep size scal_srctf = shot.srcs.tf .* model.dt return srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf diff --git a/src/utils/utils.jl b/src/utils/utils.jl index 47b9d5b..91adac6 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -230,6 +230,51 @@ function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter:: return xidx, zidx, xzcoeff end +function modd_2D_grid(x0::T, y0::T, dx::T, dy::T, nx::Int, ny::Int, r::Int=4, β::Int=10, xstart::T=0, ystart::T=0) where {T} + xs = range(xstart, length=nx, step=dx) + ys = range(ystart, length=ny, step=dy) + dd_coeffs = Vector{Tuple{Int, Int, T}}() + + kaiser(x, r, β) = (-r <= x <= r ? besseli(0, β * sqrt(1 - (x / r)^2)) / besseli(0, β) : 0.0) + modd_(x, x0, r, β, Δx) = 1/Δx * kaiser(x - x0, r, β) * sinc((x - x0)/Δx) + modd(x, x0, r, β, Δx) = begin + res = modd_(x, x0, r * Δx, β, Δx) + return res ≈ 0 ? 0.0 : res + end + modd_2D(x, y, x0, y0, r, β, Δx, Δy) = modd(x, x0, r, β, Δx) * modd(y, y0, r, β, Δy) + findnearest(x, xs) = argmin(abs.(x .- xs)) + + i0 = findnearest(x0, xs) + j0 = findnearest(y0, ys) + for i in i0-r-1:i0+r+1, j in j0-r-1:j0+r+1 + if i < 1 || i > nx || j < 1 || j > ny + continue + end + ddij = modd_2D(xs[i], ys[j], x0, y0, r, β, dx, dy) + if ddij != 0.0 + push!(dd_coeffs, (i, j, ddij)) + end + end + + return dd_coeffs +end + +function spread2D(spacing::NTuple{2, T}, size::NTuple{2, Int}, positions::Matrix{T}, npositions; r::Int=4, β::Int=10, xstart::T=0, zstart::T=0) where {T} + coeij = Vector{Matrix{Int}}(undef, npositions) + coeval = Vector{Vector{T}}(undef, npositions) + for p in 1:npositions + x0, y0 = positions[p, 1], positions[p, 2] + dd_coeffs = modd_2D_grid(x0, y0, spacing[1], spacing[2], size[1], size[2], r, β, xstart, zstart) + coeij[p] = zeros(Int, length(dd_coeffs), 2) + coeval[p] = zeros(T, length(dd_coeffs)) + for (idx, (i, j, val)) in enumerate(dd_coeffs) + coeij[p][idx, :] .= (i, j) + coeval[p][idx] = val + end + end + return coeij, coeval +end + ##################################################################### ##################################################################### From e0d458caa250e6caf2aa9bbee741d2e71512186d Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 22 Oct 2024 15:42:14 +0200 Subject: [PATCH 081/111] Replace elastic backend (WIP) --- src/models/cpmlcoeffs.jl | 98 +--- .../backends/shared/elastic2D_iso_xPU.jl | 514 ++++++++---------- src/models/elastic/ela_forward.jl | 4 +- src/models/elastic/ela_models.jl | 161 +++--- src/utils/snapshotter.jl | 2 +- 5 files changed, 345 insertions(+), 434 deletions(-) diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index b60c347..2df310a 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -5,22 +5,13 @@ struct CPMLCoefficientsAxis{T, V <: AbstractVector{T}} b::V b_h::V - function CPMLCoefficientsAxis{T, V}(halo::Int, backend::Module, sizehalfgrdplusone::Bool=false) where {T, V <: AbstractVector{T}} - if sizehalfgrdplusone - return new{T, V}( - backend.zeros(T, 2 * halo), - backend.zeros(T, 2 * (halo + 1) + 1), - backend.zeros(T, 2 * halo), - backend.zeros(T, 2 * (halo + 1) + 1) - ) - else - return new{T, V}( - backend.zeros(T, 2 * halo), - backend.zeros(T, 2 * (halo + 1)), - backend.zeros(T, 2 * halo), - backend.zeros(T, 2 * (halo + 1)) - ) - end + function CPMLCoefficientsAxis{T, V}(halo::Int, backend::Module) where {T, V <: AbstractVector{T}} + return new{T, V}( + backend.zeros(T, 2 * halo), + backend.zeros(T, 2 * (halo + 1)), + backend.zeros(T, 2 * halo), + backend.zeros(T, 2 * (halo + 1)) + ) end end @@ -34,11 +25,14 @@ function compute_CPML_coefficientsAxis!( f0::T ) where {T, V <: AbstractVector{T}} # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) - alpha_max = convert(T, π * f0) # CPML α multiplicative factor (half of dominating angular frequency) - npower = convert(T, 2.0) # CPML power coefficient - d0 = convert(T, -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness)) # damping profile - a_l, a_r, b_l, b_r = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :startongrd) - a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML_staggeredgrid(halo, dt, npower, d0, alpha_max, :starthalfgrd) + alpha_max = convert(T, π * f0) # CPML α multiplicative factor (half of dominating angular frequency) + npower = convert(T, 2.0) # CPML power coefficient + d0 = convert(T, -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness)) # damping profile + if halo == 0 # fix for thickness == 0 generating NaNs + d0 = convert(T, 0.0) + end + a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") + a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") copyto!(cpmlcoeffs.a, vcat(a_l, a_r)) copyto!(cpmlcoeffs.a_h, vcat(a_hl, a_hr)) @@ -85,68 +79,6 @@ struct CPMLCoefficients{T, V <: AbstractVector{T}} end end -function calc_Kab_CPML_staggeredgrid( - halo::Int, - dt::T, - npower::T, - d0::T, - alpha_max_pml::T, - onwhere::Symbol; - K_max_pml::Union{T, Nothing}=nothing -)::Tuple{Array{T}, Array{T}, Array{T}, Array{T}} where {T} - @assert halo >= 0.0 - - Kab_size = halo - # shift for half grid coefficients - if onwhere == :starthalfgrd - shift_left = 0.0 - shift_right = 0.5 - elseif onwhere == :startongrd - shift_left = 0.5 - shift_right = 0.0 - else - error("Wrong onwhere parameter!") - end - - # distance from edge node - dist_left = collect(LinRange(shift_left, Kab_size + shift_left - 1, Kab_size)) - dist_right = collect(LinRange(shift_right, Kab_size + shift_right - 1, Kab_size)) - - if halo != 0 - normdist_left = reverse(dist_left) ./ (halo - 0.5) - normdist_right = dist_right ./ (halo - 0.5) - else - normdist_left = reverse(dist_left) - normdist_right = dist_right - end - - if K_max_pml === nothing - K_left = 1.0 - else - K_left = 1.0 .+ (K_max_pml - 1.0) .* (normdist_left .^ npower) - end - d_left = d0 .* (normdist_left .^ npower) - alpha_left = alpha_max_pml .* (1.0 .- normdist_left) - b_left = exp.(.-(d_left ./ K_left .+ alpha_left) .* dt) - a_left = d_left .* (b_left .- 1.0) ./ (K_left .* (d_left .+ K_left .* alpha_left)) - - if K_max_pml === nothing - K_right = 1.0 - else - K_right = 1.0 .+ (K_max_pml - 1.0) .* (normdist_right .^ npower) - end - d_right = d0 .* (normdist_right .^ npower) - alpha_right = alpha_max_pml .* (1.0 .- normdist_right) - b_right = exp.(.-(d_right ./ K_right .+ alpha_right) .* dt) - a_right = d_right .* (b_right .- 1.0) ./ (K_right .* (d_right .+ K_right .* alpha_right)) - - if K_max_pml === nothing - return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right) - else - return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right), convert.(T, K_left), convert.(T, K_right) - end -end - ##################################### function compute_CPML_coefficients!( diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 2cfe8c6..5979935 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -1,49 +1,51 @@ -@parallel_indices (i, j) function update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x, b_z, a_x, a_z, freetop) - if freetop && j <= 2 - # σxx derivative only in x so no problem - ∂σxx∂x_bkw = factx * (σxx[i-2, j] - 27.0 * σxx[i-1, j] + 27.0 * σxx[i, j] - σxx[i+1, j]) - # image, mirroring σxz[i,j-2] = -σxz[i,j+1], etc. - #∂σxz∂z_bkw = factz * ( -σxz[i,j+1] +27.0*σxz[i,j] +27.0*σxz[i,j] -σxz[i,j+1] ) - if j == 1 - # j bwd-> -2 -1|0 1 (mirror -2 and -1) - ∂σxz∂z_bkw = factz * (-σxz[i, j+1] + 27.0 * σxz[i, j] + 27.0 * σxz[i, j] - σxz[i, j+1]) - elseif j == 2 - # j bwd-> -2|-1 0 1 (mirror only -2) - ∂σxz∂z_bkw = factz * (-σxz[i, j] - 27.0 * σxz[i, j-1] + 27.0 * σxz[i, j] - σxz[i, j+1]) - end - # update velocity - vx[i, j] = vx[i, j] + (dt / ρ[i, j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) +@parallel_indices (i, j) function update_4thord_vx!( + nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, + ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) + if freetop && j == 1 + # on the free surface + ∂σxx∂x = (-σxx[i+2, j] + 27 * σxx[i+1, j] - 27 * σxx[i, j] + σxx[i-1, j]) * factx + # mirroring stresses at the top boundary + σxz_top = -σxz[i, j] + σxz_toptop = -σxz[i, j+1] + ∂σxz∂z = (-σxz[i, j+1] + 27 * σxz[i, j] - 27 * σxz_top + σxz_toptop) * factz + elseif freetop && j == 2 + # just below the free surface + ∂σxx∂x = (-σxx[i+2, j] + 27 * σxx[i+1, j] - 27 * σxx[i, j] + σxx[i-1, j]) * factx + # mirroring stress at the top boundary + σxz_top = -σxz[i, j+1] + ∂σxz∂z = (-σxz[i, j+1] + 27 * σxz[i, j] - 27 * σxz[i, j-1] + σxz_top) * factz + elseif j >= 3 + ∂σxx∂x = (-σxx[i+2, j] + 27 * σxx[i+1, j] - 27 * σxx[i, j ] + σxx[i-1, j]) * factx + ∂σxz∂z = (-σxz[i, j+1] + 27 * σxz[i, j ] - 27 * σxz[i, j-1] + σxz[i, j-2]) * factz + else + ∂σxx∂x = 0.0 + ∂σxz∂z = 0.0 end - if j >= 3 - ∂σxx∂x_bkw = factx * (σxx[i-2, j] - 27.0 * σxx[i-1, j] + 27.0 * σxx[i, j] - σxx[i+1, j]) - ∂σxz∂z_bkw = factz * (σxz[i, j-2] - 27.0 * σxz[i, j-1] + 27.0 * σxz[i, j] - σxz[i, j+1]) - - if i <= halo # - # left boundary - ψ_∂σxx∂x[i, j] = b_x[i] * ψ_∂σxx∂x[i, j] + a_x[i] * ∂σxx∂x_bkw - ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[i, j] - elseif i >= nx - halo + 1 - # right boundary - ii = i - (nx - 2 * halo) - ψ_∂σxx∂x[ii, j] = b_x[ii] * ψ_∂σxx∂x[ii, j] + a_x[ii] * ∂σxx∂x_bkw - ∂σxx∂x_bkw = ∂σxx∂x_bkw + ψ_∂σxx∂x[ii, j] - end - # y boundaries - if j <= halo && freetop == false - # top boundary - ψ_∂σxz∂z[i, j] = b_z[j] * ψ_∂σxz∂z[i, j] + a_z[j] * ∂σxz∂z_bkw - ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i, j] - elseif j >= nz - halo + 1 - # bottom boundary - jj = j - (nz - 2 * halo) - ψ_∂σxz∂z[i, jj] = b_z[jj] * ψ_∂σxz∂z[i, jj] + a_z[jj] * ∂σxz∂z_bkw - ∂σxz∂z_bkw = ∂σxz∂z_bkw + ψ_∂σxz∂z[i, jj] - end - - # update velocity - vx[i, j] = vx[i, j] + (dt / ρ[i, j]) * (∂σxx∂x_bkw + ∂σxz∂z_bkw) + ### CPML ### + if i <= halo + 1 + # left boundary + ψ_∂σxx∂x[i, j] = b_x_half[i] * ψ_∂σxx∂x[i, j] + a_x_half[i] * ∂σxx∂x + ∂σxx∂x += ψ_∂σxx∂x[i, j] + elseif i >= nx - halo - 1 + # right boundary + ii = i - (nx - halo - 1) + 1 + (halo + 1) + ψ_∂σxx∂x[ii, j] = b_x_half[ii] * ψ_∂σxx∂x[ii, j] + a_x_half[ii] * ∂σxx∂x + ∂σxx∂x += ψ_∂σxx∂x[ii, j] + end + if j >= 2 && j <= halo + 1 && freetop == false + # top boundary + ψ_∂σxz∂z[i, j-1] = b_z[j-1] * ψ_∂σxz∂z[i, j-1] + a_z[j-1] * ∂σxz∂z + ∂σxz∂z += ψ_∂σxz∂z[i, j-1] + elseif j >= nz - halo + # bottom boundary + jj = j - (nz - halo) + 2 + (halo) + ψ_∂σxz∂z[i, jj-1] = b_z[jj-1] * ψ_∂σxz∂z[i, jj-1] + a_z[jj-1] * ∂σxz∂z + ∂σxz∂z += ψ_∂σxz∂z[i, jj-1] end + ############ + + vx[i, j] += dt * (∂σxx∂x + ∂σxz∂z) / ρ_ihalf[i, j] return nothing end @@ -58,231 +60,178 @@ end σxz, σzz, dt, - ρ_ihalf_jhalf, + ρ_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, - b_x_half, + b_x, b_z_half, - a_x_half, + a_x, a_z_half, - freetop -) - if freetop && j <= 2 - # σxz derivative only in x so no problem - ∂σxz∂x_fwd = factx * (σxz[i-1, j] - 27.0 * σxz[i, j] + 27.0 * σxz[i+1, j] - σxz[i+2, j]) - # image, mirroring σzz[i,j-1] = -σxz[i,j+2], etc. - #∂σzz∂z_fwd = factz * ( -σzz[i,j+2] +27.0*σzz[i,j+1] +27.0*σzz[i,j+1] -σzz[i,j+2] ) - if j == 1 - # j fwd-> -1 0| 1 2 (mirror -2 and -1) - ∂σzz∂z_fwd = factz * (-σzz[i, j+2] + 27.0 * σzz[i, j+1] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) - elseif j == 2 - # j fwd-> -1|0 1 2 (mirror only -1) - ∂σzz∂z_fwd = factz * (-σzz[i, j+2] - 27.0 * σzz[i, j] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) - end - # update velocity (ρ has been interpolated in advance) - vz[i, j] = vz[i, j] + (dt / ρ_ihalf_jhalf[i, j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) + freetop) + if freetop && j == 1 + # just half step below the free surface + # mirroring stress at the top boundary + σzz_top = -σzz[i, j+2] + ∂σzz∂z = (-σzz[i, j+2] + 27 * σzz[i, j+1] - 27 * σzz[i, j] + σzz_top) * factz + ∂σxz∂x = (-σxz[i+1, j] + 27 * σxz[i, j] - 27 * σxz[i-1, j] + σxz[i-2, j]) * factx + elseif j >= 2 + ∂σzz∂z = (-σzz[i, j+2] + 27 * σzz[i, j+1] - 27 * σzz[i, j] + σzz[i, j-1]) * factz + ∂σxz∂x = (-σxz[i+1, j] + 27 * σxz[i, j] - 27 * σxz[i-1, j] + σxz[i-2, j]) * factx + else + ∂σzz∂z = 0.0 + ∂σxz∂x = 0.0 end - # vz - if j >= 3 - # Vz - ∂σxz∂x_fwd = factx * (σxz[i-1, j] - 27.0 * σxz[i, j] + 27.0 * σxz[i+1, j] - σxz[i+2, j]) - ∂σzz∂z_fwd = factz * (σzz[i, j-1] - 27.0 * σzz[i, j] + 27.0 * σzz[i, j+1] - σzz[i, j+2]) - - ##======================= - # C-PML stuff - ##======================= - # x boundaries - if i <= halo - # left boundary - ψ_∂σxz∂x[i, j] = b_x_half[i] * ψ_∂σxz∂x[i, j] + a_x_half[i] * ∂σxz∂x_fwd - ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[i, j] - elseif i >= nx - halo + 1 - # right boundary - ii = i - (nx - 2 * halo) - ψ_∂σxz∂x[ii, j] = b_x_half[ii] * ψ_∂σxz∂x[ii, j] + a_x_half[ii] * ∂σxz∂x_fwd - ∂σxz∂x_fwd = ∂σxz∂x_fwd + ψ_∂σxz∂x[ii, j] - end - # y boundaries - if j <= halo && freetop == false # + 1 - # top boundary - ψ_∂σzz∂z[i, j] = b_z_half[j] * ψ_∂σzz∂z[i, j] + a_z_half[j] * ∂σzz∂z_fwd - ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i, j] - elseif j >= nz - halo + 1 - # bottom boundary - jj = j - (nz - 2 * halo) - ψ_∂σzz∂z[i, jj] = b_z_half[jj] * ψ_∂σzz∂z[i, jj] + a_z_half[jj] * ∂σzz∂z_fwd - ∂σzz∂z_fwd = ∂σzz∂z_fwd + ψ_∂σzz∂z[i, jj] - end - ##======================= - - # update velocity (ρ has been interpolated in advance) - vz[i, j] = vz[i, j] + (dt / ρ_ihalf_jhalf[i, j]) * (∂σxz∂x_fwd + ∂σzz∂z_fwd) + ### CPML ### + if i <= halo + 1 + # left boundary + ψ_∂σxz∂x[i-1, j] = b_x[i-1] * ψ_∂σxz∂x[i-1, j] + a_x[i-1] * ∂σxz∂x + ∂σxz∂x += ψ_∂σxz∂x[i-1, j] + elseif i >= nx - halo + # right boundary + ii = i - (nx - halo) + 2 + (halo) + ψ_∂σxz∂x[ii-1, j] = b_x[ii-1] * ψ_∂σxz∂x[ii-1, j] + a_x[ii-1] * ∂σxz∂x + ∂σxz∂x += ψ_∂σxz∂x[ii-1, j] + end + if j <= halo + 1 && freetop == false + # top boundary + ψ_∂σzz∂z[i, j] = b_z_half[j] * ψ_∂σzz∂z[i, j] + a_z_half[j] * ∂σzz∂z + ∂σzz∂z += ψ_∂σzz∂z[i, j] + elseif j >= nz - halo + # bottom boundary + jj = j - (nz - halo) + 2 + (halo + 1) + ψ_∂σzz∂z[i, jj] = b_z_half[jj] * ψ_∂σzz∂z[i, jj] + a_z_half[jj] * ∂σzz∂z + ∂σzz∂z += ψ_∂σzz∂z[i, jj] end + ############ + + vz[i, j] += dt * (∂σzz∂z + ∂σxz∂x) / ρ_jhalf[i, j] return nothing end -@parallel_indices (i, j) function update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, - vx, vz, dt, λ_ihalf, μ_ihalf, ψ_∂vx∂x, ψ_∂vz∂z, - b_x_half, b_z, a_x_half, a_z, freetop) - if freetop == true - # σxx, σzz - # j=1: we are on the free surface! - if j == 1 - # σxx - # vx derivative only in x so no problem - ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) - # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd - ∂vz∂z_bkd = -(λ_ihalf[i, j] / (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j])) * ∂vx∂x_fwd - # σxx - σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + - λ_ihalf[i, j] * dt * ∂vz∂z_bkd - # σzz - σzz[i, j] = 0.0 # we are on the free surface! - end - - # j=2: we are just below the surface (1/2) - if j == 2 - # σxx - # vx derivative only in x so no problem - ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) - # zero velocity above the free surface - ∂vz∂z_bkd = factz * (0.0 - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) - # σxx - σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + - λ_ihalf[i, j] * dt * ∂vz∂z_bkd - # σzz - σzz[i, j] = σzz[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vz∂z_bkd + - λ_ihalf[i, j] * dt * ∂vx∂x_fwd - end - end - - # σxx, σzz - if j >= 3 - # σxx,σzz - ∂vx∂x_fwd = factx * (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) - ∂vz∂z_bkd = factz * (vz[i, j-2] - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) - - ##======================= - # C-PML stuff - ##======================= - # x boundaries - if i <= halo +@parallel_indices (i, j) function update_4thord_σxxσzz!( + nx, nz, halo, σxx, σzz, factx, factz, + vx, vz, dt, λ, μ, ψ_∂vx∂x, ψ_∂vz∂z, + b_x, b_z, a_x, a_z, freetop) + if freetop && j == 1 + # on the free surface, σzz = 0 + ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx + # using boundary condition to calculate ∂vz∂z + ∂vz∂z = -(λ[i, j] / (λ[i, j] + 2*μ[i, j])) * ∂vx∂x + # update stresses + σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) + σzz[i, j] = 0.0 + elseif freetop && j == 2 + # just below the free surface + ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx + # zero velocity above the free surface + ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + 0.0) * factz + # update stresses + σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) + σzz[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vz∂z + λ[i, j] * ∂vx∂x) + elseif j >= 3 + ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx + ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + vz[i, j-2]) * factz + + ### CPML ### + if i <= halo + 1 # left boundary - ψ_∂vx∂x[i, j] = b_x_half[i] * ψ_∂vx∂x[i, j] + a_x_half[i] * ∂vx∂x_fwd - ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[i, j] - elseif i >= nx - halo + 1 + ψ_∂vx∂x[i-1, j] = b_x[i-1] * ψ_∂vx∂x[i-1, j] + a_x[i-1] * ∂vx∂x + ∂vx∂x += ψ_∂vx∂x[i-1, j] + elseif i >= nx - halo # right boundary - ii = i - (nx - 2 * halo) - ψ_∂vx∂x[ii, j] = b_x_half[ii] * ψ_∂vx∂x[ii, j] + a_x_half[ii] * ∂vx∂x_fwd - ∂vx∂x_fwd = ∂vx∂x_fwd + ψ_∂vx∂x[ii, j] + ii = i - (nx - halo) + 2 + (halo) + ψ_∂vx∂x[ii-1, j] = b_x[ii-1] * ψ_∂vx∂x[ii-1, j] + a_x[ii-1] * ∂vx∂x + ∂vx∂x += ψ_∂vx∂x[ii-1, j] end - # y boundaries - if j <= halo && freetop == false + if j <= halo + 1 && freetop == false # top boundary - ψ_∂vz∂z[i, j] = b_z[j] * ψ_∂vz∂z[i, j] + a_z[j] * ∂vz∂z_bkd - ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i, j] - elseif j >= nz - halo + 1 + ψ_∂vz∂z[i, j-1] = b_z[j-1] * ψ_∂vz∂z[i, j-1] + a_z[j-1] * ∂vz∂z + ∂vz∂z += ψ_∂vz∂z[i, j-1] + elseif j >= nz - halo # bottom boundary - jj = j - (nz - 2 * halo) - ψ_∂vz∂z[i, jj] = b_z[jj] * ψ_∂vz∂z[i, jj] + a_z[jj] * ∂vz∂z_bkd - ∂vz∂z_bkd = ∂vz∂z_bkd + ψ_∂vz∂z[i, jj] + jj = j - (nz - halo) + 2 + (halo) + ψ_∂vz∂z[i, jj-1] = b_z[jj-1] * ψ_∂vz∂z[i, jj-1] + a_z[jj-1] * ∂vz∂z + ∂vz∂z += ψ_∂vz∂z[i, jj-1] end - ##======================= - # σxx - σxx[i, j] = σxx[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vx∂x_fwd + - λ_ihalf[i, j] * dt * ∂vz∂z_bkd - - ## derivatives are the same than for σxx - # σzz - σzz[i, j] = σzz[i, j] + (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j]) * dt * ∂vz∂z_bkd + - λ_ihalf[i, j] * dt * ∂vx∂x_fwd + ############ + + # update stresses + σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) + σzz[i, j] += dt * ( λ[i, j] * ∂vx∂x + (λ[i, j] + 2*μ[i, j]) * ∂vz∂z) end return nothing end -@parallel_indices (i, j) function update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, - μ_jhalf, b_x, b_z_half, - ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, - freetop) - if freetop - # σxz - if j == 1 - # zero velocity above the free surface - ∂vx∂z_fwd = factz * (0.0 - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) - # vz derivative only in x so no problem - ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) - # σxz - σxz[i, j] = σxz[i, j] + μ_jhalf[i, j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) - end +@parallel_indices (i, j) function update_4thord_σxz!( + nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, + ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + if freetop && j == 1 + # zero velocity above the free surface + ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + 0.0 ) * factz + ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx + elseif j >= 2 + ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + vx[i, j-1]) * factz + ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx + else + ∂vx∂z = 0.0 + ∂vz∂x = 0.0 end - # σxz - if j >= 2 - # σxz - ∂vx∂z_fwd = factz * (vx[i, j-1] - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) - ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) - - ##======================= - # C-PML stuff - ##======================= - # x boundaries - if i <= halo - # left boundary - ψ_∂vz∂x[i, j] = b_x[i] * ψ_∂vz∂x[i, j] + a_x[i] * ∂vz∂x_bkd - ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[i, j] - elseif i >= nx - halo + 1 - # right boundary - ii = i - (nx - 2 * halo) - ψ_∂vz∂x[ii, j] = b_x[ii] * ψ_∂vz∂x[ii, j] + a_x[ii] * ∂vz∂x_bkd - ∂vz∂x_bkd = ∂vz∂x_bkd + ψ_∂vz∂x[ii, j] - end - # y boundaries - if j <= halo && freetop == false - # top boundary - ψ_∂vx∂z[i, j] = b_z_half[j] * ψ_∂vx∂z[i, j] + a_z_half[j] * ∂vx∂z_fwd - ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i, j] - elseif j >= nz - halo + 1 - # bottom boundary - jj = j - (nz - 2 * halo) - ψ_∂vx∂z[i, jj] = b_z_half[jj] * ψ_∂vx∂z[i, jj] + a_z_half[jj] * ∂vx∂z_fwd - ∂vx∂z_fwd = ∂vx∂z_fwd + ψ_∂vx∂z[i, jj] - end - ##======================= - - # σxz - σxz[i, j] = σxz[i, j] + μ_jhalf[i, j] * dt * (∂vx∂z_fwd + ∂vz∂x_bkd) + ### CPML ### + if i <= halo + 1 + # left boundary + ψ_∂vz∂x[i, j] = b_x_half[i] * ψ_∂vz∂x[i, j] + a_x_half[i] * ∂vz∂x + ∂vz∂x += ψ_∂vz∂x[i, j] + elseif i >= nx - halo - 1 + # right boundary + ii = i - (nx - halo - 1) + 1 + (halo + 1) + ψ_∂vz∂x[ii, j] = b_x_half[ii] * ψ_∂vz∂x[ii, j] + a_x_half[ii] * ∂vz∂x + ∂vz∂x += ψ_∂vz∂x[ii, j] + end + if j <= halo + 1 && freetop == false + # top boundary + ψ_∂vx∂z[i, j] = b_z_half[j] * ψ_∂vx∂z[i, j] + a_z_half[j] * ∂vx∂z + ∂vx∂z += ψ_∂vx∂z[i, j] + elseif j >= nz - halo - 1 + # bottom boundary + jj = j - (nz - halo - 1) + 1 + (halo + 1) + ψ_∂vx∂z[i, jj] = b_z_half[jj] * ψ_∂vx∂z[i, jj] + a_z_half[jj] * ∂vx∂z + ∂vx∂z += ψ_∂vx∂z[i, jj] end + ############ + + σxz[i, j] += dt * μ_ihalf_jhalf[i, j] * (∂vx∂z + ∂vz∂x) return nothing end -@parallel_indices (p) function inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx, Mzz, srctf_bk, srccoeij_bk, srccoeval_bk, it, s) +@parallel_indices (p) function inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx, Mzz, srctf_bk, srccoeij_bk, srccoeval_bk, it, s, dt) isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] - σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it, s] - σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it, s] + σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it, s] * dt + σzz[isrc, jsrc] += Mzz[s] * srccoeval_bk[p] * srctf_bk[it, s] * dt return nothing end -@parallel_indices (p) function inject_momten_sources2D_σxz!(σxz, Mxz, srctf_bk, srccoeij_bk, srccoeval_bk, it, s) +@parallel_indices (p) function inject_momten_sources2D_σxz!(σxz, Mxz, srctf_bk, srccoeij_bk, srccoeval_bk, it, s, dt) isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] - σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it, s] + σxz[isrc, jsrc] += Mxz[s] * srccoeval_bk[p] * srctf_bk[it, s] * dt return nothing end -@parallel_indices (p) function inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_bk, srccoeval_bk, ρ, it, s) +@parallel_indices (p) function inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_bk, srccoeval_bk, ρ_ihalf, it, s, dt) isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] - vx[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 1, s] / ρ[isrc, jsrc] + vx[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 1, s] / ρ_ihalf[isrc, jsrc] * dt return nothing end -@parallel_indices (p) function inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_bk, srccoeval_bk, ρ_ihalf_jhalf, it, s) +@parallel_indices (p) function inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_bk, srccoeval_bk, ρ_jhalf, it, s, dt) isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] - vz[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 2, s] / ρ_ihalf_jhalf[isrc, jsrc] + vz[isrc, jsrc] += srccoeval_bk[p] * srctf_bk[it, 2, s] / ρ_jhalf[isrc, jsrc] * dt return nothing end @@ -344,22 +293,22 @@ function forward_onestep_CPML!( b_z = cpmlcoeffs[2].b b_z_half = cpmlcoeffs[2].b_h - ρ = grid.fields["ρ"].value - ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value - λ_ihalf = grid.fields["λ_ihalf"].value - μ_ihalf = grid.fields["μ_ihalf"].value - μ_jhalf = grid.fields["μ_jhalf"].value + λ = grid.fields["λ"].value + μ = grid.fields["μ"].value + ρ_ihalf = grid.fields["ρ_ihalf"].value + ρ_jhalf = grid.fields["ρ_jhalf"].value + μ_ihalf_jhalf = grid.fields["μ_ihalf_jhalf"].value # Precomputing divisions factx = 1.0 / (24.0 * dx) factz = 1.0 / (24.0 * dz) - # update velocity vx - @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, - b_x, b_z, a_x, a_z, freetop) + # update velocity vx + @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, + ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) # update velocity vz - @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, - ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, + ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) # record receivers if save_trace @@ -376,25 +325,22 @@ function forward_onestep_CPML!( end # update stresses σxx and σzz - @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, - vx, vz, dt, λ_ihalf, μ_ihalf, - ψ_∂vx∂x, ψ_∂vz∂z, - b_x_half, b_z, a_x_half, a_z, freetop) + @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ, μ, + ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) # update stress σxz - @parallel (3:nx-1, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, - μ_jhalf, b_x, b_z_half, - ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, + ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # inject sources (moment tensor type of internal force) nrecs_xx = size(srccoeij_xx, 1) nrecs_xz = size(srccoeij_xz, 1) for s in 1:nrecs_xx nsrcpts_xx = size(srccoeij_xx[s], 1) - @parallel (1:nsrcpts_xx) inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx_bk, Mzz_bk, srctf_bk, srccoeij_xx[s], srccoeval_xx[s], it, s) + @parallel (1:nsrcpts_xx) inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx_bk, Mzz_bk, srctf_bk, srccoeij_xx[s], srccoeval_xx[s], it, s, dt) end for s in 1:nrecs_xz nsrcpts_xz = size(srccoeij_xz[s], 1) - @parallel (1:nsrcpts_xz) inject_momten_sources2D_σxz!(σxz, Mxz_bk, srctf_bk, srccoeij_xz[s], srccoeval_xz[s], it, s) + @parallel (1:nsrcpts_xz) inject_momten_sources2D_σxz!(σxz, Mxz_bk, srctf_bk, srccoeij_xz[s], srccoeval_xz[s], it, s, dt) end return @@ -443,33 +389,33 @@ function forward_onestep_CPML!( b_z = cpmlcoeffs[2].b b_z_half = cpmlcoeffs[2].b_h - ρ = grid.fields["ρ"].value - ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value - λ_ihalf = grid.fields["λ_ihalf"].value - μ_ihalf = grid.fields["μ_ihalf"].value - μ_jhalf = grid.fields["μ_jhalf"].value + λ = grid.fields["λ"].value + μ = grid.fields["μ"].value + ρ_ihalf = grid.fields["ρ_ihalf"].value + ρ_jhalf = grid.fields["ρ_jhalf"].value + μ_ihalf_jhalf = grid.fields["μ_ihalf_jhalf"].value # Precomputing divisions factx = 1.0 / (24.0 * dx) factz = 1.0 / (24.0 * dz) - # update velocity vx - @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, - b_x, b_z, a_x, a_z, freetop) + # update velocity vx + @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, + ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) # update velocity vz - @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, - ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, + ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) - # inject sources (residuals as velocities) + # inject sources nsrcs_vx = size(srccoeij_vx, 1) nsrcs_vz = size(srccoeij_vz, 1) for s in 1:nsrcs_vx nsrcpts_vx = size(srccoeij_vx[s], 1) - @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_vx[s], srccoeval_vx[s], ρ, it, s) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) end for s in 1:nsrcs_vz nsrcpts_vz = size(srccoeij_vz[s], 1) - @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_ihalf_jhalf, it, s) + @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_jhalf, it, s, dt) end # record receivers @@ -487,14 +433,11 @@ function forward_onestep_CPML!( end # update stresses σxx and σzz - @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, - vx, vz, dt, λ_ihalf, μ_ihalf, - ψ_∂vx∂x, ψ_∂vz∂z, - b_x_half, b_z, a_x_half, a_z, freetop) + @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ, μ, + ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) # update stress σxz - @parallel (3:nx-1, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, - μ_jhalf, b_x, b_z_half, - ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, + ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) return end @@ -536,38 +479,41 @@ function adjoint_onestep_CPML!( b_z = cpmlcoeffs[2].b b_z_half = cpmlcoeffs[2].b_h - ρ = grid.fields["ρ"].value - ρ_ihalf_jhalf = grid.fields["ρ_ihalf_jhalf"].value - λ_ihalf = grid.fields["λ_ihalf"].value - μ_ihalf = grid.fields["μ_ihalf"].value - μ_jhalf = grid.fields["μ_jhalf"].value + λ = grid.fields["λ"].value + μ = grid.fields["μ"].value + ρ_ihalf = grid.fields["ρ_ihalf"].value + ρ_jhalf = grid.fields["ρ_jhalf"].value + μ_ihalf_jhalf = grid.fields["μ_ihalf_jhalf"].value # Precomputing divisions factx = 1.0 / (24.0 * dx) factz = 1.0 / (24.0 * dz) # update stresses σxx and σzz - @parallel (2:nx-2, 1:nz-1) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, - vx, vz, dt, λ_ihalf, μ_ihalf, - ψ_∂vx∂x, ψ_∂vz∂z, - b_x_half, b_z, a_x_half, a_z, freetop) + @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ, μ, + ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) # update stress σxz - @parallel (3:nx-1, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, - μ_jhalf, b_x, b_z_half, - ψ_∂vx∂z, ψ_∂vz∂x, a_x, a_z_half, freetop) + @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, + ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) - # update velocity vx - @parallel (3:nx-1, 1:nz-1) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ, ψ_∂σxx∂x, ψ_∂σxz∂z, - b_x, b_z, a_x, a_z, freetop) + # update velocity vx + @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, + ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) # update velocity vz - @parallel (2:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_ihalf_jhalf, ψ_∂σxz∂x, - ψ_∂σzz∂z, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, + ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) # inject sources (residuals as velocities) - nsrcpts_vx = size(srccoeij_vx, 1) - nsrcpts_vz = size(srccoeij_vz, 1) - @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, residuals_bk, srccoeij_vx, srccoeval_vx, ρ, it) - @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, residuals_bk, srccoeij_vz, srccoeval_vz, ρ_ihalf_jhalf, it) + nsrcs_vx = size(srccoeij_vx, 1) + nsrcs_vz = size(srccoeij_vz, 1) + for s in 1:nsrcs_vx + nsrcpts_vx = size(srccoeij_vx[s], 1) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, residuals_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) + end + for s in 1:nsrcs_vz + nsrcpts_vz = size(srccoeij_vz[s], 1) + @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, residuals_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_jhalf, it, s, dt) + end return end \ No newline at end of file diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index f5d7a78..07cab26 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -74,6 +74,7 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound # Save snapshot if snapenabled(model) savesnapshot!(model.snapshotter, "v" => model.grid.fields["v"], it) + savesnapshot!(model.snapshotter, "σ" => model.grid.fields["σ"], it) end end @@ -109,7 +110,7 @@ end reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] - + srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) @@ -149,6 +150,7 @@ end # Save snapshot if snapenabled(model) savesnapshot!(model.snapshotter, "v" => model.grid.fields["v"], it) + savesnapshot!(model.snapshotter, "σ" => model.grid.fields["σ"], it) end end diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 9cf69b5..cc9c999 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -7,14 +7,14 @@ if sincinterp # interpolation coefficients for sources in vx nsrcs = size(shot.srcs.positions, 1) - srccoeij_vx, srccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=0.0) + srccoeij_vx, srccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=0.0) # interpolation coefficients for sources in vz - srccoeij_vz, srccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + srccoeij_vz, srccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=model.grid.spacing[2]/2) nrecs = size(shot.recs.positions, 1) # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=0.0) + reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=0.0) # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=model.grid.spacing[2]/2) else src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) @@ -30,24 +30,21 @@ reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end - # scale source time function with timestep size - scal_srctf = shot.srcs.tf .* model.dt - - return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf + return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, shot.srcs.tf end @views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}; sincinterp=false) where {T} if sincinterp nsrcs = size(shot.srcs.positions, 1) # interpolation coefficients for sources in σxx and σzz - srccoeij_xx, srccoeval_xx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=0.0) + srccoeij_xx, srccoeval_xx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=0.0) # interpolation coefficients for sources in σxz - srccoeij_xz, srccoeval_xz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=model.grid.spacing[2]/2) + srccoeij_xz, srccoeval_xz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) nrecs = size(shot.recs.positions, 1) # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=0.0) + reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=0.0) # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=model.grid.spacing[2]/2) else src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) @@ -63,10 +60,7 @@ end reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end - # scale source time function with timestep size - scal_srctf = shot.srcs.tf .* model.dt - - return srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, scal_srctf + return srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, shot.srcs.tf end @@ -129,23 +123,20 @@ end function precomp_elaprop!(model::ElasticIsoWaveSimulation{T, 2}) where {T} # Excract fields - ρ, λ, μ = model.grid.fields["ρ"].value, model.grid.fields["λ"].value, model.grid.fields["μ"].value - ρ_ihalf_jhalf = model.grid.fields["ρ_ihalf_jhalf"].value - μ_ihalf = model.grid.fields["μ_ihalf"].value - μ_jhalf = model.grid.fields["μ_jhalf"].value - λ_ihalf = model.grid.fields["λ_ihalf"].value + λ = model.grid.fields["λ"].value + μ = model.grid.fields["μ"].value + ρ_ihalf = model.grid.fields["ρ_ihalf"].value + ρ_jhalf = model.grid.fields["ρ_jhalf"].value + μ_ihalf_jhalf = model.grid.fields["μ_ihalf_jhalf"].value # Copy from internal matprop - copyto!(ρ, model.matprop.ρ) copyto!(λ, model.matprop.λ) copyto!(μ, model.matprop.μ) #------------------------------------------------------------- # pre-interpolate properties at half distances between nodes #------------------------------------------------------------- - copyto!(ρ_ihalf_jhalf, interp(model.matprop.interp_method_ρ, model.matprop.ρ, [1, 2])) - copyto!(λ_ihalf, interp(model.matprop.interp_method_λ, model.matprop.λ, 1)) - copyto!(μ_ihalf, interp(model.matprop.interp_method_μ, model.matprop.μ, 1)) - copyto!(μ_jhalf, interp(model.matprop.interp_method_μ, model.matprop.μ, 2)) - + copyto!(ρ_ihalf, interp(model.matprop.interp_method_ρ, model.matprop.ρ, 1)) + copyto!(ρ_jhalf, interp(model.matprop.interp_method_ρ, model.matprop.ρ, 2)) + copyto!(μ_ihalf_jhalf, interp(model.matprop.interp_method_μ, model.matprop.μ, [1, 2])) return end @@ -214,88 +205,116 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac if N == 2 # Stress and velocity addfield!(grid, "σ" => MultiVariableField( - [backend.zeros(T, gridsize...) for _ in 1:3] + [ + backend.zeros(T, gridsize...), # σxx + backend.zeros(T, gridsize...), # σzz + backend.zeros(T, (gridsize .- 1)...) # σxz + ] )) addfield!(grid, "v" => MultiVariableField( - [backend.zeros(T, gridsize...) for _ in 1:2] + [ + backend.zeros(T, (gridsize .- [1, 0])...), # vx + backend.zeros(T, (gridsize .- [0, 1])...) # vz + ] )) # Material properties - addfield!(grid, "ρ" => ScalarVariableField( - backend.zeros(T, gridsize...) - )) addfield!(grid, "λ" => ScalarVariableField( backend.zeros(T, gridsize...) )) addfield!(grid, "μ" => ScalarVariableField( backend.zeros(T, gridsize...) )) - addfield!(grid, "λ_ihalf" => ScalarVariableField( - backend.zeros(T, (gridsize .- [1, 0])...) - )) - addfield!(grid, "μ_ihalf" => ScalarVariableField( + addfield!(grid, "ρ_ihalf" => ScalarVariableField( backend.zeros(T, (gridsize .- [1, 0])...) )) - addfield!(grid, "μ_jhalf" => ScalarVariableField( + addfield!(grid, "ρ_jhalf" => ScalarVariableField( backend.zeros(T, (gridsize .- [0, 1])...) )) - addfield!(grid, "ρ_ihalf_jhalf" => ScalarVariableField( + addfield!(grid, "μ_ihalf_jhalf" => ScalarVariableField( backend.zeros(T, (gridsize .- 1)...) )) # CPML memory variables - grds = [gridsize...] - gs1, gs2 = copy(grds), copy(grds) - gs1[1] = 2 * halo - gs2[2] = 2 * halo addfield!(grid, "ψ_∂σ∂x" => MultiVariableField( - [backend.zeros(T, gs1...) for _ in 1:2] + [ + backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂σxx∂x + backend.zeros(T, 2halo , gridsize[2]-1) # ψ_∂σxz∂x + ] )) addfield!(grid, "ψ_∂σ∂z" => MultiVariableField( - [backend.zeros(T, gs2...) for _ in 1:2] + [ + backend.zeros(T, gridsize[1] , 2(halo+1)), # ψ_∂σzz∂z + backend.zeros(T, gridsize[1]-1, 2halo ) # ψ_∂σxz∂z + ] )) addfield!(grid, "ψ_∂v∂x" => MultiVariableField( - [backend.zeros(T, gs1...) for _ in 1:2] + [ + backend.zeros(T, 2halo , gridsize[2] ), # ψ_∂vx∂x + backend.zeros(T, 2(halo+1), gridsize[2]-1) # ψ_∂vz∂x + ] )) addfield!(grid, "ψ_∂v∂z" => MultiVariableField( - [backend.zeros(T, gs2...) for _ in 1:2] + [ + backend.zeros(T, gridsize[1]-1, 2(halo+1)), # ψ_∂vx∂z + backend.zeros(T, gridsize[1] , 2halo ) # ψ_∂vz∂z + ] )) # Initialize gradient arrays if needed if gradient # Stress and velocity addfield!(grid, "adjσ" => MultiVariableField( - [backend.zeros(T, gridsize...) for _ in 1:3] + [ + backend.zeros(T, gridsize...), # σxx + backend.zeros(T, gridsize...), # σzz + backend.zeros(T, (gridsize .- 1)...) # σxz + ] )) addfield!(grid, "adjv" => MultiVariableField( - [backend.zeros(T, gridsize...) for _ in 1:2] + [ + backend.zeros(T, (gridsize .- [1, 0])...), # vx + backend.zeros(T, (gridsize .- [0, 1])...) # vz + ] )) # CPML memory variables - addfield!(grid, "adjψ_∂σ∂x" => MultiVariableField( - [backend.zeros(T, gs1...) for _ in 1:2] + addfield!(grid, "adjψ_∂σ∂x" => MultiVariableField( + [ + backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂σxx∂x + backend.zeros(T, 2halo , gridsize[2]-1) # ψ_∂σxz∂x + ] )) addfield!(grid, "adjψ_∂σ∂z" => MultiVariableField( - [backend.zeros(T, gs2...) for _ in 1:2] + [ + backend.zeros(T, gridsize[1] , 2(halo+1)), # ψ_∂σzz∂z + backend.zeros(T, gridsize[1]-1, 2halo ) # ψ_∂σxz∂z + ] )) addfield!(grid, "adjψ_∂v∂x" => MultiVariableField( - [backend.zeros(T, gs1...) for _ in 1:2] + [ + backend.zeros(T, 2halo , gridsize[2] ), # ψ_∂vx∂x + backend.zeros(T, 2(halo+1), gridsize[2]-1) # ψ_∂vz∂x + ] )) addfield!(grid, "adjψ_∂v∂z" => MultiVariableField( - [backend.zeros(T, gs2...) for _ in 1:2] + [ + backend.zeros(T, gridsize[1]-1, 2(halo+1)), # ψ_∂vx∂z + backend.zeros(T, gridsize[1] , 2halo ) # ψ_∂vz∂z + ] )) # Gradient arrays - addfield!(grid, "grad_ρ" => ScalarVariableField( + addfield!(grid, "grad_λ" => ScalarVariableField( backend.zeros(T, gridsize...) )) - addfield!(grid, "grad_ρ_ihalf_jhalf" => ScalarVariableField( - backend.zeros(T, (gridsize .- 1)...) - )) - addfield!(grid, "grad_λ_ihalf" => ScalarVariableField( - backend.zeros(T, (gridsize .- [1, 0])...) + addfield!(grid, "grad_μ" => ScalarVariableField( + backend.zeros(T, gridsize...) )) - addfield!(grid, "grad_μ_ihalf" => ScalarVariableField( + addfield!(grid, "grad_ρ_ihalf" => ScalarVariableField( backend.zeros(T, (gridsize .- [1, 0])...) )) - addfield!(grid, "grad_μ_jhalf" => ScalarVariableField( + addfield!(grid, "grad_ρ_jhalf" => ScalarVariableField( backend.zeros(T, (gridsize .- [0, 1])...) )) + addfield!(grid, "grad_μ_ihalf_jhalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- 1)...) + )) # Initialize checkpointer checkpointer = LinearCheckpointer( @@ -322,9 +341,21 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac if snapevery !== nothing # Initialize snapshotter - snapshotter = LinearSnapshotter{Array{T, N}}(nt, snapevery, Dict("v" => MultiVariableField( - [backend.zeros(T, gridsize...) for _ in 1:N] - ))) + snapshotter = LinearSnapshotter{Array{T, N}}(nt, snapevery, Dict( + "v" => MultiVariableField( + [ + backend.zeros(T, (gridsize .- [1, 0])...), # vx + backend.zeros(T, (gridsize .- [0, 1])...) # vz + ] + ), + "σ" => MultiVariableField( + [ + backend.zeros(T, gridsize...), # σxx + backend.zeros(T, gridsize...), # σzz + backend.zeros(T, (gridsize .- 1)...) # σxz + ] + ) + )) end # Check infoevery @@ -361,7 +392,7 @@ end @views function reset!(model::ElasticIsoCPMLWaveSimulation{T, N}) where {T, N} # Reset computational arrays - reset!(model.grid; except=["ρ", "λ", "μ", "λ_ihalf", "μ_ihalf", "μ_jhalf", "ρ_ihalf_jhalf"]) + reset!(model.grid; except=["λ", "μ", "ρ_ihalf", "ρ_jhalf", "μ_ihalf_jhalf"]) if model.checkpointer !== nothing reset!(model.checkpointer) end diff --git a/src/utils/snapshotter.jl b/src/utils/snapshotter.jl index 11d0cf5..e33abed 100644 --- a/src/utils/snapshotter.jl +++ b/src/utils/snapshotter.jl @@ -35,7 +35,7 @@ end function savesnapshot!(snapshotter::LinearSnapshotter{T, N}, field::Pair{String, <:AbstractField{T}}, it::Int) where {T, N} # Save field in snapshots if it % snapshotter.snapevery == 0 - @info @sprintf("Snapping iteration: %d", it) + @info @sprintf("Field: %s, snapping iteration: %d", field.first, it) copyto!(snapshotter.snapshots[it][field.first], field.second) end end From ba6e662a3a9e0b7f4c251660e2fa75fa495c83df Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 22 Oct 2024 16:26:05 +0200 Subject: [PATCH 082/111] Fix gradient correlations and checkpointing + test --- .../backends/shared/correlate_gradient_xPU.jl | 102 ++++++++++-------- src/models/elastic/ela_gradient.jl | 57 +++++----- .../test_gradient_elastic_constant_density.jl | 58 +++++++++- 3 files changed, 144 insertions(+), 73 deletions(-) diff --git a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl index 6427222..fb40bf5 100644 --- a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl +++ b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl @@ -4,70 +4,78 @@ return nothing end -@parallel_indices (i, j) function correlate_gradient_ihalf_kernel!(grad_λ_ihalf, grad_μ_ihalf, adjσxx, adjσzz, vx, vz, λ_ihalf, μ_ihalf, factx, factz, freetop) - ∂vx∂x_fwd = ∂vz∂z_bkd = 0 - if freetop == true - # j=1: we are on the free surface! - if j == 1 - # vx derivative only in x so no problem - ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx - # using boundary condition to calculate ∂vz∂z_bkd from ∂vx∂x_fwd - ∂vz∂z_bkd = -(λ_ihalf[i, j] / (λ_ihalf[i, j] + 2.0 * μ_ihalf[i, j])) * ∂vx∂x_fwd - end - # j=2: we are just below the surface (1/2) - if j == 2 - # vx derivative only in x so no problem - ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx - # zero velocity above the free surface - ∂vz∂z_bkd = (0.0 - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) * factz - end - end - if j >= 3 - ∂vx∂x_fwd = (vx[i-1, j] - 27.0 * vx[i, j] + 27.0 * vx[i+1, j] - vx[i+2, j]) * factx - ∂vz∂z_bkd = (vz[i, j-2] - 27.0 * vz[i, j-1] + 27.0 * vz[i, j] - vz[i, j+1]) * factz +@parallel_indices (i, j) function correlate_gradient_λ_μ_kernel!(grad_λ, grad_μ, adjσxx, adjσzz, vx, vz, λ, μ, factx, factz, freetop) + ∂vx∂x = 0.0 + ∂vz∂z = 0.0 + if freetop && j == 1 + # on the free surface, σzz = 0 + ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx + # using boundary condition to calculate ∂vz∂z + ∂vz∂z = -(λ[i, j] / (λ[i, j] + 2*μ[i, j])) * ∂vx∂x + elseif freetop && j == 2 + # just below the free surface + ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx + # zero velocity above the free surface + ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + 0.0) * factz + elseif j >= 3 + ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx + ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + vz[i, j-2]) * factz end # correlate - grad_λ_ihalf[i, j] += -((∂vx∂x_fwd + ∂vz∂z_bkd) * (adjσxx[i, j] + adjσzz[i, j])) - grad_μ_ihalf[i, j] += (-2 * ∂vx∂x_fwd * adjσxx[i, j]) + (-2 * ∂vz∂z_bkd * adjσzz[i, j]) + grad_λ[i, j] += (-(∂vx∂x + ∂vz∂z) * (adjσxx[i, j] + adjσzz[i, j])) + grad_μ[i, j] += (-2 * ∂vx∂x * adjσxx[i, j]) + (-2 * ∂vz∂z * adjσzz[i, j]) return nothing end -@parallel_indices (i, j) function correlate_gradient_jhalf_kernel!(grad_μ_jhalf, adjσxz, vx, vz, factx, factz, freetop) - ∂vx∂z_fwd = ∂vz∂x_bkd = 0 - if freetop - if j == 1 - # zero velocity above the free surface - ∂vx∂z_fwd = factz * (0.0 - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) - # vz derivative only in x so no problem - ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) - end - end - if j >= 2 - ∂vx∂z_fwd = factz * (vx[i, j-1] - 27.0 * vx[i, j] + 27.0 * vx[i, j+1] - vx[i, j+2]) - ∂vz∂x_bkd = factx * (vz[i-2, j] - 27.0 * vz[i-1, j] + 27.0 * vz[i, j] - vz[i+1, j]) +@parallel_indices (i, j) function correlate_gradient_μ_ihalf_jhalf_kernel!(grad_μ_ihalf_jhalf, adjσxz, vx, vz, factx, factz, freetop) + ∂vx∂z = 0.0 + ∂vz∂x = 0.0 + if freetop && j == 1 + # zero velocity above the free surface + ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + 0.0 ) * factz + ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx + elseif j >= 2 + ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + vx[i, j-1]) * factz + ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx end # correlate - grad_μ_jhalf[i, j] += (-∂vx∂z_fwd-∂vz∂x_bkd) * adjσxz[i, j] + grad_μ_ihalf_jhalf[i, j] += -(∂vx∂z+∂vz∂x) * adjσxz[i, j] return nothing end @views function correlate_gradients!(grid, vcurr, vold, dt, freetop) nx, nz = grid.size - @parallel correlate_gradient_ρ_kernel!(grid.fields["grad_ρ"].value, grid.fields["adjv"].value[1], vcurr[1], vold[1], 1 / dt) - @parallel correlate_gradient_ρ_kernel!(grid.fields["grad_ρ_ihalf_jhalf"].value, grid.fields["adjv"].value[2], vcurr[2], vold[2], 1 / dt) - @parallel (2:nx-2, 1:nz-1) correlate_gradient_ihalf_kernel!( - grid.fields["grad_λ_ihalf"].value, - grid.fields["grad_μ_ihalf"].value, - grid.fields["adjσ"].value[1], grid.fields["adjσ"].value[2], vcurr..., - grid.fields["λ_ihalf"].value, grid.fields["μ_ihalf"].value, + @parallel correlate_gradient_ρ_kernel!( + grid.fields["grad_ρ_ihalf"].value, + grid.fields["adjv"].value[1], + vcurr[1], + vold[1], + 1 / dt + ) + @parallel correlate_gradient_ρ_kernel!( + grid.fields["grad_ρ_jhalf"].value, + grid.fields["adjv"].value[2], + vcurr[2], + vold[2], + 1 / dt + ) + @parallel (3:nx-2, 1:nz-2) correlate_gradient_λ_μ_kernel!( + grid.fields["grad_λ"].value, + grid.fields["grad_μ"].value, + grid.fields["adjσ"].value[1], + grid.fields["adjσ"].value[2], + vcurr..., + grid.fields["λ"].value, + grid.fields["μ"].value, (1.0 ./ (24.0 .* grid.spacing))..., freetop ) - @parallel (3:nx-1, 1:nz-2) correlate_gradient_jhalf_kernel!( - grid.fields["grad_μ_jhalf"].value, - grid.fields["adjσ"].value[3], vcurr..., + @parallel (2:nx-2, 1:nz-2) correlate_gradient_μ_ihalf_jhalf_kernel!( + grid.fields["grad_μ_ihalf_jhalf"].value, + grid.fields["adjσ"].value[3], + vcurr..., (1.0 ./ (24.0 .* grid.spacing))..., freetop ) diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index fedf13f..9a6924f 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -10,7 +10,7 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = # scale source time function srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, - scal_srctf = possrcrec_scaletf(model, shots; sincinterp=model.sincinterp) + scal_srctf = possrcrec_scaletf(model, shot; sincinterp=model.sincinterp) # moment tensors momtens = shot.srcs.momtens @@ -46,7 +46,8 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = # Forward time loop for it in 1:nt # Compute one forward step - backend.forward_onestep_CPML!(model, + backend.forward_onestep_CPML!( + model, srccoeij_xx, srccoeval_xx, srccoeij_xz, @@ -59,7 +60,8 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = traces_bk, it, Mxx_bk, Mzz_bk, Mxz_bk; - save_trace=true) + save_trace=true + ) # Print timestep info if it % model.infoevery == 0 @@ -118,7 +120,8 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = recover!( checkpointer, recit -> begin - backend.forward_onestep_CPML!(model, + backend.forward_onestep_CPML!( + model, srccoeij_xx, srccoeval_xx, srccoeij_xz, @@ -128,10 +131,11 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = reccoeij_vz, reccoeval_vz, srctf_bk, - nothing, - it, + traces_bk, + recit, Mxx_bk, Mzz_bk, Mxz_bk; - save_trace=false) + save_trace=false + ) return ["v" => grid.fields["v"]] end ) @@ -147,12 +151,12 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = gradient_λ = zeros(T, grid.size...) gradient_μ = zeros(T, grid.size...) # Get gradients - copyto!(gradient_ρ, grid.fields["grad_ρ"].value) + copyto!(gradient_λ, grid.fields["grad_λ"].value) + copyto!(gradient_μ, grid.fields["grad_μ"].value) # Compute chain rules for back interpolations - gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf_jhalf"].value), [1, 2]) - gradient_λ .+= back_interp(model.matprop.interp_method_λ, model.matprop.λ, Array(grid.fields["grad_λ_ihalf"].value), 1) - gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf"].value), 1) .+ - back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_jhalf"].value), 2) + gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf"].value), 1) .+ + back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_jhalf"].value), 2) + gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf_jhalf"].value), [1, 2]) # TODO smooth gradients # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) @@ -193,7 +197,7 @@ end reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] - + srctf_bk = backend.Data.Array(scal_srctf) traces_bk = backend.zeros(T, size(shot.recs.seismograms)) @@ -203,7 +207,8 @@ end # Forward time loop for it in 1:nt # Compute one forward step - backend.forward_onestep_CPML!(model, + backend.forward_onestep_CPML!( + model, srccoeij_vx, srccoeval_vx, srccoeij_vz, @@ -215,7 +220,8 @@ end srctf_bk, traces_bk, it; - save_trace=true) + save_trace=true + ) # Print timestep info if it % model.infoevery == 0 @@ -274,7 +280,8 @@ end recover!( checkpointer, recit -> begin - backend.forward_onestep_CPML!(model, + backend.forward_onestep_CPML!( + model, srccoeij_vx, srccoeval_vx, srccoeij_vz, @@ -284,10 +291,10 @@ end reccoeij_vz, reccoeval_vz, srctf_bk, - nothing, - it, - fx_bk, fz_bk; - save_trace=false) + traces_bk, + recit; + save_trace=false + ) return ["v" => grid.fields["v"]] end ) @@ -303,12 +310,12 @@ end gradient_λ = zeros(T, grid.size...) gradient_μ = zeros(T, grid.size...) # Get gradients - copyto!(gradient_ρ, grid.fields["grad_ρ"].value) + copyto!(gradient_λ, grid.fields["grad_λ"].value) + copyto!(gradient_μ, grid.fields["grad_μ"].value) # Compute chain rules for back interpolations - gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf_jhalf"].value), [1, 2]) - gradient_λ .+= back_interp(model.matprop.interp_method_λ, model.matprop.λ, Array(grid.fields["grad_λ_ihalf"].value), 1) - gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf"].value), 1) .+ - back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_jhalf"].value), 2) + gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf"].value), 1) .+ + back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_jhalf"].value), 2) + gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf_jhalf"].value), [1, 2]) # TODO smooth gradients # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) diff --git a/test/test_gradient_elastic_constant_density.jl b/test/test_gradient_elastic_constant_density.jl index d931739..f7125de 100644 --- a/test/test_gradient_elastic_constant_density.jl +++ b/test/test_gradient_elastic_constant_density.jl @@ -4,7 +4,7 @@ using CUDA: CUDA using Logging using SeismicWaves -with_logger(ConsoleLogger(stderr, Logging.Info)) do +with_logger(ConsoleLogger(stderr, Logging.Warn)) do test_backends = [:threads] # test GPU backend only if CUDA is functional if @isdefined(CUDA) && CUDA.functional() @@ -56,5 +56,61 @@ with_logger(ConsoleLogger(stderr, Logging.Info)) do # Check that misfits are equivalent @test misfit ≈ misfit_check end + + @testset "Test 2D (P-SV) $(parall) swgradient! checkpointing" begin + # Physics + ρ0 = 2100.0 + vp0 = 3210.5 + vs0 = vp0 / sqrt(3) + λ0 = ρ0 * (vp0^2 - 2 * vs0^2) + μ0 = ρ0 * vs0^2 + f0 = 12.0 + T = 0.075 + # Numerics + nx = 380 # 211 + nz = 270 # 120 + dx = dz = 4.5 # meters + dt = 0.0005 + nt = ceil(Int, T / dt) + halo = 20 + rcoef = 0.0001 + params, shots, matprop = setup_constant_elastic_2D_CPML(nt, dt, nx, nz, dx, dz, ρ0, λ0, μ0, halo, rcoef, f0) + + # Compute gradient and misfit with checkpointing + grad, misfit = swgradient!( + params, + matprop, + shots; + parall=parall, + check_freq=floor(Int, sqrt(nt)), + compute_misfit=true + ) + # Compute gradient and misfit without checkpointing + grad_check, misfit_check = swgradient!( + params, + matprop, + shots; + parall=parall, + check_freq=nothing, + compute_misfit=true + ) + + # Check that gradients are non zero + @test !all(g -> g == 0.0, grad["rho"]) + @test !all(g -> g == 0.0, grad["lambda"]) + @test !all(g -> g == 0.0, grad["mu"]) + @test !all(g -> g == 0.0, grad_check["rho"]) + @test !all(g -> g == 0.0, grad_check["lambda"]) + @test !all(g -> g == 0.0, grad_check["mu"]) + # Check that misfits are non zero + @test !(misfit ≈ 0.0) + @test !(misfit_check ≈ 0.0) + # Check that misfits are equivalent + @test misfit ≈ misfit_check + # Check that gradients are equivalent + @test grad["rho"] ≈ grad_check["rho"] + @test grad["lambda"] ≈ grad_check["lambda"] + @test grad["mu"] ≈ grad_check["mu"] + end end end From 2ea1bd327612743e9d4c5cf15bf7c0c1e2a50a89 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 23 Oct 2024 16:38:04 +0200 Subject: [PATCH 083/111] Update grad check --- .../elastic/gradient_check_fd.jl | 207 ++++++++++++------ 1 file changed, 142 insertions(+), 65 deletions(-) diff --git a/examples/gradient_check_fd/elastic/gradient_check_fd.jl b/examples/gradient_check_fd/elastic/gradient_check_fd.jl index cb967b5..0c13e3b 100644 --- a/examples/gradient_check_fd/elastic/gradient_check_fd.jl +++ b/examples/gradient_check_fd/elastic/gradient_check_fd.jl @@ -13,6 +13,15 @@ function gaussian_vel_2D(nx, ny, c0, c0max, r, origin=[(nx + 1) / 2, (ny + 1) / return c0 .+ [f(x, y) for x in 1:nx, y in 1:ny] end +function gradient_vel_2D(nx, ny, c0, c0max) + c = zeros(nx, ny) + dc = (c0max - c0) / (ny-1) + for j in 1:ny + c[:, j] .= c0 .+ dc * (j-1) + end + return c +end + function create_constant_velocity_model(nx, nz, ρ0, vp0, vs0=vp0 / sqrt(3)) vp = vp0 .* ones(nx, nz) vs = vs0 .* ones(nx, nz) @@ -34,41 +43,37 @@ function create_gaussian_velocity_model(nx, nz, ρ0, vp0, vs0=vp0 / sqrt(3)) end # Function to define shots -function define_shots(nx, nz, nt, dt, dh) +function define_shots(lx, lz, nx, nz, nt, dt, dh) nsrc = 1 possrcs = zeros(nsrc, 2) - for s in 1:nsrc - possrcs[s, :] .= [(s / (nsrc+1) * nx) * dh, (nz / 6) * dh] - end - f0 = 150.0 + possrcs[1, :] .= [lx / 3, lz / 2] + f0 = 4.0 t0 = 1.20 / f0 - # srcstf = zeros(nt, nsrc) - # Mxx = fill(5e10, nsrc) - # Mzz = fill(0.0, nsrc) - # Mxz = fill(0.0, nsrc) - # srcstf[:, 1] .= rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) - srcstf = zeros(nt, 2, nsrc) - for s in 1:nsrc - srcstf[:, 1, s] .= 0.0 .* rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) - srcstf[:, 2, s] .= 1e10 .* rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) - end - srcs = ExternalForceSources(possrcs, srcstf, f0) - # srcs = MomentTensorSources(possrcs, srcstf, [MomentTensor2D(; Mxx=Mxx[s], Mzz=Mzz[s], Mxz=Mxz[s]) for s in 1:nsrc], f0) + srcstf = zeros(nt, nsrc) + Mxx = fill(1e15, nsrc) + Mzz = fill(1e15, nsrc) + Mxz = fill(2e14, nsrc) + srcstf[:, 1] .= rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) + # srcstf = zeros(nt, 2, nsrc) + # for s in 1:nsrc + # srcstf[:, 1, s] .= 1e10 .* rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) + # srcstf[:, 2, s] .= 1e10 .* rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) + # end + # srcs = ExternalForceSources(possrcs, srcstf, f0) + srcs = MomentTensorSources(possrcs, srcstf, [MomentTensor2D(; Mxx=Mxx[s], Mzz=Mzz[s], Mxz=Mxz[s]) for s in 1:nsrc], f0) nrecs = 1 posrecs = zeros(nrecs, 2) - for r in 1:nrecs - posrecs[r, :] .= [(r / (nrecs+1) * nx) * dh, (5nz / 6) * dh] - end + posrecs[1, :] .= [2lx / 3, lz / 2] recs = VectorReceivers(posrecs, nt) - shots = [ExternalForceShot(; srcs=srcs, recs=recs)] - # shots = [MomentTensorShot(; srcs=srcs, recs=recs)] + # shots = [ExternalForceShot(; srcs=srcs, recs=recs)] + shots = [MomentTensorShot(; srcs=srcs, recs=recs)] return shots end # Function to compute the forward simulation function compute_forward_simulation(params, matprop, shots) - model = build_wavesim(params, matprop; parall=:threads, gradient=true, check_freq=nothing, snapevery=5) + model = build_wavesim(params, matprop; parall=:threads, gradient=true, check_freq=nothing, snapevery=20) snaps = swforward!(model, matprop, shots) return model, snaps end @@ -97,55 +102,128 @@ end # Main function to orchestrate the workflow function main() # Time and grid parameters - nt = 1000 - dt = 0.00008 halo = 20 - nx = 200 + halo*2 - nz = 200 + halo*2 - dh = 0.5 rcoef = 0.0001 + nx, nz = 11*7*5+1 + 2halo, 11*7*5+1 + 2halo + vp0 = 3100.0 + vs0 = vp0 / sqrt(3) + # vs0 = 0.0 + ρ0 = 2700.0 + lx = lz = 6000.0 + dx, dz = lx / (nx - 1), lz / (nz - 1) + T = 5.0 + dt = dx / vp0 / sqrt(2) * 0.7 + nt = ceil(Int, T / dt) + dh = dx = dz # Create velocity model - matprop_const = create_constant_velocity_model(nx, nz, 2100.0, 3100.0, 0.0) - matprop_gauss = create_gaussian_velocity_model(nx, nz, 2100.0, 3100.0, 0.0) + matprop_const = create_constant_velocity_model(nx, nz, ρ0, vp0, vs0) + # matprop_const.λ .= gradient_vel_2D(nx, nz, λ0, λ0 * 1.15) + matprop_gauss = deepcopy(matprop_const) + matprop_gauss.ρ .*= 0.75 + # matprop_gauss.ρ .= gradient_vel_2D(nx, nz, ρ0, ρ0 * 0.75) + # matprop_gauss = create_constant_velocity_model(nx, nz, ρ0 * 0.75, vp0, vs0) + # Define shots - shots = define_shots(nx, nz, nt, dt, dh) + shots = define_shots(lx, lz, nx, nz, nt, dt, dh) # Input parameters for elastic simulation - boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false) + boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=true) params = InputParametersElastic(nt, dt, (nx, nz), (dh, dh), boundcond) # Compute forward simulation + println("Computing forward simulation to get observed data") model, snapshots = compute_forward_simulation(params, matprop_gauss, shots) # Compute the gradient - shots_grad = Vector{ExternalForceShot{Float64, 2}}() - # shots_grad = Vector{MomentTensorShot{Float64, 2, MomentTensor2D{Float64}}}() + # shots_grad = Vector{ExternalForceShot{Float64, 2}}() + shots_grad = Vector{MomentTensorShot{Float64, 2, MomentTensor2D{Float64}}}() for i in eachindex(shots) recs_grad = VectorReceivers(shots[i].recs.positions, nt; observed=copy(shots[i].recs.seismograms), invcov=1.0 * I(nt)) - push!(shots_grad, ExternalForceShot(; srcs=shots[i].srcs, recs=recs_grad)) - # push!(shots_grad, MomentTensorShot(; srcs=shots[i].srcs, recs=recs_grad)) + # push!(shots_grad, ExternalForceShot(; srcs=shots[i].srcs, recs=recs_grad)) + push!(shots_grad, MomentTensorShot(; srcs=shots[i].srcs, recs=recs_grad)) end + println("Compute gradient with adjoint method") grad, misfit = compute_gradient(model, matprop_const, shots_grad) serialize("grads_adj.jls", grad) - # # Compute FD gradients - # Δρ = minimum(ρ) * 1e-4 - # grad_ρ_FD = zeros(nx, nz) - # compute_fd_gradient!(grad_ρ_FD, :ρ, Δρ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) - # serialize("grad_ρ_FD.jls", grad_ρ_FD) - - # Δλ = minimum(λ) * 1e-4 - # grad_λ_FD = zeros(nx, nz) - # compute_fd_gradient!(grad_λ_FD, :λ, Δλ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) - # serialize("grad_λ_FD.jls", grad_λ_FD) - - # Δμ = minimum(λ) * 1e-4 - # grad_μ_FD = zeros(nx, nz) - # compute_fd_gradient!(grad_μ_FD, :μ, Δμ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) - # serialize("grad_μ_FD.jls", grad_μ_FD) + # # Check gradient with respect to density + # println("Check gradient with respect to ρ") + # @show minimum(matprop_const.ρ) + # Δρ = rand(nx, nz) .* minimum(matprop_const.ρ) .* 1e-6 + # FD_matprop_right = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ .+ Δρ, μ=matprop_const.μ, λ=matprop_const.λ) + # FD_matprop_left = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ .- Δρ, μ=matprop_const.μ, λ=matprop_const.λ) + # FD_misfit_right = swmisfit!(params, FD_matprop_right, shots_grad) + # FD_misfit_left = swmisfit!(params, FD_matprop_left, shots_grad) + # right = FD_misfit_right - FD_misfit_left + # left = dot(reduce(vcat, grad["rho"]), reduce(vcat, 2 .* Δρ)) + # println("χ(m + Δρ) - χ(m - Δρ) = ", right) + # println("∂χ/∂ρ * 2Δρ = ", left) + # println("Difference = ", right - left) + # println("Ratio = ", left / right) + + # # Check gradient with respect to λ + # println("Check gradient with respect to λ") + # @show minimum(matprop_const.λ) + # Δλ = rand(nx, nz) .* minimum(matprop_const.λ) .* 1e-6 + # FD_matprop_right = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ, μ=matprop_const.μ, λ=matprop_const.λ .+ Δλ) + # FD_matprop_left = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ, μ=matprop_const.μ, λ=matprop_const.λ .- Δλ) + # FD_misfit_right = swmisfit!(params, FD_matprop_right, shots_grad) + # FD_misfit_left = swmisfit!(params, FD_matprop_left, shots_grad) + # right = FD_misfit_right - FD_misfit_left + # left = dot(reduce(vcat, grad["lambda"]), reduce(vcat, 2 .* Δλ)) + # println("χ(m + Δλ) - χ(m - Δλ) = ", right) + # println("∂χ/∂λ * 2Δλ = ", left) + # println("Difference = ", right - left) + # println("Ratio = ", left / right) + + # println("Check gradient with respect to λ") + # @show minimum(matprop_const.λ) + # Δλ = rand(nx, nz) .* minimum(matprop_const.λ) .* 1e-6 + # FD_matprop_right = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ, μ=matprop_const.μ, λ=matprop_const.λ .+ Δλ) + # FD_matprop_left = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ, μ=matprop_const.μ, λ=matprop_const.λ .- Δλ) + # FD_misfit_right = swmisfit!(params, FD_matprop_right, shots_grad) + # FD_misfit_left = swmisfit!(params, FD_matprop_left, shots_grad) + # right = FD_misfit_right - FD_misfit_left + # left = dot(reduce(vcat, grad["lambda"]), reduce(vcat, 2 .* Δλ)) + # println("χ(m + Δλ) - χ(m - Δλ) = ", right) + # println("∂χ/∂λ * 2Δλ = ", left) + # println("Difference = ", right - left) + # println("Ratio = ", left / right) + + # # Check gradient with respect to μ + # println("Check gradient with respect to μ") + # @show minimum(matprop_const.μ) + # Δμ = rand(nx, nz) .* minimum(matprop_const.μ) .* 1e-6 + # FD_matprop_right = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ, μ=matprop_const.μ .+ Δμ, λ=matprop_const.λ) + # FD_matprop_left = ElasticIsoMaterialProperties(; ρ=matprop_const.ρ, μ=matprop_const.μ .- Δμ, λ=matprop_const.λ) + # FD_misfit_right = swmisfit!(params, FD_matprop_right, shots_grad) + # FD_misfit_left = swmisfit!(params, FD_matprop_left, shots_grad) + # right = FD_misfit_right - FD_misfit_left + # left = dot(reduce(vcat, grad["mu"]), reduce(vcat, 2 .* Δμ)) + # println("χ(m + Δμ) - χ(m - Δμ) = ", right) + # println("∂χ/∂μ * 2Δμ = ", left) + # println("Difference = ", right - left) + # println("Ratio = ", left / right) + + model = build_wavesim(params, matprop_const; parall=:threads) + # Compute FD gradients + Δρ = minimum(matprop_const.ρ) * 1e-4 + grad_ρ_FD = zeros(nx, nz) + compute_fd_gradient!(grad_ρ_FD, :ρ, Δρ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) + serialize("grad_ρ_FD.jls", grad_ρ_FD) + + Δλ = minimum(matprop_const.λ) * 1e-4 + grad_λ_FD = zeros(nx, nz) + compute_fd_gradient!(grad_λ_FD, :λ, Δλ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) + serialize("grad_λ_FD.jls", grad_λ_FD) + + Δμ = minimum(matprop_const.μ) * 1e-4 + grad_μ_FD = zeros(nx, nz) + compute_fd_gradient!(grad_μ_FD, :μ, Δμ, model, matprop_grad, shots_grad, misfit, halo, nx, nz) + serialize("grad_μ_FD.jls", grad_μ_FD) return params, matprop_gauss, shots, snapshots end @@ -156,7 +234,6 @@ function load_and_plot_gradients(params, shots) grad_ρ_FD = deserialize("grad_ρ_FD.jls") grad_λ_FD = deserialize("grad_λ_FD.jls") grad_μ_FD = deserialize("grad_μ_FD.jls") - # Plot gradients plotgrad(params, grads, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) end @@ -165,7 +242,7 @@ function plotgrad(par, grad, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) xgrd = [par.gridspacing[1] * (i - 1) for i in 1:par.gridsize[1]] ygrd = [par.gridspacing[2] * (i - 1) for i in 1:par.gridsize[2]] - fig = Figure(; size=(1000, 1000)) + fig = Figure(; size=(500, 1000)) axes = [ (Axis(fig[1, 1]; aspect=DataAspect(), title="grad ρ", xlabel="x [m]", ylabel="z [m]"), grad["rho"], "∂χ/∂ρ", [1,2]), @@ -181,14 +258,14 @@ function plotgrad(par, grad, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) for (ax, grad_data, label, cbarpos) in axes grad2 = copy(grad_data) for s in 1:size(shots[1].srcs.positions, 1) - srcx, srcy = ceil.(Int, shots[1].srcs.positions[s, :] ./ par.gridspacing) - grad2[srcx-radius:srcx+radius, srcy-radius:srcy+radius] .= 0 + srcx, srcy = ceil.(Int, shots[1].srcs.positions[s, :] ./ par.gridspacing) .+ 1 + grad2[srcx-radius:srcx+radius, srcy:srcy+radius] .= 0 end for r in 1:size(shots[1].recs.positions, 1) - recx, recy = ceil.(Int, shots[1].recs.positions[r, :] ./ par.gridspacing) - grad2[recx-radius:recx+radius, recy-radius:recy+radius] .= 0 + recx, recy = ceil.(Int, shots[1].recs.positions[r, :] ./ par.gridspacing) .+ 1 + grad2[recx-radius:recx+radius, recy:recy+radius] .= 0 end - maxabsgrad = maximum(abs.(grad2)) + maxabsgrad = maximum(abs.(grad2)) / 10 hm = heatmap!(ax, xgrd, ygrd, grad_data; colormap=:vik, colorrange=(-maxabsgrad, maxabsgrad)) Colorbar(fig[cbarpos[1], cbarpos[2]], hm; label=label) ax.yreversed = true @@ -198,7 +275,7 @@ function plotgrad(par, grad, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) return fig end -function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) +function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=20) xgrd = [par.gridspacing[1] * (i - 1) for i in 1:par.gridsize[1]] ygrd = [par.gridspacing[2] * (i - 1) for i in 1:par.gridsize[2]] xrec = shots[1].recs.positions[:, 1] @@ -231,7 +308,7 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) end ##===================================== - fig = Figure(; size=(800, 1500÷2 * 3)) + fig = Figure(; size=(1500, 500)) nframes = length(vxsnap) @@ -254,7 +331,7 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) # axislegend(ax1) ax1.yreversed = true - ax2 = Axis(fig[2, 1]; aspect=DataAspect(), + ax2 = Axis(fig[1, 3]; aspect=DataAspect(), xlabel="x [m]", ylabel="z [m]", title="Vz, clip at $scalamp of max amplitude, iteration 0 of $(snapevery*nframes)") #poly!(ax4,Rect(rect...),color=:green,alpha=0.3) extx = extrema.([vzsnap[i] for i in eachindex(vzsnap)]) @@ -263,7 +340,7 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) vminmax = scalamp .* (-vmax, vmax) hm = heatmap!(ax2, xgrd, ygrd, curvz; colormap=cmapwavefield, colorrange=vminmax) #,alpha=0.7) - Colorbar(fig[2, 2], hm; label="z partic. vel.") + Colorbar(fig[1, 4], hm; label="z partic. vel.") lines!(ax2, Rect(rectpml...); color=:green) scatter!(ax2, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) @@ -271,10 +348,10 @@ function snapanimate(par, matprop, shots, snapsh; scalamp=0.01, snapevery=5) # axislegend(ax2) ax2.yreversed = true - ax3 = Axis(fig[3, 1]; aspect=DataAspect(), + ax3 = Axis(fig[1, 5]; aspect=DataAspect(), xlabel="x [m]", ylabel="z [m]") hm = heatmap!(ax3, xgrd, ygrd, vp; colormap=:Reds) #,alpha=0.7) - Colorbar(fig[3, 2], hm; label="Vp") + Colorbar(fig[1, 6], hm; label="Vp") scatter!(ax3, xrec, yrec; marker=:dtriangle, label="Receivers", markersize=15) scatter!(ax3, xsrc, ysrc; label="Sources", markersize=15) @@ -313,6 +390,6 @@ end # Run the main function params, matprop_gauss, shots, snapshots = main() # Plot animation -snapanimate(params, matprop_gauss, shots, snapshots) +snapanimate(params, matprop_gauss, shots, snapshots; scalamp=0.005) # Load and plot gradients load_and_plot_gradients(params, shots) From 8e919b3f2c5c1a1a1ef59f9663d60ab60169551c Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 23 Oct 2024 16:48:13 +0200 Subject: [PATCH 084/111] Fix gradient check --- .../elastic/gradient_check_fd.jl | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/examples/gradient_check_fd/elastic/gradient_check_fd.jl b/examples/gradient_check_fd/elastic/gradient_check_fd.jl index 0c13e3b..94bcbc5 100644 --- a/examples/gradient_check_fd/elastic/gradient_check_fd.jl +++ b/examples/gradient_check_fd/elastic/gradient_check_fd.jl @@ -47,12 +47,12 @@ function define_shots(lx, lz, nx, nz, nt, dt, dh) nsrc = 1 possrcs = zeros(nsrc, 2) possrcs[1, :] .= [lx / 3, lz / 2] - f0 = 4.0 + f0 = 2.0 t0 = 1.20 / f0 srcstf = zeros(nt, nsrc) Mxx = fill(1e15, nsrc) Mzz = fill(1e15, nsrc) - Mxz = fill(2e14, nsrc) + Mxz = fill(0.0, nsrc) srcstf[:, 1] .= rickerstf.(collect(Float64, range(0.0; step=dt, length=nt)), t0, f0) # srcstf = zeros(nt, 2, nsrc) # for s in 1:nsrc @@ -104,7 +104,7 @@ function main() # Time and grid parameters halo = 20 rcoef = 0.0001 - nx, nz = 11*7*5+1 + 2halo, 11*7*5+1 + 2halo + nx, nz = 11*7*2+1 + 2halo, 11*7*2+1 + 2halo vp0 = 3100.0 vs0 = vp0 / sqrt(3) # vs0 = 0.0 @@ -120,7 +120,7 @@ function main() matprop_const = create_constant_velocity_model(nx, nz, ρ0, vp0, vs0) # matprop_const.λ .= gradient_vel_2D(nx, nz, λ0, λ0 * 1.15) matprop_gauss = deepcopy(matprop_const) - matprop_gauss.ρ .*= 0.75 + matprop_gauss.ρ .*= 0.9 # matprop_gauss.ρ .= gradient_vel_2D(nx, nz, ρ0, ρ0 * 0.75) # matprop_gauss = create_constant_velocity_model(nx, nz, ρ0 * 0.75, vp0, vs0) @@ -129,7 +129,7 @@ function main() shots = define_shots(lx, lz, nx, nz, nt, dt, dh) # Input parameters for elastic simulation - boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=true) + boundcond = CPMLBoundaryConditionParameters(; halo=halo, rcoef=rcoef, freeboundtop=false) params = InputParametersElastic(nt, dt, (nx, nz), (dh, dh), boundcond) # Compute forward simulation @@ -209,6 +209,7 @@ function main() # println("Ratio = ", left / right) model = build_wavesim(params, matprop_const; parall=:threads) + matprop_grad = deepcopy(matprop_const) # Compute FD gradients Δρ = minimum(matprop_const.ρ) * 1e-4 grad_ρ_FD = zeros(nx, nz) @@ -231,9 +232,10 @@ end # Function to load and plot gradients function load_and_plot_gradients(params, shots) grads = deserialize("grads_adj.jls") - grad_ρ_FD = deserialize("grad_ρ_FD.jls") - grad_λ_FD = deserialize("grad_λ_FD.jls") - grad_μ_FD = deserialize("grad_μ_FD.jls") + # grad_ρ_FD = deserialize("grad_ρ_FD.jls") + # grad_λ_FD = deserialize("grad_λ_FD.jls") + # grad_μ_FD = deserialize("grad_μ_FD.jls") + grad_ρ_FD = grad_λ_FD = grad_μ_FD = zeros(params.gridsize...) # Plot gradients plotgrad(params, grads, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) end @@ -259,13 +261,13 @@ function plotgrad(par, grad, shots, grad_ρ_FD, grad_λ_FD, grad_μ_FD) grad2 = copy(grad_data) for s in 1:size(shots[1].srcs.positions, 1) srcx, srcy = ceil.(Int, shots[1].srcs.positions[s, :] ./ par.gridspacing) .+ 1 - grad2[srcx-radius:srcx+radius, srcy:srcy+radius] .= 0 + grad2[srcx-radius:srcx+radius, srcy-radius:srcy+radius] .= 0 end for r in 1:size(shots[1].recs.positions, 1) recx, recy = ceil.(Int, shots[1].recs.positions[r, :] ./ par.gridspacing) .+ 1 - grad2[recx-radius:recx+radius, recy:recy+radius] .= 0 + grad2[recx-radius:recx+radius, recy-radius:recy+radius] .= 0 end - maxabsgrad = maximum(abs.(grad2)) / 10 + maxabsgrad = maximum(abs.(grad2)) hm = heatmap!(ax, xgrd, ygrd, grad_data; colormap=:vik, colorrange=(-maxabsgrad, maxabsgrad)) Colorbar(fig[cbarpos[1], cbarpos[2]], hm; label=label) ax.yreversed = true From a477f14bc0c3ca4cef696a1fe07cd9554134117d Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 24 Oct 2024 15:16:24 +0200 Subject: [PATCH 085/111] Refactor receiver recording to fix concurrency --- .../backends/shared/elastic2D_iso_xPU.jl | 44 +++++++++------ src/models/elastic/ela_forward.jl | 50 +++++++++++------ src/models/elastic/ela_gradient.jl | 56 +++++++++++++------ 3 files changed, 98 insertions(+), 52 deletions(-) diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 5979935..f15ef19 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -235,15 +235,15 @@ end return nothing end -@parallel_indices (p) function record_receivers2D_vx!(vx, traces_bk, reccoeij_vx, reccoeval_vx, it, r) +@parallel_indices (p) function record_receivers2D_vx!(vx, traces_vx_bk_buf, reccoeij_vx, reccoeval_vx) irec, jrec = reccoeij_vx[p, 1], reccoeij_vx[p, 2] - traces_bk[it, 1, r] += reccoeval_vx[p] * vx[irec, jrec] + traces_vx_bk_buf[p] = reccoeval_vx[p] * vx[irec, jrec] return nothing end -@parallel_indices (p) function record_receivers2D_vz!(vz, traces_bk, reccoeij_vz, reccoeval_vz, it, r) +@parallel_indices (p) function record_receivers2D_vz!(vz, traces_vz_bk_buf, reccoeij_vz, reccoeval_vz) irec, jrec = reccoeij_vz[p, 1], reccoeij_vz[p, 2] - traces_bk[it, 2, r] += reccoeval_vz[p] * vz[irec, jrec] + traces_vz_bk_buf[p] = reccoeval_vz[p] * vz[irec, jrec] return nothing end @@ -258,6 +258,9 @@ function forward_onestep_CPML!( reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, it::Int, Mxx_bk, @@ -312,16 +315,19 @@ function forward_onestep_CPML!( # record receivers if save_trace - nrecs_vx = size(reccoeij_vx, 1) - nrecs_vz = size(reccoeij_vz, 1) - for r in 1:nrecs_vx + nrecs = size(reccoeij_vx, 1) + for r in 1:nrecs nrecspts_vx = size(reccoeij_vx[r], 1) - @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx[r], reccoeval_vx[r], it, r) + @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_vx_bk_buf[r], reccoeij_vx[r], reccoeval_vx[r]) + reduced_buf[r] = reduce(+, traces_vx_bk_buf[r]) end - for r in 1:nrecs_vz + copyto!(@view(traces_bk[it, 1, :]), reduced_buf) + for r in 1:nrecs nrecspts_vz = size(reccoeij_vz[r], 1) - @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz[r], reccoeval_vz[r], it, r) + @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_vz_bk_buf[r], reccoeij_vz[r], reccoeval_vz[r]) + reduced_buf[r] = reduce(+, traces_vz_bk_buf[r]) end + copyto!(@view(traces_bk[it, 2, :]), reduced_buf) end # update stresses σxx and σzz @@ -357,6 +363,9 @@ function forward_onestep_CPML!( reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, it::Int; save_trace::Bool=true @@ -420,16 +429,19 @@ function forward_onestep_CPML!( # record receivers if save_trace - nrecs_vx = size(reccoeij_vx, 1) - nrecs_vz = size(reccoeij_vz, 1) - for r in 1:nrecs_vx + nrecs = size(reccoeij_vx, 1) + for r in 1:nrecs nrecspts_vx = size(reccoeij_vx[r], 1) - @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_bk, reccoeij_vx[r], reccoeval_vx[r], it, r) + @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_vx_bk_buf[r], reccoeij_vx[r], reccoeval_vx[r]) + reduced_buf[r] = reduce(+, traces_vx_bk_buf[r]) end - for r in 1:nrecs_vz + copyto!(@view(traces_bk[it, 1, :]), reduced_buf) + for r in 1:nrecs nrecspts_vz = size(reccoeij_vz[r], 1) - @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_bk, reccoeij_vz[r], reccoeval_vz[r], it, r) + @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_vz_bk_buf[r], reccoeij_vz[r], reccoeval_vz[r]) + reduced_buf[r] = reduce(+, traces_vz_bk_buf[r]) end + copyto!(@view(traces_bk[it, 2, :]), reduced_buf) end # update stresses σxx and σzz diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 07cab26..5082b07 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -20,16 +20,20 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound nt = model.nt # Wrap sources and receivers arrays - srccoeij_xx = [backend.Data.Array(srccoeij_xx[i]) for i in eachindex(srccoeij_xx)] - srccoeval_xx = [backend.Data.Array(srccoeval_xx[i]) for i in eachindex(srccoeval_xx)] - srccoeij_xz = [backend.Data.Array(srccoeij_xz[i]) for i in eachindex(srccoeij_xz)] - srccoeval_xz = [backend.Data.Array(srccoeval_xz[i]) for i in eachindex(srccoeval_xz)] - reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] - reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] - reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] - reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] - + nsrcs = size(shot.srcs.positions, 1) + nrecs = size(shot.recs.positions, 1) + srccoeij_xx = [backend.Data.Array( srccoeij_xx[i]) for i in 1:nsrcs] + srccoeval_xx = [backend.Data.Array(srccoeval_xx[i]) for i in 1:nsrcs] + srccoeij_xz = [backend.Data.Array( srccoeij_xz[i]) for i in 1:nsrcs] + srccoeval_xz = [backend.Data.Array(srccoeval_xz[i]) for i in 1:nsrcs] + reccoeij_vx = [backend.Data.Array( reccoeij_vx[i]) for i in 1:nrecs] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in 1:nrecs] + reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) + reduced_buf = zeros(T, nrecs) + traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] + traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) ## ONLY 2D for now!!! @@ -53,6 +57,9 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, it, Mxx_bk, Mzz_bk, Mxz_bk; @@ -102,16 +109,20 @@ end nt = model.nt # Wrap sources and receivers arrays - srccoeij_vx = [backend.Data.Array(srccoeij_vx[i]) for i in eachindex(srccoeij_vx)] - srccoeval_vx = [backend.Data.Array(srccoeval_vx[i]) for i in eachindex(srccoeval_vx)] - srccoeij_vz = [backend.Data.Array(srccoeij_vz[i]) for i in eachindex(srccoeij_vz)] - srccoeval_vz = [backend.Data.Array(srccoeval_vz[i]) for i in eachindex(srccoeval_vz)] - reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] - reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] - reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] - reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] - + nsrcs = size(shot.srcs.positions, 1) + nrecs = size(shot.recs.positions, 1) + srccoeij_vx = [backend.Data.Array( srccoeij_vx[i]) for i in 1:nsrcs] + srccoeval_vx = [backend.Data.Array(srccoeval_vx[i]) for i in 1:nsrcs] + srccoeij_vz = [backend.Data.Array( srccoeij_vz[i]) for i in 1:nsrcs] + srccoeval_vz = [backend.Data.Array(srccoeval_vz[i]) for i in 1:nsrcs] + reccoeij_vx = [backend.Data.Array( reccoeij_vx[i]) for i in 1:nrecs] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in 1:nrecs] + reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) + reduced_buf = zeros(T, nrecs) + traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] + traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) # Reset wavesim @@ -130,6 +141,9 @@ end reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, it; save_trace=true) diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index 9a6924f..3c695a7 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -22,16 +22,20 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = # Numerics nt = model.nt # Wrap sources and receivers arrays - srccoeij_xx = [backend.Data.Array(srccoeij_xx[i]) for i in eachindex(srccoeij_xx)] - srccoeval_xx = [backend.Data.Array(srccoeval_xx[i]) for i in eachindex(srccoeval_xx)] - srccoeij_xz = [backend.Data.Array(srccoeij_xz[i]) for i in eachindex(srccoeij_xz)] - srccoeval_xz = [backend.Data.Array(srccoeval_xz[i]) for i in eachindex(srccoeval_xz)] - reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] - reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] - reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] - reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] - + nsrcs = size(shot.srcs.positions, 1) + nrecs = size(shot.recs.positions, 1) + srccoeij_xx = [backend.Data.Array( srccoeij_xx[i]) for i in 1:nsrcs] + srccoeval_xx = [backend.Data.Array(srccoeval_xx[i]) for i in 1:nsrcs] + srccoeij_xz = [backend.Data.Array( srccoeij_xz[i]) for i in 1:nsrcs] + srccoeval_xz = [backend.Data.Array(srccoeval_xz[i]) for i in 1:nsrcs] + reccoeij_vx = [backend.Data.Array( reccoeij_vx[i]) for i in 1:nrecs] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in 1:nrecs] + reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) + reduced_buf = zeros(T, nrecs) + traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] + traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) ## ONLY 2D for now!!! @@ -57,6 +61,9 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, it, Mxx_bk, Mzz_bk, Mxz_bk; @@ -131,6 +138,9 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, recit, Mxx_bk, Mzz_bk, Mxz_bk; @@ -189,16 +199,20 @@ end # Numerics nt = model.nt # Wrap sources and receivers arrays - srccoeij_vx = [backend.Data.Array(srccoeij_vx[i]) for i in eachindex(srccoeij_vx)] - srccoeval_vx = [backend.Data.Array(srccoeval_vx[i]) for i in eachindex(srccoeval_vx)] - srccoeij_vz = [backend.Data.Array(srccoeij_vz[i]) for i in eachindex(srccoeij_vz)] - srccoeval_vz = [backend.Data.Array(srccoeval_vz[i]) for i in eachindex(srccoeval_vz)] - reccoeij_vx = [backend.Data.Array(reccoeij_vx[i]) for i in eachindex(reccoeij_vx)] - reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in eachindex(reccoeval_vx)] - reccoeij_vz = [backend.Data.Array(reccoeij_vz[i]) for i in eachindex(reccoeij_vz)] - reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in eachindex(reccoeval_vz)] - + nsrcs = size(shot.srcs.positions, 1) + nrecs = size(shot.recs.positions, 1) + srccoeij_vx = [backend.Data.Array( srccoeij_vx[i]) for i in 1:nsrcs] + srccoeval_vx = [backend.Data.Array(srccoeval_vx[i]) for i in 1:nsrcs] + srccoeij_vz = [backend.Data.Array( srccoeij_vz[i]) for i in 1:nsrcs] + srccoeval_vz = [backend.Data.Array(srccoeval_vz[i]) for i in 1:nsrcs] + reccoeij_vx = [backend.Data.Array( reccoeij_vx[i]) for i in 1:nrecs] + reccoeval_vx = [backend.Data.Array(reccoeval_vx[i]) for i in 1:nrecs] + reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] + reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) + reduced_buf = zeros(T, nrecs) + traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] + traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) # Reset wavesim @@ -218,6 +232,9 @@ end reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, it; save_trace=true @@ -291,6 +308,9 @@ end reccoeij_vz, reccoeval_vz, srctf_bk, + reduced_buf, + traces_vx_bk_buf, + traces_vz_bk_buf, traces_bk, recit; save_trace=false From 059ee127d616da179dc273b2e364c096c5e06eb8 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 24 Oct 2024 15:57:25 +0200 Subject: [PATCH 086/111] Refactor receiver recording to improve performance --- .../backends/shared/elastic2D_iso_xPU.jl | 56 ++++++++----------- src/models/elastic/ela_forward.jl | 4 +- src/models/elastic/ela_gradient.jl | 4 +- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index f15ef19..524c899 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -318,16 +318,16 @@ function forward_onestep_CPML!( nrecs = size(reccoeij_vx, 1) for r in 1:nrecs nrecspts_vx = size(reccoeij_vx[r], 1) - @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_vx_bk_buf[r], reccoeij_vx[r], reccoeval_vx[r]) - reduced_buf[r] = reduce(+, traces_vx_bk_buf[r]) - end - copyto!(@view(traces_bk[it, 1, :]), reduced_buf) - for r in 1:nrecs nrecspts_vz = size(reccoeij_vz[r], 1) + @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_vx_bk_buf[r], reccoeij_vx[r], reccoeval_vx[r]) @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_vz_bk_buf[r], reccoeij_vz[r], reccoeval_vz[r]) - reduced_buf[r] = reduce(+, traces_vz_bk_buf[r]) + Base.mapreducedim!(identity, +, @view(reduced_buf[1][r:r]), traces_vx_bk_buf[r]) + Base.mapreducedim!(identity, +, @view(reduced_buf[2][r:r]), traces_vz_bk_buf[r]) end - copyto!(@view(traces_bk[it, 2, :]), reduced_buf) + copyto!(@view(traces_bk[it, 1, :]), reduced_buf[1]) + copyto!(@view(traces_bk[it, 2, :]), reduced_buf[2]) + reduced_buf[1] .= 0.0 + reduced_buf[2] .= 0.0 end # update stresses σxx and σzz @@ -338,14 +338,11 @@ function forward_onestep_CPML!( ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # inject sources (moment tensor type of internal force) - nrecs_xx = size(srccoeij_xx, 1) - nrecs_xz = size(srccoeij_xz, 1) - for s in 1:nrecs_xx + nsrcs = size(srccoeij_xx, 1) + for s in 1:nsrcs nsrcpts_xx = size(srccoeij_xx[s], 1) - @parallel (1:nsrcpts_xx) inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx_bk, Mzz_bk, srctf_bk, srccoeij_xx[s], srccoeval_xx[s], it, s, dt) - end - for s in 1:nrecs_xz nsrcpts_xz = size(srccoeij_xz[s], 1) + @parallel (1:nsrcpts_xx) inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx_bk, Mzz_bk, srctf_bk, srccoeij_xx[s], srccoeval_xx[s], it, s, dt) @parallel (1:nsrcpts_xz) inject_momten_sources2D_σxz!(σxz, Mxz_bk, srctf_bk, srccoeij_xz[s], srccoeval_xz[s], it, s, dt) end @@ -416,32 +413,28 @@ function forward_onestep_CPML!( ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) # inject sources - nsrcs_vx = size(srccoeij_vx, 1) - nsrcs_vz = size(srccoeij_vz, 1) - for s in 1:nsrcs_vx + nsrcs = size(srccoeij_vx, 1) + for s in 1:nsrcs nsrcpts_vx = size(srccoeij_vx[s], 1) - @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) - end - for s in 1:nsrcs_vz nsrcpts_vz = size(srccoeij_vz[s], 1) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, srctf_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, srctf_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_jhalf, it, s, dt) end - # record receivers if save_trace nrecs = size(reccoeij_vx, 1) for r in 1:nrecs nrecspts_vx = size(reccoeij_vx[r], 1) - @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_vx_bk_buf[r], reccoeij_vx[r], reccoeval_vx[r]) - reduced_buf[r] = reduce(+, traces_vx_bk_buf[r]) - end - copyto!(@view(traces_bk[it, 1, :]), reduced_buf) - for r in 1:nrecs nrecspts_vz = size(reccoeij_vz[r], 1) + @parallel (1:nrecspts_vx) record_receivers2D_vx!(vx, traces_vx_bk_buf[r], reccoeij_vx[r], reccoeval_vx[r]) @parallel (1:nrecspts_vz) record_receivers2D_vz!(vz, traces_vz_bk_buf[r], reccoeij_vz[r], reccoeval_vz[r]) - reduced_buf[r] = reduce(+, traces_vz_bk_buf[r]) + Base.mapreducedim!(identity, +, @view(reduced_buf[1][r:r]), traces_vx_bk_buf[r]) + Base.mapreducedim!(identity, +, @view(reduced_buf[2][r:r]), traces_vz_bk_buf[r]) end - copyto!(@view(traces_bk[it, 2, :]), reduced_buf) + copyto!(@view(traces_bk[it, 1, :]), reduced_buf[1]) + copyto!(@view(traces_bk[it, 2, :]), reduced_buf[2]) + reduced_buf[1] .= 0.0 + reduced_buf[2] .= 0.0 end # update stresses σxx and σzz @@ -516,14 +509,11 @@ function adjoint_onestep_CPML!( ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) # inject sources (residuals as velocities) - nsrcs_vx = size(srccoeij_vx, 1) - nsrcs_vz = size(srccoeij_vz, 1) - for s in 1:nsrcs_vx + nsrcs = size(srccoeij_vx, 1) + for s in 1:nsrcs nsrcpts_vx = size(srccoeij_vx[s], 1) - @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, residuals_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) - end - for s in 1:nsrcs_vz nsrcpts_vz = size(srccoeij_vz[s], 1) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, residuals_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, residuals_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_jhalf, it, s, dt) end diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 5082b07..28989ba 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -31,7 +31,7 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) - reduced_buf = zeros(T, nrecs) + reduced_buf = [backend.zeros(T, nrecs), backend.zeros(T, nrecs)] traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) @@ -120,7 +120,7 @@ end reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) - reduced_buf = zeros(T, nrecs) + reduced_buf = [backend.zeros(T, nrecs), backend.zeros(T, nrecs)] traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index 3c695a7..27efacb 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -33,7 +33,7 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) - reduced_buf = zeros(T, nrecs) + reduced_buf = [backend.zeros(T, nrecs), backend.zeros(T, nrecs)] traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) @@ -210,7 +210,7 @@ end reccoeij_vz = [backend.Data.Array( reccoeij_vz[i]) for i in 1:nrecs] reccoeval_vz = [backend.Data.Array(reccoeval_vz[i]) for i in 1:nrecs] srctf_bk = backend.Data.Array(scal_srctf) - reduced_buf = zeros(T, nrecs) + reduced_buf = [backend.zeros(T, nrecs), backend.zeros(T, nrecs)] traces_vx_bk_buf = [backend.zeros(T, size(reccoeij_vx[i], 1)) for i in 1:nrecs] traces_vz_bk_buf = [backend.zeros(T, size(reccoeij_vz[i], 1)) for i in 1:nrecs] traces_bk = backend.zeros(T, size(shot.recs.seismograms)) From 39e48e2029055ed12d3521def6ee78204cd4bf99 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 28 Oct 2024 15:28:51 +0100 Subject: [PATCH 087/111] Implement correct adjoint solver elasic 2D iso P-SV --- .../backends/shared/elastic2D_iso_xPU.jl | 229 ++++++++++++++---- src/models/elastic/ela_models.jl | 28 ++- 2 files changed, 215 insertions(+), 42 deletions(-) diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 524c899..3161ff3 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -50,24 +50,50 @@ return nothing end +@parallel_indices (i, j) function update_4thord_adjvx!( + nx, nz, halo, adjvx, factx, factz, adjσxx, adjσzz, adjσxz, dt, ρ_ihalf, λ_ihalf, μ_ihalf, + adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) + + ∂σxx∂x = (-adjσxx[i+2, j] + 27 * adjσxx[i+1, j] - 27 * adjσxx[i, j ] + adjσxx[i-1, j]) * factx + ∂σzz∂x = (-adjσzz[i+2, j] + 27 * adjσzz[i+1, j] - 27 * adjσzz[i, j ] + adjσzz[i-1, j]) * factx + ∂σxz∂z = (-adjσxz[i, j+1] + 27 * adjσxz[i, j ] - 27 * adjσxz[i, j-1] + adjσxz[i, j-2]) * factz + + ### CPML ### + if i <= halo + 1 + # left boundary + adjψ_∂σxx∂x[i, j] = b_x_half[i] * adjψ_∂σxx∂x[i, j] + a_x_half[i] * ∂σxx∂x + adjψ_∂σzz∂x[i, j] = b_x_half[i] * adjψ_∂σzz∂x[i, j] + a_x_half[i] * ∂σzz∂x + ∂σxx∂x += adjψ_∂σxx∂x[i, j] + ∂σzz∂x += adjψ_∂σzz∂x[i, j] + elseif i >= nx - halo - 1 + # right boundary + ii = i - (nx - halo - 1) + 1 + (halo + 1) + adjψ_∂σxx∂x[ii, j] = b_x_half[ii] * adjψ_∂σxx∂x[ii, j] + a_x_half[ii] * ∂σxx∂x + adjψ_∂σzz∂x[ii, j] = b_x_half[ii] * adjψ_∂σzz∂x[ii, j] + a_x_half[ii] * ∂σzz∂x + ∂σxx∂x += adjψ_∂σxx∂x[ii, j] + ∂σzz∂x += adjψ_∂σzz∂x[ii, j] + end + if j >= 2 && j <= halo + 1 && freetop == false + # top boundary + adjψ_∂σxz∂z[i, j-1] = b_z[j-1] * adjψ_∂σxz∂z[i, j-1] + a_z[j-1] * ∂σxz∂z + ∂σxz∂z += adjψ_∂σxz∂z[i, j-1] + elseif j >= nz - halo + # bottom boundary + jj = j - (nz - halo) + 2 + (halo) + adjψ_∂σxz∂z[i, jj-1] = b_z[jj-1] * adjψ_∂σxz∂z[i, jj-1] + a_z[jj-1] * ∂σxz∂z + ∂σxz∂z += adjψ_∂σxz∂z[i, jj-1] + end + ############ + + adjvx[i, j] += dt * (((λ_ihalf[i, j] + 2*μ_ihalf[i, j]) / ρ_ihalf[i, j]) * ∂σxx∂x + (λ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σzz∂x + (μ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σxz∂z) + # adjvx[i, j] += dt * (∂σxx∂x + ∂σzz∂x + ∂σxz∂z) + + return nothing +end + @parallel_indices (i, j) function update_4thord_vz!( - nx, - nz, - halo, - vz, - factx, - factz, - σxz, - σzz, - dt, - ρ_jhalf, - ψ_∂σxz∂x, - ψ_∂σzz∂z, - b_x, - b_z_half, - a_x, - a_z_half, - freetop) + nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, + ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) if freetop && j == 1 # just half step below the free surface # mirroring stress at the top boundary @@ -110,6 +136,47 @@ end return nothing end +@parallel_indices (i, j) function update_4thord_adjvz!( + nx, nz, halo, adjvz, factx, factz, adjσxx, adjσzz, adjσxz, dt, ρ_jhalf, λ_jhalf, μ_jhalf, + adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, b_x, b_z_half, a_x, a_z_half, freetop) + + ∂σxx∂z = (-adjσxx[i, j+2] + 27 * adjσxx[i, j+1] - 27 * adjσxx[i, j ] + adjσxx[i, j-1]) * factz + ∂σzz∂z = (-adjσzz[i, j+2] + 27 * adjσzz[i, j+1] - 27 * adjσzz[i, j ] + adjσzz[i, j-1]) * factz + ∂σxz∂x = (-adjσxz[i+1, j] + 27 * adjσxz[i, j ] - 27 * adjσxz[i-1, j] + adjσxz[i-2, j]) * factx + + ### CPML ### + if i <= halo + 1 + # left boundary + adjψ_∂σxz∂x[i-1, j] = b_x[i-1] * adjψ_∂σxz∂x[i-1, j] + a_x[i-1] * ∂σxz∂x + ∂σxz∂x += adjψ_∂σxz∂x[i-1, j] + elseif i >= nx - halo + # right boundary + ii = i - (nx - halo) + 2 + (halo) + adjψ_∂σxz∂x[ii-1, j] = b_x[ii-1] * adjψ_∂σxz∂x[ii-1, j] + a_x[ii-1] * ∂σxz∂x + ∂σxz∂x += adjψ_∂σxz∂x[ii-1, j] + end + if j <= halo + 1 && freetop == false + # top boundary + adjψ_∂σxx∂z[i, j] = b_z_half[j] * adjψ_∂σxx∂z[i, j] + a_z_half[j] * ∂σxx∂z + adjψ_∂σzz∂z[i, j] = b_z_half[j] * adjψ_∂σzz∂z[i, j] + a_z_half[j] * ∂σzz∂z + ∂σxx∂z += adjψ_∂σxx∂z[i, j] + ∂σzz∂z += adjψ_∂σzz∂z[i, j] + elseif j >= nz - halo + # bottom boundary + jj = j - (nz - halo) + 2 + (halo + 1) + adjψ_∂σxx∂z[i, jj] = b_z_half[jj] * adjψ_∂σxx∂z[i, jj] + a_z_half[jj] * ∂σxx∂z + adjψ_∂σzz∂z[i, jj] = b_z_half[jj] * adjψ_∂σzz∂z[i, jj] + a_z_half[jj] * ∂σzz∂z + ∂σxx∂z += adjψ_∂σxx∂z[i, jj] + ∂σzz∂z += adjψ_∂σzz∂z[i, jj] + end + ############ + + adjvz[i, j] += dt * (((λ_jhalf[i, j] + 2*μ_jhalf[i, j]) / ρ_jhalf[i, j]) * ∂σzz∂z + (λ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxx∂z + (μ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxz∂x) + # adjvz[i, j] += dt * (∂σxx∂z + ∂σzz∂z + ∂σxz∂x) + + return nothing +end + @parallel_indices (i, j) function update_4thord_σxxσzz!( nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ, μ, ψ_∂vx∂x, ψ_∂vz∂z, @@ -165,6 +232,44 @@ end return nothing end +@parallel_indices (i, j) function update_4thord_adjσxxσzz!( + nx, nz, halo, adjσxx, adjσzz, factx, factz, + adjvx, adjvz, dt, adjψ_∂vx∂x, adjψ_∂vz∂z, + b_x, b_z, a_x, a_z, freetop) + + ∂vx∂x = (-adjvx[i+1, j] + 27 * adjvx[i, j] - 27 * adjvx[i-1, j] + adjvx[i-2, j]) * factx + ∂vz∂z = (-adjvz[i, j+1] + 27 * adjvz[i, j] - 27 * adjvz[i, j-1] + adjvz[i, j-2]) * factz + + ### CPML ### + if i <= halo + 1 + # left boundary + adjψ_∂vx∂x[i-1, j] = b_x[i-1] * adjψ_∂vx∂x[i-1, j] + a_x[i-1] * ∂vx∂x + ∂vx∂x += adjψ_∂vx∂x[i-1, j] + elseif i >= nx - halo + # right boundary + ii = i - (nx - halo) + 2 + (halo) + adjψ_∂vx∂x[ii-1, j] = b_x[ii-1] * adjψ_∂vx∂x[ii-1, j] + a_x[ii-1] * ∂vx∂x + ∂vx∂x += adjψ_∂vx∂x[ii-1, j] + end + if j <= halo + 1 && freetop == false + # top boundary + adjψ_∂vz∂z[i, j-1] = b_z[j-1] * adjψ_∂vz∂z[i, j-1] + a_z[j-1] * ∂vz∂z + ∂vz∂z += adjψ_∂vz∂z[i, j-1] + elseif j >= nz - halo + # bottom boundary + jj = j - (nz - halo) + 2 + (halo) + adjψ_∂vz∂z[i, jj-1] = b_z[jj-1] * adjψ_∂vz∂z[i, jj-1] + a_z[jj-1] * ∂vz∂z + ∂vz∂z += adjψ_∂vz∂z[i, jj-1] + end + ############ + + # update stresses + adjσxx[i, j] += dt * ∂vx∂x + adjσzz[i, j] += dt * ∂vz∂z + + return nothing +end + @parallel_indices (i, j) function update_4thord_σxz!( nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) @@ -208,6 +313,41 @@ end return nothing end +@parallel_indices (i, j) function update_4thord_adjσxz!( + nx, nz, halo, adjσxz, factx, factz, adjvx, adjvz, dt, + adjψ_∂vx∂z, adjψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + + ∂vx∂z = (-adjvx[i, j+2] + 27 * adjvx[i, j+1] - 27 * adjvx[i, j] + adjvx[i, j-1]) * factz + ∂vz∂x = (-adjvz[i+2, j] + 27 * adjvz[i+1, j] - 27 * adjvz[i, j] + adjvz[i-1, j]) * factx + + ### CPML ### + if i <= halo + 1 + # left boundary + adjψ_∂vz∂x[i, j] = b_x_half[i] * adjψ_∂vz∂x[i, j] + a_x_half[i] * ∂vz∂x + ∂vz∂x += adjψ_∂vz∂x[i, j] + elseif i >= nx - halo - 1 + # right boundary + ii = i - (nx - halo - 1) + 1 + (halo + 1) + adjψ_∂vz∂x[ii, j] = b_x_half[ii] * adjψ_∂vz∂x[ii, j] + a_x_half[ii] * ∂vz∂x + ∂vz∂x += adjψ_∂vz∂x[ii, j] + end + if j <= halo + 1 && freetop == false + # top boundary + adjψ_∂vx∂z[i, j] = b_z_half[j] * adjψ_∂vx∂z[i, j] + a_z_half[j] * ∂vx∂z + ∂vx∂z += adjψ_∂vx∂z[i, j] + elseif j >= nz - halo - 1 + # bottom boundary + jj = j - (nz - halo - 1) + 1 + (halo + 1) + adjψ_∂vx∂z[i, jj] = b_z_half[jj] * adjψ_∂vx∂z[i, jj] + a_z_half[jj] * ∂vx∂z + ∂vx∂z += adjψ_∂vx∂z[i, jj] + end + ############ + + adjσxz[i, j] += dt * (∂vx∂z + ∂vz∂x) + + return nothing +end + @parallel_indices (p) function inject_momten_sources2D_σxx_σzz!(σxx, σzz, Mxx, Mzz, srctf_bk, srccoeij_bk, srccoeval_bk, it, s, dt) isrc, jsrc = srccoeij_bk[p, 1], srccoeij_bk[p, 2] σxx[isrc, jsrc] += Mxx[s] * srccoeval_bk[p] * srctf_bk[it, s] * dt @@ -466,13 +606,13 @@ function adjoint_onestep_CPML!( halo = model.cpmlparams.halo grid = model.grid - vx, vz = grid.fields["adjv"].value - σxx, σzz, σxz = grid.fields["adjσ"].value + adjvx, adjvz = grid.fields["adjv"].value + adjσxx, adjσzz, adjσxz = grid.fields["adjσ"].value - ψ_∂σxx∂x, ψ_∂σxz∂x = grid.fields["adjψ_∂σ∂x"].value - ψ_∂σzz∂z, ψ_∂σxz∂z = grid.fields["adjψ_∂σ∂z"].value - ψ_∂vx∂x, ψ_∂vz∂x = grid.fields["adjψ_∂v∂x"].value - ψ_∂vx∂z, ψ_∂vz∂z = grid.fields["adjψ_∂v∂z"].value + adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂x = grid.fields["adjψ_∂σ∂x"].value + adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂z = grid.fields["adjψ_∂σ∂z"].value + adjψ_∂vx∂x, adjψ_∂vz∂x = grid.fields["adjψ_∂v∂x"].value + adjψ_∂vx∂z, adjψ_∂vz∂z = grid.fields["adjψ_∂v∂z"].value a_x = cpmlcoeffs[1].a a_x_half = cpmlcoeffs[1].a_h @@ -484,37 +624,44 @@ function adjoint_onestep_CPML!( b_z = cpmlcoeffs[2].b b_z_half = cpmlcoeffs[2].b_h - λ = grid.fields["λ"].value - μ = grid.fields["μ"].value ρ_ihalf = grid.fields["ρ_ihalf"].value ρ_jhalf = grid.fields["ρ_jhalf"].value - μ_ihalf_jhalf = grid.fields["μ_ihalf_jhalf"].value + λ_ihalf = grid.fields["λ_ihalf"].value + λ_jhalf = grid.fields["λ_jhalf"].value + μ_ihalf = grid.fields["μ_ihalf"].value + μ_jhalf = grid.fields["μ_jhalf"].value # Precomputing divisions factx = 1.0 / (24.0 * dx) factz = 1.0 / (24.0 * dz) - # update stresses σxx and σzz - @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ, μ, - ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) - # update stress σxz - @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, - ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) - - # update velocity vx - @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, - ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) - # update velocity vz - @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, - ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) + # update adjoint stresses σxx and σzz + @parallel (3:nx-2, 3:nz-2) update_4thord_adjσxxσzz!(nx, nz, halo, adjσxx, adjσzz, factx, factz, + adjvx, adjvz, dt, adjψ_∂vx∂x, adjψ_∂vz∂z, + b_x, b_z, a_x, a_z, freetop) + # update adjoint stress σxz + @parallel (2:nx-2, 2:nz-2) update_4thord_adjσxz!(nx, nz, halo, adjσxz, factx, factz, + adjvx, adjvz, dt, adjψ_∂vx∂z, adjψ_∂vz∂x, + b_x_half, b_z_half, a_x_half, a_z_half, freetop) + + # update adjoint velocity vx + @parallel (2:nx-2, 3:nz-2) update_4thord_adjvx!(nx, nz, halo, adjvx, factx, factz, + adjσxx, adjσzz, adjσxz, dt, ρ_ihalf, λ_ihalf, μ_ihalf, + adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, + b_x_half, b_z, a_x_half, a_z, freetop) + # update adjoint velocity vz + @parallel (3:nx-2, 2:nz-2) update_4thord_adjvz!(nx, nz, halo, adjvz, factx, factz, + adjσxx, adjσzz, adjσxz, dt, ρ_jhalf, λ_jhalf, μ_jhalf, + adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, + b_x, b_z_half, a_x, a_z_half, freetop) # inject sources (residuals as velocities) nsrcs = size(srccoeij_vx, 1) for s in 1:nsrcs nsrcpts_vx = size(srccoeij_vx[s], 1) nsrcpts_vz = size(srccoeij_vz[s], 1) - @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(vx, residuals_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) - @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(vz, residuals_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_jhalf, it, s, dt) + @parallel (1:nsrcpts_vx) inject_external_sources2D_vx!(adjvx, residuals_bk, srccoeij_vx[s], srccoeval_vx[s], ρ_ihalf, it, s, dt) + @parallel (1:nsrcpts_vz) inject_external_sources2D_vz!(adjvz, residuals_bk, srccoeij_vz[s], srccoeval_vz[s], ρ_jhalf, it, s, dt) end return diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index cc9c999..833b4e5 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -137,6 +137,17 @@ function precomp_elaprop!(model::ElasticIsoWaveSimulation{T, 2}) where {T} copyto!(ρ_ihalf, interp(model.matprop.interp_method_ρ, model.matprop.ρ, 1)) copyto!(ρ_jhalf, interp(model.matprop.interp_method_ρ, model.matprop.ρ, 2)) copyto!(μ_ihalf_jhalf, interp(model.matprop.interp_method_μ, model.matprop.μ, [1, 2])) + if model.checkpointer !== nothing + # Interpolated material properties for adjoint evolution + λ_ihalf = model.grid.fields["λ_ihalf"].value + λ_jhalf = model.grid.fields["λ_jhalf"].value + μ_ihalf = model.grid.fields["μ_ihalf"].value + μ_jhalf = model.grid.fields["μ_jhalf"].value + copyto!(λ_ihalf, interp(model.matprop.interp_method_λ, model.matprop.λ, 1)) + copyto!(λ_jhalf, interp(model.matprop.interp_method_λ, model.matprop.λ, 2)) + copyto!(μ_ihalf, interp(model.matprop.interp_method_μ, model.matprop.μ, 1)) + copyto!(μ_jhalf, interp(model.matprop.interp_method_μ, model.matprop.μ, 2)) + end return end @@ -260,6 +271,19 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac )) # Initialize gradient arrays if needed if gradient + # Interpolated material properties + addfield!(grid, "λ_ihalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- [1, 0])...) + )) + addfield!(grid, "λ_jhalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- [0, 1])...) + )) + addfield!(grid, "μ_ihalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- [1, 0])...) + )) + addfield!(grid, "μ_jhalf" => ScalarVariableField( + backend.zeros(T, (gridsize .- [0, 1])...) + )) # Stress and velocity addfield!(grid, "adjσ" => MultiVariableField( [ @@ -278,11 +302,13 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac addfield!(grid, "adjψ_∂σ∂x" => MultiVariableField( [ backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂σxx∂x + backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂σzz∂x backend.zeros(T, 2halo , gridsize[2]-1) # ψ_∂σxz∂x ] )) addfield!(grid, "adjψ_∂σ∂z" => MultiVariableField( [ + backend.zeros(T, gridsize[1] , 2(halo+1)), # ψ_∂σxx∂z backend.zeros(T, gridsize[1] , 2(halo+1)), # ψ_∂σzz∂z backend.zeros(T, gridsize[1]-1, 2halo ) # ψ_∂σxz∂z ] @@ -392,7 +418,7 @@ end @views function reset!(model::ElasticIsoCPMLWaveSimulation{T, N}) where {T, N} # Reset computational arrays - reset!(model.grid; except=["λ", "μ", "ρ_ihalf", "ρ_jhalf", "μ_ihalf_jhalf"]) + reset!(model.grid; except=["λ", "μ", "ρ_ihalf", "ρ_jhalf", "λ_ihalf", "λ_jhalf", "μ_ihalf", "μ_jhalf", "μ_ihalf_jhalf"]) if model.checkpointer !== nothing reset!(model.checkpointer) end From 12a3ef02ac4b927f7459558941a00ce14580a669 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 20 Nov 2024 14:47:18 +0100 Subject: [PATCH 088/111] Add module FiniteDifferencesMacros and use them to refactor elastic 2D P-SV --- src/SeismicWaves.jl | 5 + .../backends/Elastic2D_Iso_CPML_AMDGPU.jl | 3 +- .../backends/Elastic2D_Iso_CPML_CUDA.jl | 3 +- .../backends/Elastic2D_Iso_CPML_Threads.jl | 3 +- .../backends/shared/correlate_gradient_xPU.jl | 41 +--- .../backends/shared/elastic2D_iso_xPU.jl | 224 ++++++++---------- .../fourth_order_FiniteDifferences2D.jl | 7 - src/utils/fdgen.jl | 171 +++++++++++++ 8 files changed, 291 insertions(+), 166 deletions(-) delete mode 100644 src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl create mode 100644 src/utils/fdgen.jl diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index ba7c3d3..df3206b 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -29,6 +29,11 @@ export build_wavesim, swforward!, swmisfit!, swgradient! # source time functions export gaussstf, gaussderivstf, rickerstf +module FiniteDifferencesMacros + include("utils/fdgen.jl") + export @∂, @∂², @∂ⁿ, @∇, @∇², @∇ⁿ, @div, @∂x, @∂y, @∂z, @∂²x, @∂²y, @∂²z, @∂ⁿx, @∂ⁿy, @∂ⁿz +end + include("utils/abstract_types.jl") # Traits diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl index df745e3..6b30bd3 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl @@ -4,10 +4,11 @@ using AMDGPU using ParallelStencil using ParallelStencil.FiniteDifferences2D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = AMDGPU, ndims = 2, inbounds = false) include("shared/standard_xPU.jl") -include("shared/fourth_order_FiniteDifferences2D.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl index 4037ccc..82da12b 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl @@ -4,10 +4,11 @@ using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences2D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = CUDA, ndims = 2, inbounds = false) include("shared/standard_xPU.jl") -include("shared/fourth_order_FiniteDifferences2D.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl index 075efcf..732c94e 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl @@ -3,10 +3,11 @@ module Elastic2D_Iso_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences2D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = Threads, ndims = 2, inbounds = false) include("shared/standard_xPU.jl") -include("shared/fourth_order_FiniteDifferences2D.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") diff --git a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl index fb40bf5..04b78a4 100644 --- a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl +++ b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl @@ -4,22 +4,14 @@ return nothing end -@parallel_indices (i, j) function correlate_gradient_λ_μ_kernel!(grad_λ, grad_μ, adjσxx, adjσzz, vx, vz, λ, μ, factx, factz, freetop) - ∂vx∂x = 0.0 - ∂vz∂z = 0.0 +@parallel_indices (i, j) function correlate_gradient_λ_μ_kernel!(grad_λ, grad_μ, adjσxx, adjσzz, vx, vz, λ, μ, _dx, _dz, freetop) + # compute derivatives + ∂vx∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true vx if freetop && j == 1 - # on the free surface, σzz = 0 - ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx - # using boundary condition to calculate ∂vz∂z + # on the free surface, using boundary condition to calculate ∂vz∂z ∂vz∂z = -(λ[i, j] / (λ[i, j] + 2*μ[i, j])) * ∂vx∂x - elseif freetop && j == 2 - # just below the free surface - ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx - # zero velocity above the free surface - ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + 0.0) * factz - elseif j >= 3 - ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx - ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + vz[i, j-2]) * factz + else + ∂vz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true vz end # correlate grad_λ[i, j] += (-(∂vx∂x + ∂vz∂z) * (adjσxx[i, j] + adjσzz[i, j])) @@ -28,19 +20,12 @@ end return nothing end -@parallel_indices (i, j) function correlate_gradient_μ_ihalf_jhalf_kernel!(grad_μ_ihalf_jhalf, adjσxz, vx, vz, factx, factz, freetop) - ∂vx∂z = 0.0 - ∂vz∂x = 0.0 - if freetop && j == 1 - # zero velocity above the free surface - ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + 0.0 ) * factz - ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx - elseif j >= 2 - ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + vx[i, j-1]) * factz - ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx - end +@parallel_indices (i, j) function correlate_gradient_μ_ihalf_jhalf_kernel!(grad_μ_ihalf_jhalf, adjσxz, vx, vz, _dx, _dz, freetop) + # compute derivatives + ∂vx∂z = @∂y order=4 I=(i,j) _Δ=_dz bdcheck=true vx + ∂vz∂x = @∂x order=4 I=(i,j) _Δ=_dx bdcheck=true vz # correlate - grad_μ_ihalf_jhalf[i, j] += -(∂vx∂z+∂vz∂x) * adjσxz[i, j] + grad_μ_ihalf_jhalf[i, j] += -(∂vx∂z + ∂vz∂x) * adjσxz[i, j] return nothing end @@ -69,14 +54,14 @@ end vcurr..., grid.fields["λ"].value, grid.fields["μ"].value, - (1.0 ./ (24.0 .* grid.spacing))..., + (1.0 ./ grid.spacing)..., freetop ) @parallel (2:nx-2, 1:nz-2) correlate_gradient_μ_ihalf_jhalf_kernel!( grid.fields["grad_μ_ihalf_jhalf"].value, grid.fields["adjσ"].value[3], vcurr..., - (1.0 ./ (24.0 .* grid.spacing))..., + (1.0 ./ grid.spacing)..., freetop ) end \ No newline at end of file diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 3161ff3..c512bb9 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -1,25 +1,12 @@ @parallel_indices (i, j) function update_4thord_vx!( - nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, + nx, nz, halo, vx, _dx, _dz, σxx, σxz, dt, ρ_ihalf, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) - if freetop && j == 1 - # on the free surface - ∂σxx∂x = (-σxx[i+2, j] + 27 * σxx[i+1, j] - 27 * σxx[i, j] + σxx[i-1, j]) * factx - # mirroring stresses at the top boundary - σxz_top = -σxz[i, j] - σxz_toptop = -σxz[i, j+1] - ∂σxz∂z = (-σxz[i, j+1] + 27 * σxz[i, j] - 27 * σxz_top + σxz_toptop) * factz - elseif freetop && j == 2 - # just below the free surface - ∂σxx∂x = (-σxx[i+2, j] + 27 * σxx[i+1, j] - 27 * σxx[i, j] + σxx[i-1, j]) * factx - # mirroring stress at the top boundary - σxz_top = -σxz[i, j+1] - ∂σxz∂z = (-σxz[i, j+1] + 27 * σxz[i, j] - 27 * σxz[i, j-1] + σxz_top) * factz - elseif j >= 3 - ∂σxx∂x = (-σxx[i+2, j] + 27 * σxx[i+1, j] - 27 * σxx[i, j ] + σxx[i-1, j]) * factx - ∂σxz∂z = (-σxz[i, j+1] + 27 * σxz[i, j ] - 27 * σxz[i, j-1] + σxz[i, j-2]) * factz + + ∂σxx∂x = @∂x order=4 I=(i,j ) _Δ=_dx bdcheck=true σxx + if freetop + ∂σxz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true mirror=(true, false) σxz else - ∂σxx∂x = 0.0 - ∂σxz∂z = 0.0 + ∂σxz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true σxz end ### CPML ### @@ -51,12 +38,12 @@ end @parallel_indices (i, j) function update_4thord_adjvx!( - nx, nz, halo, adjvx, factx, factz, adjσxx, adjσzz, adjσxz, dt, ρ_ihalf, λ_ihalf, μ_ihalf, + nx, nz, halo, adjvx, _dx, _dz, adjσxx, adjσzz, adjσxz, dt, ρ_ihalf, λ_ihalf, μ_ihalf, adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) - ∂σxx∂x = (-adjσxx[i+2, j] + 27 * adjσxx[i+1, j] - 27 * adjσxx[i, j ] + adjσxx[i-1, j]) * factx - ∂σzz∂x = (-adjσzz[i+2, j] + 27 * adjσzz[i+1, j] - 27 * adjσzz[i, j ] + adjσzz[i-1, j]) * factx - ∂σxz∂z = (-adjσxz[i, j+1] + 27 * adjσxz[i, j ] - 27 * adjσxz[i, j-1] + adjσxz[i, j-2]) * factz + ∂σxx∂x = @∂x order=4 I=(i,j ) _Δ=_dx bdcheck=true adjσxx + ∂σzz∂x = @∂x order=4 I=(i,j ) _Δ=_dx bdcheck=true adjσzz + ∂σxz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true adjσxz ### CPML ### if i <= halo + 1 @@ -85,31 +72,26 @@ end end ############ - adjvx[i, j] += dt * (((λ_ihalf[i, j] + 2*μ_ihalf[i, j]) / ρ_ihalf[i, j]) * ∂σxx∂x + (λ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σzz∂x + (μ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σxz∂z) - # adjvx[i, j] += dt * (∂σxx∂x + ∂σzz∂x + ∂σxz∂z) + adjvx[i, j] += dt * (((λ_ihalf[i, j] + 2*μ_ihalf[i, j]) / ρ_ihalf[i, j]) * ∂σxx∂x + + ( λ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σzz∂x + + ( μ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σxz∂z) return nothing end @parallel_indices (i, j) function update_4thord_vz!( - nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, + nx, nz, halo, vz, _dx, _dz, σxz, σzz, dt, ρ_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) - if freetop && j == 1 - # just half step below the free surface - # mirroring stress at the top boundary - σzz_top = -σzz[i, j+2] - ∂σzz∂z = (-σzz[i, j+2] + 27 * σzz[i, j+1] - 27 * σzz[i, j] + σzz_top) * factz - ∂σxz∂x = (-σxz[i+1, j] + 27 * σxz[i, j] - 27 * σxz[i-1, j] + σxz[i-2, j]) * factx - elseif j >= 2 - ∂σzz∂z = (-σzz[i, j+2] + 27 * σzz[i, j+1] - 27 * σzz[i, j] + σzz[i, j-1]) * factz - ∂σxz∂x = (-σxz[i+1, j] + 27 * σxz[i, j] - 27 * σxz[i-1, j] + σxz[i-2, j]) * factx + + ∂σxz∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true σxz + if freetop + ∂σzz∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true mirror=(true, false) σzz else - ∂σzz∂z = 0.0 - ∂σxz∂x = 0.0 + ∂σzz∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true σzz end ### CPML ### - if i <= halo + 1 + if i >= 2 && i <= halo + 1 # left boundary ψ_∂σxz∂x[i-1, j] = b_x[i-1] * ψ_∂σxz∂x[i-1, j] + a_x[i-1] * ∂σxz∂x ∂σxz∂x += ψ_∂σxz∂x[i-1, j] @@ -137,15 +119,15 @@ end end @parallel_indices (i, j) function update_4thord_adjvz!( - nx, nz, halo, adjvz, factx, factz, adjσxx, adjσzz, adjσxz, dt, ρ_jhalf, λ_jhalf, μ_jhalf, + nx, nz, halo, adjvz, _dx, _dz, adjσxx, adjσzz, adjσxz, dt, ρ_jhalf, λ_jhalf, μ_jhalf, adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, b_x, b_z_half, a_x, a_z_half, freetop) - ∂σxx∂z = (-adjσxx[i, j+2] + 27 * adjσxx[i, j+1] - 27 * adjσxx[i, j ] + adjσxx[i, j-1]) * factz - ∂σzz∂z = (-adjσzz[i, j+2] + 27 * adjσzz[i, j+1] - 27 * adjσzz[i, j ] + adjσzz[i, j-1]) * factz - ∂σxz∂x = (-adjσxz[i+1, j] + 27 * adjσxz[i, j ] - 27 * adjσxz[i-1, j] + adjσxz[i-2, j]) * factx - + ∂σxx∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true adjσxx + ∂σzz∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true adjσzz + ∂σxz∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true adjσxz + ### CPML ### - if i <= halo + 1 + if i >= 2 && i <= halo + 1 # left boundary adjψ_∂σxz∂x[i-1, j] = b_x[i-1] * adjψ_∂σxz∂x[i-1, j] + a_x[i-1] * ∂σxz∂x ∂σxz∂x += adjψ_∂σxz∂x[i-1, j] @@ -171,61 +153,55 @@ end end ############ - adjvz[i, j] += dt * (((λ_jhalf[i, j] + 2*μ_jhalf[i, j]) / ρ_jhalf[i, j]) * ∂σzz∂z + (λ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxx∂z + (μ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxz∂x) - # adjvz[i, j] += dt * (∂σxx∂z + ∂σzz∂z + ∂σxz∂x) + adjvz[i, j] += dt * (((λ_jhalf[i, j] + 2*μ_jhalf[i, j]) / ρ_jhalf[i, j]) * ∂σzz∂z + + ( λ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxx∂z + + ( μ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxz∂x) return nothing end @parallel_indices (i, j) function update_4thord_σxxσzz!( - nx, nz, halo, σxx, σzz, factx, factz, + nx, nz, halo, σxx, σzz, _dx, _dz, vx, vz, dt, λ, μ, ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) + + ∂vx∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true vx if freetop && j == 1 - # on the free surface, σzz = 0 - ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx - # using boundary condition to calculate ∂vz∂z + # on the free surface, using boundary condition to calculate ∂vz∂z ∂vz∂z = -(λ[i, j] / (λ[i, j] + 2*μ[i, j])) * ∂vx∂x - # update stresses - σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) - σzz[i, j] = 0.0 - elseif freetop && j == 2 - # just below the free surface - ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx - # zero velocity above the free surface - ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + 0.0) * factz - # update stresses - σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) - σzz[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vz∂z + λ[i, j] * ∂vx∂x) - elseif j >= 3 - ∂vx∂x = (-vx[i+1, j] + 27 * vx[i, j] - 27 * vx[i-1, j] + vx[i-2, j]) * factx - ∂vz∂z = (-vz[i, j+1] + 27 * vz[i, j] - 27 * vz[i, j-1] + vz[i, j-2]) * factz - - ### CPML ### - if i <= halo + 1 - # left boundary - ψ_∂vx∂x[i-1, j] = b_x[i-1] * ψ_∂vx∂x[i-1, j] + a_x[i-1] * ∂vx∂x - ∂vx∂x += ψ_∂vx∂x[i-1, j] - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 + (halo) - ψ_∂vx∂x[ii-1, j] = b_x[ii-1] * ψ_∂vx∂x[ii-1, j] + a_x[ii-1] * ∂vx∂x - ∂vx∂x += ψ_∂vx∂x[ii-1, j] - end - if j <= halo + 1 && freetop == false - # top boundary - ψ_∂vz∂z[i, j-1] = b_z[j-1] * ψ_∂vz∂z[i, j-1] + a_z[j-1] * ∂vz∂z - ∂vz∂z += ψ_∂vz∂z[i, j-1] - elseif j >= nz - halo - # bottom boundary - jj = j - (nz - halo) + 2 + (halo) - ψ_∂vz∂z[i, jj-1] = b_z[jj-1] * ψ_∂vz∂z[i, jj-1] + a_z[jj-1] * ∂vz∂z - ∂vz∂z += ψ_∂vz∂z[i, jj-1] - end - ############ + else + ∂vz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true vz + end - # update stresses - σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) + ### CPML ### + if i >= 2 && i <= halo + 1 + # left boundary + ψ_∂vx∂x[i-1, j] = b_x[i-1] * ψ_∂vx∂x[i-1, j] + a_x[i-1] * ∂vx∂x + ∂vx∂x += ψ_∂vx∂x[i-1, j] + elseif i >= nx - halo + # right boundary + ii = i - (nx - halo) + 2 + (halo) + ψ_∂vx∂x[ii-1, j] = b_x[ii-1] * ψ_∂vx∂x[ii-1, j] + a_x[ii-1] * ∂vx∂x + ∂vx∂x += ψ_∂vx∂x[ii-1, j] + end + if j >= 2 && j <= halo + 1 && freetop == false + # top boundary + ψ_∂vz∂z[i, j-1] = b_z[j-1] * ψ_∂vz∂z[i, j-1] + a_z[j-1] * ∂vz∂z + ∂vz∂z += ψ_∂vz∂z[i, j-1] + elseif j >= nz - halo + # bottom boundary + jj = j - (nz - halo) + 2 + (halo) + ψ_∂vz∂z[i, jj-1] = b_z[jj-1] * ψ_∂vz∂z[i, jj-1] + a_z[jj-1] * ∂vz∂z + ∂vz∂z += ψ_∂vz∂z[i, jj-1] + end + ############ + + # update stresses + σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) + if freetop && j == 1 + # on the free surface, σzz = 0 + σzz[i, j] = 0.0 + else σzz[i, j] += dt * ( λ[i, j] * ∂vx∂x + (λ[i, j] + 2*μ[i, j]) * ∂vz∂z) end @@ -233,15 +209,15 @@ end end @parallel_indices (i, j) function update_4thord_adjσxxσzz!( - nx, nz, halo, adjσxx, adjσzz, factx, factz, + nx, nz, halo, adjσxx, adjσzz, _dx, _dz, adjvx, adjvz, dt, adjψ_∂vx∂x, adjψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) - - ∂vx∂x = (-adjvx[i+1, j] + 27 * adjvx[i, j] - 27 * adjvx[i-1, j] + adjvx[i-2, j]) * factx - ∂vz∂z = (-adjvz[i, j+1] + 27 * adjvz[i, j] - 27 * adjvz[i, j-1] + adjvz[i, j-2]) * factz + + ∂vx∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true adjvx + ∂vz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true adjvz ### CPML ### - if i <= halo + 1 + if i >= 2 && i <= halo + 1 # left boundary adjψ_∂vx∂x[i-1, j] = b_x[i-1] * adjψ_∂vx∂x[i-1, j] + a_x[i-1] * ∂vx∂x ∂vx∂x += adjψ_∂vx∂x[i-1, j] @@ -251,7 +227,7 @@ end adjψ_∂vx∂x[ii-1, j] = b_x[ii-1] * adjψ_∂vx∂x[ii-1, j] + a_x[ii-1] * ∂vx∂x ∂vx∂x += adjψ_∂vx∂x[ii-1, j] end - if j <= halo + 1 && freetop == false + if j >= 2 && j <= halo + 1 && freetop == false # top boundary adjψ_∂vz∂z[i, j-1] = b_z[j-1] * adjψ_∂vz∂z[i, j-1] + a_z[j-1] * ∂vz∂z ∂vz∂z += adjψ_∂vz∂z[i, j-1] @@ -271,19 +247,11 @@ end end @parallel_indices (i, j) function update_4thord_σxz!( - nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, + nx, nz, halo, σxz, _dx, _dz, vx, vz, dt, μ_ihalf_jhalf, ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) - if freetop && j == 1 - # zero velocity above the free surface - ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + 0.0 ) * factz - ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx - elseif j >= 2 - ∂vx∂z = (-vx[i, j+2] + 27 * vx[i, j+1] - 27 * vx[i, j] + vx[i, j-1]) * factz - ∂vz∂x = (-vz[i+2, j] + 27 * vz[i+1, j] - 27 * vz[i, j] + vz[i-1, j]) * factx - else - ∂vx∂z = 0.0 - ∂vz∂x = 0.0 - end + + ∂vx∂z = @∂y order=4 I=(i,j) _Δ=_dz bdcheck=true vx + ∂vz∂x = @∂x order=4 I=(i,j) _Δ=_dx bdcheck=true vz ### CPML ### if i <= halo + 1 @@ -314,11 +282,11 @@ end end @parallel_indices (i, j) function update_4thord_adjσxz!( - nx, nz, halo, adjσxz, factx, factz, adjvx, adjvz, dt, + nx, nz, halo, adjσxz, _dx, _dz, adjvx, adjvz, dt, adjψ_∂vx∂z, adjψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) - ∂vx∂z = (-adjvx[i, j+2] + 27 * adjvx[i, j+1] - 27 * adjvx[i, j] + adjvx[i, j-1]) * factz - ∂vz∂x = (-adjvz[i+2, j] + 27 * adjvz[i+1, j] - 27 * adjvz[i, j] + adjvz[i-1, j]) * factx + ∂vx∂z = @∂y order=4 I=(i,j) _Δ=_dz bdcheck=true adjvx + ∂vz∂x = @∂x order=4 I=(i,j) _Δ=_dx bdcheck=true adjvz ### CPML ### if i <= halo + 1 @@ -443,14 +411,14 @@ function forward_onestep_CPML!( μ_ihalf_jhalf = grid.fields["μ_ihalf_jhalf"].value # Precomputing divisions - factx = 1.0 / (24.0 * dx) - factz = 1.0 / (24.0 * dz) + _dx = 1.0 / dx + _dz = 1.0 / dz # update velocity vx - @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, + @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, _dx, _dz, σxx, σxz, dt, ρ_ihalf, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) # update velocity vz - @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, + @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, _dx, _dz, σxz, σzz, dt, ρ_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) # record receivers @@ -471,10 +439,10 @@ function forward_onestep_CPML!( end # update stresses σxx and σzz - @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ, μ, + @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, _dx, _dz, vx, vz, dt, λ, μ, ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) # update stress σxz - @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, + @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, _dx, _dz, vx, vz, dt, μ_ihalf_jhalf, ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # inject sources (moment tensor type of internal force) @@ -542,14 +510,14 @@ function forward_onestep_CPML!( μ_ihalf_jhalf = grid.fields["μ_ihalf_jhalf"].value # Precomputing divisions - factx = 1.0 / (24.0 * dx) - factz = 1.0 / (24.0 * dz) + _dx = 1.0 / dx + _dz = 1.0 / dz # update velocity vx - @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, factx, factz, σxx, σxz, dt, ρ_ihalf, + @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, _dx, _dz, σxx, σxz, dt, ρ_ihalf, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) # update velocity vz - @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, factx, factz, σxz, σzz, dt, ρ_jhalf, + @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, _dx, _dz, σxz, σzz, dt, ρ_jhalf, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) # inject sources @@ -578,10 +546,10 @@ function forward_onestep_CPML!( end # update stresses σxx and σzz - @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, factx, factz, vx, vz, dt, λ, μ, + @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, _dx, _dz, vx, vz, dt, λ, μ, ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) # update stress σxz - @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, factx, factz, vx, vz, dt, μ_ihalf_jhalf, + @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, _dx, _dz, vx, vz, dt, μ_ihalf_jhalf, ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) return @@ -632,25 +600,25 @@ function adjoint_onestep_CPML!( μ_jhalf = grid.fields["μ_jhalf"].value # Precomputing divisions - factx = 1.0 / (24.0 * dx) - factz = 1.0 / (24.0 * dz) + _dx = 1.0 / dx + _dz = 1.0 / dz # update adjoint stresses σxx and σzz - @parallel (3:nx-2, 3:nz-2) update_4thord_adjσxxσzz!(nx, nz, halo, adjσxx, adjσzz, factx, factz, + @parallel (3:nx-2, 3:nz-2) update_4thord_adjσxxσzz!(nx, nz, halo, adjσxx, adjσzz, _dx, _dz, adjvx, adjvz, dt, adjψ_∂vx∂x, adjψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) # update adjoint stress σxz - @parallel (2:nx-2, 2:nz-2) update_4thord_adjσxz!(nx, nz, halo, adjσxz, factx, factz, + @parallel (2:nx-2, 2:nz-2) update_4thord_adjσxz!(nx, nz, halo, adjσxz, _dx, _dz, adjvx, adjvz, dt, adjψ_∂vx∂z, adjψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) # update adjoint velocity vx - @parallel (2:nx-2, 3:nz-2) update_4thord_adjvx!(nx, nz, halo, adjvx, factx, factz, + @parallel (2:nx-2, 3:nz-2) update_4thord_adjvx!(nx, nz, halo, adjvx, _dx, _dz, adjσxx, adjσzz, adjσxz, dt, ρ_ihalf, λ_ihalf, μ_ihalf, adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) # update adjoint velocity vz - @parallel (3:nx-2, 2:nz-2) update_4thord_adjvz!(nx, nz, halo, adjvz, factx, factz, + @parallel (3:nx-2, 2:nz-2) update_4thord_adjvz!(nx, nz, halo, adjvz, _dx, _dz, adjσxx, adjσzz, adjσxz, dt, ρ_jhalf, λ_jhalf, μ_jhalf, adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, b_x, b_z_half, a_x, a_z_half, freetop) diff --git a/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl b/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl deleted file mode 100644 index 2dce407..0000000 --- a/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl +++ /dev/null @@ -1,7 +0,0 @@ -macro d_dx_4th(a, i, j) - return esc(:((-$a[$i+1, $j] + 27.0 * $a[$i, $j] - 27.0 * $a[$i-1, $j] + $a[$i-2, $j]))) -end - -macro d_dy_4th(a, i, j) - return esc(:((-$a[$i, $j+1] + 27.0 * $a[$i, $j] - 27.0 * $a[$i, $j-1] + $a[$i, $j-2]))) -end diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl new file mode 100644 index 0000000..f8df962 --- /dev/null +++ b/src/utils/fdgen.jl @@ -0,0 +1,171 @@ + +""" + fornberg(x::Vector{T}, m::Int) where {T} + +Calculate the weights of a finite difference approximation of the `m`th derivative +with maximal order of accuracy at `0` using the nodes `x`, see +Fornberg (1998) +Calculation of Weights in Finite Difference Formulas +SIAM Rev. 40.3, pp. 685-691. +""" +function fornberg(xx::Vector{T}, m::Int) where {T} + x = sort(xx) + z = zero(T) + n = length(x) - 1 + c = fill(zero(T), length(x), m+1) + c1 = one(T) + c4 = x[1] - z + c[1,1] = one(T) + for i in 1:n + mn = min(i,m) + c2 = one(T) + c5 = c4 + c4 = x[i+1] - z + for j in 0:i-1 + c3 = x[i+1] - x[j+1] + c2 = c2 * c3 + if j == i-1 + for k in mn:-1:1 + c[i+1,k+1] = c1 * (k*c[i,k]-c5*c[i,k+1]) / c2 + end + c[i+1,1] = -c1*c5*c[i,1] / c2 + end + for k in mn:-1:1 + c[j+1,k+1] = (c4*c[j+1,k+1]-k*c[j+1,k]) / c3 + end + c[j+1,1] = c4*c[j+1,1] / c3 + end + c1 = c2 + end + + c[:,end] +end + +function fdcoeffs(deriv::Int, order::Int) + nnn = order + deriv - 1 + return fornberg(collect(1:(nnn)) .- (nnn / 2 + 0.5), deriv) +end + +function fdidxs(deriv::Int, order::Int, dim::Int, I...) + N = length(I) + nnn = order + deriv - 1 + grid = collect(1:nnn) .- (nnn / 2 + 0.5) + if (deriv+order) % 2 == 1 + grid .+= 0.5 + end + grid = Int.(grid) + Is = Tuple( Tuple(i == dim && grid[j] != 0 ? :($(I[i])+$(grid[j])) : I[i] for i in 1:N) for j in 1:nnn ) + return Is +end + +function ∂ⁿ_(A, dim::Int; I=[:i], _Δ=1.0, deriv::Int=1, order::Int=2, bdcheck::Bool=false, mirror=(false, false)) + coeffs = fdcoeffs(deriv, order) + Is = fdidxs(deriv, order, dim, I...) + N = length(I) + mirror_left, mirror_right = mirror + # right boundary checks + function right_checks_recursive(coeffs, Is, A, dim, _Δ, state) + is = Tuple(Is[i][dim] for i in eachindex(Is)) + width = length(coeffs) + # elseif in the checks + if state > 1 + head = :elseif + # zero if out of boundaries + else + Aname = string(A) + return Expr(:elseif, :(size($A, $dim) < $width), :(error("Size of array (size($($Aname), $($dim)) = $(size($A, $dim))) is smaller than stancil width ($($width))")), :(0)) + end + condition = :(1 <= $(is[1]) <= $(is[state-1]) <= size($A, $dim) && $(is[state]) > size($A, $dim)) + if mirror_right + # construct the mirrored stencil + original_stencil = Expr(:call, :+, [:($(coeffs[i]) * $A[$(Is[i]...)]) for i in 1:state-1]...) # original stencil with indices up to boundary + mirrored_Is = Tuple( Tuple(i == dim ? :($(Is[state-1][i])-$(j-state)) : Is[state-1][i] for i in 1:N) for j in state:width) # indices mirrored around boundary + mirrored_stencil = Expr(:call, :+, [:($(coeffs[i]) * -$A[$(mirrored_Is[i-state+1]...)]) for i in state:width]...) # mirrored stencil with indices beyond boundary but mirrored + stencil = Expr(:call, :*, Expr(:call, :+, original_stencil, mirrored_stencil), _Δ) # sum the original and mirrored stencils + else + stencil = Expr(:call, :*, Expr(:call, :+, [:($(coeffs[i]) * $A[$(Is[i]...)]) for i in 1:state-1]...), _Δ) + end + return Expr(head, condition, stencil, right_checks_recursive(coeffs, Is, A, dim, _Δ, state-1)) # recursively construct the if-elseif-else block + end + # (left) boundary checks + function checks_recursive(coeffs, Is, A, dim, _Δ, state) + is = Tuple(Is[i][dim] for i in eachindex(Is)) + width = length(coeffs) + # first if in the checks + if state == 1 + head = :if + # elseif in the checks + elseif state < width + head = :elseif + # time to check the right boundary + else + return right_checks_recursive(coeffs, Is, A, dim, _Δ, width) + end + condition = :($(is[state]) < 1 && 1 <= $(is[state+1]) <= $(is[end]) <= size($A, $dim)) + if mirror_left + # construct the mirrored stencil + original_stencil = Expr(:call, :+, [:($(coeffs[i]) * $A[$(Is[i]...)]) for i in state+1:width]...) # original stencil with indices beyond boundary + mirrored_Is = Tuple( Tuple(i == dim ? :($(Is[state+1][i])+$(j-1)) : Is[state+1][i] for i in 1:N) for j in 1:state) # indices mirrored around boundary + mirrored_stencil = Expr(:call, :+, [:($(coeffs[i]) * -$A[$(mirrored_Is[i]...)]) for i in 1:state]...) # mirrored stencil with indices up to boundary but mirrored + stencil = Expr(:call, :*, Expr(:call, :+, mirrored_stencil, original_stencil), _Δ) # sum the original and mirrored stencils + else + stencil = Expr(:call, :*, Expr(:call, :+, [:($(coeffs[i]) * $A[$(Is[i]...)]) for i in state+1:width]...), _Δ) + end + return Expr(head, condition, stencil, checks_recursive(coeffs, Is, A, dim, _Δ, state+1)) # recursively construct the if-elseif-else block + end + # with boundary checks + if bdcheck + ileft = Is[1][dim] + iright = Is[end][dim] + expr = Expr(:if, :(1 <= $ileft && $iright <= size($A, $dim)), # if all indices inside range + Expr(:call, :*, Expr(:call, :+, [:($c * $A[$(Is[i]...)]) for (i, c) in enumerate(coeffs)]...), _Δ), # inner case derivative + Expr(:block, # else + checks_recursive(coeffs, Is, A, dim, _Δ, 1) # boundary checks + ) + ) + return expr + end + # without boundary checks + return Expr(:call, :*, Expr(:call, :+, [:($c * $A[$(Is[i]...)]) for (i, c) in enumerate(coeffs)]...), _Δ) +end + +function ∇ⁿ_(A; I=(), _Δ=(), kwargs...) + @assert length(I) == length(_Δ) + return Expr(:tuple, (∂ⁿ_(A, i; _Δ=_Δ[i], I=I, deriv=1, kwargs...) for i in eachindex(_Δ))...) +end + +function extract_kwargs(args...) + kwargs = Dict{Symbol, Any}() + positional = [] + for arg in args + if isa(arg, Expr) && arg.head == :(=) && length(arg.args) == 2 && isa(arg.args[1], Symbol) + rightarghead = isa(arg.args[2], Expr) ? arg.args[2].head : nothing + kwargs[arg.args[1]] = rightarghead == :tuple ? Tuple(arg.args[2].args) : arg.args[2] + else + push!(positional, arg) + end + end + return positional, kwargs +end + +# General partial scalar derivatives +macro ∂( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs...; kwargs..., deriv=1) ) end +macro ∂²( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs...; kwargs..., deriv=2) ) end +macro ∂ⁿ( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs...; kwargs...) ) end + +# General partial vector derivatives (gradient, divergence and Laplacian) +macro ∇( args...) posargs, kwargs = extract_kwargs(args...); esc( ∇ⁿ_(posargs...; kwargs...) ) end +macro div(args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., deriv=1).args... ) ) end +macro ∇²( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., deriv=2).args... ) ) end +macro ∇ⁿ( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., ).args... ) ) end + +# Specialized partial scalar derivatives +macro ∂x( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 1; kwargs..., deriv=1) ) end +macro ∂y( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 2; kwargs..., deriv=1) ) end +macro ∂z( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs..., deriv=1) ) end +macro ∂²x(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 1; kwargs..., deriv=2) ) end +macro ∂²y(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 2; kwargs..., deriv=2) ) end +macro ∂²z(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs..., deriv=2) ) end +macro ∂ⁿx(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 1; kwargs...) ) end +macro ∂ⁿy(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 2; kwargs...) ) end +macro ∂ⁿz(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs...) ) end \ No newline at end of file From 257c4eb8dccad64237c0b7f9c7b2979755b97a58 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 21 Nov 2024 18:01:18 +0100 Subject: [PATCH 089/111] Add macros for first derivatives with CPMLs --- src/SeismicWaves.jl | 2 +- src/models/cpmlcoeffs.jl | 67 ++- .../backends/shared/elastic2D_iso_xPU.jl | 490 ++++++++---------- src/models/elastic/ela_models.jl | 39 +- src/utils/fdgen.jl | 35 +- 5 files changed, 321 insertions(+), 312 deletions(-) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index df3206b..6410084 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -31,7 +31,7 @@ export gaussstf, gaussderivstf, rickerstf module FiniteDifferencesMacros include("utils/fdgen.jl") - export @∂, @∂², @∂ⁿ, @∇, @∇², @∇ⁿ, @div, @∂x, @∂y, @∂z, @∂²x, @∂²y, @∂²z, @∂ⁿx, @∂ⁿy, @∂ⁿz + export @∂, @∂², @∂ⁿ, @∇, @∇², @∇ⁿ, @div, @∂x, @∂y, @∂z, @∂²x, @∂²y, @∂²z, @∂ⁿx, @∂ⁿy, @∂ⁿz, @∂̃, @∂̃x, @∂̃y, @∂̃z end include("utils/abstract_types.jl") diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index 2df310a..af66e6e 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -7,10 +7,10 @@ struct CPMLCoefficientsAxis{T, V <: AbstractVector{T}} function CPMLCoefficientsAxis{T, V}(halo::Int, backend::Module) where {T, V <: AbstractVector{T}} return new{T, V}( - backend.zeros(T, 2 * halo), backend.zeros(T, 2 * (halo + 1)), backend.zeros(T, 2 * halo), - backend.zeros(T, 2 * (halo + 1)) + backend.zeros(T, 2 * (halo + 1)), + backend.zeros(T, 2 * halo) ) end end @@ -31,8 +31,8 @@ function compute_CPML_coefficientsAxis!( if halo == 0 # fix for thickness == 0 generating NaNs d0 = convert(T, 0.0) end - a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") - a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") + a_l, a_r, b_l, b_r = calc_Kab_CPML2(halo, dt, npower, d0, alpha_max, "ongrd") + a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML2(halo, dt, npower, d0, alpha_max, "halfgrd") copyto!(cpmlcoeffs.a, vcat(a_l, a_r)) copyto!(cpmlcoeffs.a_h, vcat(a_hl, a_hr)) @@ -40,6 +40,65 @@ function compute_CPML_coefficientsAxis!( copyto!(cpmlcoeffs.b_h, vcat(b_hl, b_hr)) end +function calc_Kab_CPML2( + halo::Int, + dt::T, + npower::T, + d0::T, + alpha_max_pml::T, + onwhere::String; + K_max_pml::Union{T, Nothing}=nothing +)::Tuple{Array{T}, Array{T}, Array{T}, Array{T}} where {T} + @assert halo >= 0.0 + + Kab_size = halo + # shift for half grid coefficients + if onwhere == "halfgrd" + shift = 0.5 + elseif onwhere == "ongrd" + shift = 0.0 + Kab_size += 1 + else + error("Wrong onwhere parameter!") + end + + # distance from edge node + dist = collect(LinRange(0 + shift, Kab_size + shift - 1, Kab_size)) + if halo != 0 + normdist_left = reverse(dist) ./ halo + normdist_right = dist ./ halo + else + normdist_left = reverse(dist) + normdist_right = dist + end + + if K_max_pml === nothing + K_left = 1.0 + else + K_left = 1.0 .+ (K_max_pml - 1.0) .* (normdist_left .^ npower) + end + d_left = d0 .* (normdist_left .^ npower) + alpha_left = alpha_max_pml .* (1.0 .- normdist_left) + b_left = exp.(.-(d_left ./ K_left .+ alpha_left) .* dt) + a_left = d_left .* (b_left .- 1.0) ./ (K_left .* (d_left .+ K_left .* alpha_left)) + + if K_max_pml === nothing + K_right = 1.0 + else + K_right = 1.0 .+ (K_max_pml - 1.0) .* (normdist_right .^ npower) + end + d_right = d0 .* (normdist_right .^ npower) + alpha_right = alpha_max_pml .* (1.0 .- normdist_right) + b_right = exp.(.-(d_right ./ K_right .+ alpha_right) .* dt) + a_right = d_right .* (b_right .- 1.0) ./ (K_right .* (d_right .+ K_right .* alpha_right)) + + if K_max_pml === nothing + return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right) + else + return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right), convert.(T, K_left), convert.(T, K_right) + end +end + ################################################################# struct CPMLCoefficients{T, V <: AbstractVector{T}} diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index c512bb9..6bcd7cd 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -1,205 +1,144 @@ @parallel_indices (i, j) function update_4thord_vx!( - nx, nz, halo, vx, _dx, _dz, σxx, σxz, dt, ρ_ihalf, - ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) + vx, σxx, σxz, dt, _dx, _dz, ρ_ihalf, + halo, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop +) - ∂σxx∂x = @∂x order=4 I=(i,j ) _Δ=_dx bdcheck=true σxx - if freetop - ∂σxz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true mirror=(true, false) σxz + #################################### + # ∂vx/∂t = (∂σxx/∂x + ∂σxz/∂z) / ρ # + #################################### + + # Compute partial derivatives + ∂σxx∂x = @∂̃x(σxx, a_x_half, b_x_half, ψ_∂σxx∂x, + order=4, I=(i,j), _Δ=_dx, + halo=halo, halfgrid=true) + if freetop # if free surface, mirror the top boundary + ∂σxz∂z = @∂̃y(σxz, a_z, b_z, ψ_∂σxz∂z, + order=4, I=(i,j-1), _Δ=_dz, mirror=(true, false), + halo=halo, halfgrid=false) else - ∂σxz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true σxz + ∂σxz∂z = @∂̃y(σxz, a_z, b_z, ψ_∂σxz∂z, + order=4, I=(i,j-1), _Δ=_dz, + halo=halo, halfgrid=false) end - ### CPML ### - if i <= halo + 1 - # left boundary - ψ_∂σxx∂x[i, j] = b_x_half[i] * ψ_∂σxx∂x[i, j] + a_x_half[i] * ∂σxx∂x - ∂σxx∂x += ψ_∂σxx∂x[i, j] - elseif i >= nx - halo - 1 - # right boundary - ii = i - (nx - halo - 1) + 1 + (halo + 1) - ψ_∂σxx∂x[ii, j] = b_x_half[ii] * ψ_∂σxx∂x[ii, j] + a_x_half[ii] * ∂σxx∂x - ∂σxx∂x += ψ_∂σxx∂x[ii, j] - end - if j >= 2 && j <= halo + 1 && freetop == false - # top boundary - ψ_∂σxz∂z[i, j-1] = b_z[j-1] * ψ_∂σxz∂z[i, j-1] + a_z[j-1] * ∂σxz∂z - ∂σxz∂z += ψ_∂σxz∂z[i, j-1] - elseif j >= nz - halo - # bottom boundary - jj = j - (nz - halo) + 2 + (halo) - ψ_∂σxz∂z[i, jj-1] = b_z[jj-1] * ψ_∂σxz∂z[i, jj-1] + a_z[jj-1] * ∂σxz∂z - ∂σxz∂z += ψ_∂σxz∂z[i, jj-1] - end - ############ - + # Update velocity vx[i, j] += dt * (∂σxx∂x + ∂σxz∂z) / ρ_ihalf[i, j] return nothing end @parallel_indices (i, j) function update_4thord_adjvx!( - nx, nz, halo, adjvx, _dx, _dz, adjσxx, adjσzz, adjσxz, dt, ρ_ihalf, λ_ihalf, μ_ihalf, - adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) - - ∂σxx∂x = @∂x order=4 I=(i,j ) _Δ=_dx bdcheck=true adjσxx - ∂σzz∂x = @∂x order=4 I=(i,j ) _Δ=_dx bdcheck=true adjσzz - ∂σxz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true adjσxz - - ### CPML ### - if i <= halo + 1 - # left boundary - adjψ_∂σxx∂x[i, j] = b_x_half[i] * adjψ_∂σxx∂x[i, j] + a_x_half[i] * ∂σxx∂x - adjψ_∂σzz∂x[i, j] = b_x_half[i] * adjψ_∂σzz∂x[i, j] + a_x_half[i] * ∂σzz∂x - ∂σxx∂x += adjψ_∂σxx∂x[i, j] - ∂σzz∂x += adjψ_∂σzz∂x[i, j] - elseif i >= nx - halo - 1 - # right boundary - ii = i - (nx - halo - 1) + 1 + (halo + 1) - adjψ_∂σxx∂x[ii, j] = b_x_half[ii] * adjψ_∂σxx∂x[ii, j] + a_x_half[ii] * ∂σxx∂x - adjψ_∂σzz∂x[ii, j] = b_x_half[ii] * adjψ_∂σzz∂x[ii, j] + a_x_half[ii] * ∂σzz∂x - ∂σxx∂x += adjψ_∂σxx∂x[ii, j] - ∂σzz∂x += adjψ_∂σzz∂x[ii, j] - end - if j >= 2 && j <= halo + 1 && freetop == false - # top boundary - adjψ_∂σxz∂z[i, j-1] = b_z[j-1] * adjψ_∂σxz∂z[i, j-1] + a_z[j-1] * ∂σxz∂z - ∂σxz∂z += adjψ_∂σxz∂z[i, j-1] - elseif j >= nz - halo - # bottom boundary - jj = j - (nz - halo) + 2 + (halo) - adjψ_∂σxz∂z[i, jj-1] = b_z[jj-1] * adjψ_∂σxz∂z[i, jj-1] + a_z[jj-1] * ∂σxz∂z - ∂σxz∂z += adjψ_∂σxz∂z[i, jj-1] - end - ############ + adjvx, adjσxx, adjσzz, adjσxz, dt, _dx, _dz, ρ_ihalf, λ_ihalf, μ_ihalf, + halo, adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z +) - adjvx[i, j] += dt * (((λ_ihalf[i, j] + 2*μ_ihalf[i, j]) / ρ_ihalf[i, j]) * ∂σxx∂x + - ( λ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σzz∂x + - ( μ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂σxz∂z) + ############################################################################### + # ∂adjvx/∂t = ((λ + 2μ)/ρ * ∂adjσxx/∂x + λ/ρ * ∂adjσzz/∂x + μ/ρ * ∂adjσxz/∂z) # + ############################################################################### + + # Compute partial derivatives + ∂adjσxx∂x = @∂̃x(adjσxx, a_x_half, b_x_half, adjψ_∂σxx∂x, + order=4, I=(i,j), _Δ=_dx, + halo=halo, halfgrid=true) + ∂adjσzz∂x = @∂̃x(adjσzz, a_x_half, b_x_half, adjψ_∂σzz∂x, + order=4, I=(i,j), _Δ=_dx, + halo=halo, halfgrid=true) + ∂adjσxz∂z = @∂̃y(adjσxz, a_z, b_z, adjψ_∂σxz∂z, + order=4, I=(i,j-1), _Δ=_dz, + halo=halo, halfgrid=false) + + # Update adjoint velocity + adjvx[i, j] += dt * (((λ_ihalf[i, j] + 2*μ_ihalf[i, j]) / ρ_ihalf[i, j]) * ∂adjσxx∂x + + ( λ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂adjσzz∂x + + ( μ_ihalf[i, j] / ρ_ihalf[i, j]) * ∂adjσxz∂z) return nothing end @parallel_indices (i, j) function update_4thord_vz!( - nx, nz, halo, vz, _dx, _dz, σxz, σzz, dt, ρ_jhalf, - ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) + vz, σxz, σzz, dt, _dx, _dz, ρ_jhalf, + halo, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop +) - ∂σxz∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true σxz - if freetop - ∂σzz∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true mirror=(true, false) σzz + #################################### + # ∂vz/∂t = (∂σzz/∂z + ∂σxz/∂x) / ρ # + #################################### + + # Compute partial derivatives + ∂σxz∂x = @∂̃x(σxz, a_x, b_x, ψ_∂σxz∂x, + order=4, I=(i-1,j), _Δ=_dx, + halo=halo, halfgrid=false) + if freetop # if free surface, mirror the top boundary + ∂σzz∂z = @∂̃y(σzz, a_z_half, b_z_half, ψ_∂σzz∂z, + order=4, I=(i,j), _Δ=_dz, mirror=(true, false), + halo=halo, halfgrid=true) else - ∂σzz∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true σzz + ∂σzz∂z = @∂̃y(σzz, a_z_half, b_z_half, ψ_∂σzz∂z, + order=4, I=(i,j), _Δ=_dz, + halo=halo, halfgrid=true) end - ### CPML ### - if i >= 2 && i <= halo + 1 - # left boundary - ψ_∂σxz∂x[i-1, j] = b_x[i-1] * ψ_∂σxz∂x[i-1, j] + a_x[i-1] * ∂σxz∂x - ∂σxz∂x += ψ_∂σxz∂x[i-1, j] - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 + (halo) - ψ_∂σxz∂x[ii-1, j] = b_x[ii-1] * ψ_∂σxz∂x[ii-1, j] + a_x[ii-1] * ∂σxz∂x - ∂σxz∂x += ψ_∂σxz∂x[ii-1, j] - end - if j <= halo + 1 && freetop == false - # top boundary - ψ_∂σzz∂z[i, j] = b_z_half[j] * ψ_∂σzz∂z[i, j] + a_z_half[j] * ∂σzz∂z - ∂σzz∂z += ψ_∂σzz∂z[i, j] - elseif j >= nz - halo - # bottom boundary - jj = j - (nz - halo) + 2 + (halo + 1) - ψ_∂σzz∂z[i, jj] = b_z_half[jj] * ψ_∂σzz∂z[i, jj] + a_z_half[jj] * ∂σzz∂z - ∂σzz∂z += ψ_∂σzz∂z[i, jj] - end - ############ - + # Update velocity vz[i, j] += dt * (∂σzz∂z + ∂σxz∂x) / ρ_jhalf[i, j] return nothing end @parallel_indices (i, j) function update_4thord_adjvz!( - nx, nz, halo, adjvz, _dx, _dz, adjσxx, adjσzz, adjσxz, dt, ρ_jhalf, λ_jhalf, μ_jhalf, - adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, b_x, b_z_half, a_x, a_z_half, freetop) - - ∂σxx∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true adjσxx - ∂σzz∂z = @∂y order=4 I=(i,j ) _Δ=_dz bdcheck=true adjσzz - ∂σxz∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true adjσxz - - ### CPML ### - if i >= 2 && i <= halo + 1 - # left boundary - adjψ_∂σxz∂x[i-1, j] = b_x[i-1] * adjψ_∂σxz∂x[i-1, j] + a_x[i-1] * ∂σxz∂x - ∂σxz∂x += adjψ_∂σxz∂x[i-1, j] - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 + (halo) - adjψ_∂σxz∂x[ii-1, j] = b_x[ii-1] * adjψ_∂σxz∂x[ii-1, j] + a_x[ii-1] * ∂σxz∂x - ∂σxz∂x += adjψ_∂σxz∂x[ii-1, j] - end - if j <= halo + 1 && freetop == false - # top boundary - adjψ_∂σxx∂z[i, j] = b_z_half[j] * adjψ_∂σxx∂z[i, j] + a_z_half[j] * ∂σxx∂z - adjψ_∂σzz∂z[i, j] = b_z_half[j] * adjψ_∂σzz∂z[i, j] + a_z_half[j] * ∂σzz∂z - ∂σxx∂z += adjψ_∂σxx∂z[i, j] - ∂σzz∂z += adjψ_∂σzz∂z[i, j] - elseif j >= nz - halo - # bottom boundary - jj = j - (nz - halo) + 2 + (halo + 1) - adjψ_∂σxx∂z[i, jj] = b_z_half[jj] * adjψ_∂σxx∂z[i, jj] + a_z_half[jj] * ∂σxx∂z - adjψ_∂σzz∂z[i, jj] = b_z_half[jj] * adjψ_∂σzz∂z[i, jj] + a_z_half[jj] * ∂σzz∂z - ∂σxx∂z += adjψ_∂σxx∂z[i, jj] - ∂σzz∂z += adjψ_∂σzz∂z[i, jj] - end - ############ + adjvz, adjσxx, adjσzz, adjσxz, dt, _dx, _dz, ρ_jhalf, λ_jhalf, μ_jhalf, + halo, adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, b_x, b_z_half, a_x, a_z_half +) - adjvz[i, j] += dt * (((λ_jhalf[i, j] + 2*μ_jhalf[i, j]) / ρ_jhalf[i, j]) * ∂σzz∂z + - ( λ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxx∂z + - ( μ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂σxz∂x) + ############################################################################### + # ∂adjvz/∂t = ((λ + 2μ)/ρ * ∂adjσzz/∂z + λ/ρ * ∂adjσxx/∂z + μ/ρ * ∂adjσxz/∂x) # + ############################################################################### + + # Compute partial derivatives + ∂adjσxx∂z = @∂̃y(adjσxx, a_z_half, b_z_half, adjψ_∂σxx∂z, + order=4, I=(i,j), _Δ=_dz, + halo=halo, halfgrid=true) + ∂adjσzz∂z = @∂̃y(adjσzz, a_z_half, b_z_half, adjψ_∂σzz∂z, + order=4, I=(i,j), _Δ=_dz, + halo=halo, halfgrid=true) + ∂adjσxz∂x = @∂̃x(adjσxz, a_x, b_x, adjψ_∂σxz∂x, + order=4, I=(i-1,j), _Δ=_dx, + halo=halo, halfgrid=false) + + # Update adjoint velocity + adjvz[i, j] += dt * (((λ_jhalf[i, j] + 2*μ_jhalf[i, j]) / ρ_jhalf[i, j]) * ∂adjσzz∂z + + ( λ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂adjσxx∂z + + ( μ_jhalf[i, j] / ρ_jhalf[i, j]) * ∂adjσxz∂x) return nothing end @parallel_indices (i, j) function update_4thord_σxxσzz!( - nx, nz, halo, σxx, σzz, _dx, _dz, - vx, vz, dt, λ, μ, ψ_∂vx∂x, ψ_∂vz∂z, - b_x, b_z, a_x, a_z, freetop) + σxx, σzz, vx, vz, dt, _dx, _dz, λ, μ, + halo, ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop +) - ∂vx∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true vx - if freetop && j == 1 - # on the free surface, using boundary condition to calculate ∂vz∂z + ############################################################ + # ∂vz/∂z = -λ/(λ + 2μ) * ∂vx/∂x if z = 0 and free surface # + # σzz = 0 if z = 0 and free surface # + # ∂σxx/∂t = ((λ + 2μ) * ∂vx/∂x + μ * ∂vz/∂z) # + # ∂σzz/∂t = (λ * ∂vx/∂x + (λ + 2μ) * ∂vz/∂z) # + ############################################################ + + # Compute partial derivatives + ∂vx∂x = @∂̃x(vx, a_x, b_x, ψ_∂vx∂x, + order=4, I=(i-1,j), _Δ=_dx, + halo=halo, halfgrid=false) + if freetop && j == 1 # on the free surface, using BDC to calculate ∂vz∂z ∂vz∂z = -(λ[i, j] / (λ[i, j] + 2*μ[i, j])) * ∂vx∂x else - ∂vz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true vz + ∂vz∂z = @∂̃y(vz, a_z, b_z, ψ_∂vz∂z, + order=4, I=(i,j-1), _Δ=_dz, + halo=halo, halfgrid=false) end - ### CPML ### - if i >= 2 && i <= halo + 1 - # left boundary - ψ_∂vx∂x[i-1, j] = b_x[i-1] * ψ_∂vx∂x[i-1, j] + a_x[i-1] * ∂vx∂x - ∂vx∂x += ψ_∂vx∂x[i-1, j] - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 + (halo) - ψ_∂vx∂x[ii-1, j] = b_x[ii-1] * ψ_∂vx∂x[ii-1, j] + a_x[ii-1] * ∂vx∂x - ∂vx∂x += ψ_∂vx∂x[ii-1, j] - end - if j >= 2 && j <= halo + 1 && freetop == false - # top boundary - ψ_∂vz∂z[i, j-1] = b_z[j-1] * ψ_∂vz∂z[i, j-1] + a_z[j-1] * ∂vz∂z - ∂vz∂z += ψ_∂vz∂z[i, j-1] - elseif j >= nz - halo - # bottom boundary - jj = j - (nz - halo) + 2 + (halo) - ψ_∂vz∂z[i, jj-1] = b_z[jj-1] * ψ_∂vz∂z[i, jj-1] + a_z[jj-1] * ∂vz∂z - ∂vz∂z += ψ_∂vz∂z[i, jj-1] - end - ############ - - # update stresses + # Update stresses σxx[i, j] += dt * ((λ[i, j] + 2*μ[i, j]) * ∂vx∂x + λ[i, j] * ∂vz∂z) - if freetop && j == 1 - # on the free surface, σzz = 0 + if freetop && j == 1 # on the free surface, σzz = 0 σzz[i, j] = 0.0 else σzz[i, j] += dt * ( λ[i, j] * ∂vx∂x + (λ[i, j] + 2*μ[i, j]) * ∂vz∂z) @@ -209,109 +148,72 @@ end end @parallel_indices (i, j) function update_4thord_adjσxxσzz!( - nx, nz, halo, adjσxx, adjσzz, _dx, _dz, - adjvx, adjvz, dt, adjψ_∂vx∂x, adjψ_∂vz∂z, - b_x, b_z, a_x, a_z, freetop) - - ∂vx∂x = @∂x order=4 I=(i-1,j) _Δ=_dx bdcheck=true adjvx - ∂vz∂z = @∂y order=4 I=(i,j-1) _Δ=_dz bdcheck=true adjvz - - ### CPML ### - if i >= 2 && i <= halo + 1 - # left boundary - adjψ_∂vx∂x[i-1, j] = b_x[i-1] * adjψ_∂vx∂x[i-1, j] + a_x[i-1] * ∂vx∂x - ∂vx∂x += adjψ_∂vx∂x[i-1, j] - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 + (halo) - adjψ_∂vx∂x[ii-1, j] = b_x[ii-1] * adjψ_∂vx∂x[ii-1, j] + a_x[ii-1] * ∂vx∂x - ∂vx∂x += adjψ_∂vx∂x[ii-1, j] - end - if j >= 2 && j <= halo + 1 && freetop == false - # top boundary - adjψ_∂vz∂z[i, j-1] = b_z[j-1] * adjψ_∂vz∂z[i, j-1] + a_z[j-1] * ∂vz∂z - ∂vz∂z += adjψ_∂vz∂z[i, j-1] - elseif j >= nz - halo - # bottom boundary - jj = j - (nz - halo) + 2 + (halo) - adjψ_∂vz∂z[i, jj-1] = b_z[jj-1] * adjψ_∂vz∂z[i, jj-1] + a_z[jj-1] * ∂vz∂z - ∂vz∂z += adjψ_∂vz∂z[i, jj-1] - end - ############ + adjσxx, adjσzz, adjvx, adjvz, dt, _dx, _dz, + halo, adjψ_∂vx∂x, adjψ_∂vz∂z, b_x, b_z, a_x, a_z +) - # update stresses - adjσxx[i, j] += dt * ∂vx∂x - adjσzz[i, j] += dt * ∂vz∂z + ########################## + # ∂adjσxx/∂t = ∂adjvx/∂x # + # ∂adjσzz/∂t = ∂adjvz/∂z # + ########################## + + # Compute partial derivatives + ∂adjvx∂x = @∂̃x(adjvx, a_x, b_x, adjψ_∂vx∂x, + order=4, I=(i-1,j), _Δ=_dx, + halo=halo, halfgrid=false) + ∂adjvz∂z = @∂̃y(adjvz, a_z, b_z, adjψ_∂vz∂z, + order=4, I=(i,j-1), _Δ=_dz, + halo=halo, halfgrid=false) + + # Update adjoint stresses + adjσxx[i, j] += dt * ∂adjvx∂x + adjσzz[i, j] += dt * ∂adjvz∂z return nothing end @parallel_indices (i, j) function update_4thord_σxz!( - nx, nz, halo, σxz, _dx, _dz, vx, vz, dt, μ_ihalf_jhalf, - ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) - - ∂vx∂z = @∂y order=4 I=(i,j) _Δ=_dz bdcheck=true vx - ∂vz∂x = @∂x order=4 I=(i,j) _Δ=_dx bdcheck=true vz - - ### CPML ### - if i <= halo + 1 - # left boundary - ψ_∂vz∂x[i, j] = b_x_half[i] * ψ_∂vz∂x[i, j] + a_x_half[i] * ∂vz∂x - ∂vz∂x += ψ_∂vz∂x[i, j] - elseif i >= nx - halo - 1 - # right boundary - ii = i - (nx - halo - 1) + 1 + (halo + 1) - ψ_∂vz∂x[ii, j] = b_x_half[ii] * ψ_∂vz∂x[ii, j] + a_x_half[ii] * ∂vz∂x - ∂vz∂x += ψ_∂vz∂x[ii, j] - end - if j <= halo + 1 && freetop == false - # top boundary - ψ_∂vx∂z[i, j] = b_z_half[j] * ψ_∂vx∂z[i, j] + a_z_half[j] * ∂vx∂z - ∂vx∂z += ψ_∂vx∂z[i, j] - elseif j >= nz - halo - 1 - # bottom boundary - jj = j - (nz - halo - 1) + 1 + (halo + 1) - ψ_∂vx∂z[i, jj] = b_z_half[jj] * ψ_∂vx∂z[i, jj] + a_z_half[jj] * ∂vx∂z - ∂vx∂z += ψ_∂vx∂z[i, jj] - end - ############ + σxz, vx, vz, dt, _dx, _dz, μ_ihalf_jhalf, + halo, ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half +) + + #################################### + # ∂σxz/∂t = μ * (∂vx/∂z + ∂vz/∂x) # + #################################### + # Compute partial derivatives + ∂vx∂z = @∂̃y(vx, a_z_half, b_z_half, ψ_∂vx∂z, + order=4, I=(i,j), _Δ=_dz, + halo=halo, halfgrid=true) + ∂vz∂x = @∂̃x(vz, a_x_half, b_x_half, ψ_∂vz∂x, + order=4, I=(i,j), _Δ=_dx, + halo=halo, halfgrid=true) + + # Update stress σxz[i, j] += dt * μ_ihalf_jhalf[i, j] * (∂vx∂z + ∂vz∂x) return nothing end @parallel_indices (i, j) function update_4thord_adjσxz!( - nx, nz, halo, adjσxz, _dx, _dz, adjvx, adjvz, dt, - adjψ_∂vx∂z, adjψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) - - ∂vx∂z = @∂y order=4 I=(i,j) _Δ=_dz bdcheck=true adjvx - ∂vz∂x = @∂x order=4 I=(i,j) _Δ=_dx bdcheck=true adjvz - - ### CPML ### - if i <= halo + 1 - # left boundary - adjψ_∂vz∂x[i, j] = b_x_half[i] * adjψ_∂vz∂x[i, j] + a_x_half[i] * ∂vz∂x - ∂vz∂x += adjψ_∂vz∂x[i, j] - elseif i >= nx - halo - 1 - # right boundary - ii = i - (nx - halo - 1) + 1 + (halo + 1) - adjψ_∂vz∂x[ii, j] = b_x_half[ii] * adjψ_∂vz∂x[ii, j] + a_x_half[ii] * ∂vz∂x - ∂vz∂x += adjψ_∂vz∂x[ii, j] - end - if j <= halo + 1 && freetop == false - # top boundary - adjψ_∂vx∂z[i, j] = b_z_half[j] * adjψ_∂vx∂z[i, j] + a_z_half[j] * ∂vx∂z - ∂vx∂z += adjψ_∂vx∂z[i, j] - elseif j >= nz - halo - 1 - # bottom boundary - jj = j - (nz - halo - 1) + 1 + (halo + 1) - adjψ_∂vx∂z[i, jj] = b_z_half[jj] * adjψ_∂vx∂z[i, jj] + a_z_half[jj] * ∂vx∂z - ∂vx∂z += adjψ_∂vx∂z[i, jj] - end - ############ + adjσxz, adjvx, adjvz, dt, _dx, _dz, + halo, adjψ_∂vx∂z, adjψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half +) + + ###################################### + # ∂adjσxz/∂t = ∂adjvx/∂z + ∂adjvz/∂x # + ###################################### + + # Compute partial derivatives + ∂adjvx∂z = @∂̃y(adjvx, a_z_half, b_z_half, adjψ_∂vx∂z, + order=4, I=(i,j), _Δ=_dz, + halo=halo, halfgrid=true) + ∂adjvz∂x = @∂̃x(adjvz, a_x_half, b_x_half, adjψ_∂vz∂x, + order=4, I=(i,j), _Δ=_dx, + halo=halo, halfgrid=true) - adjσxz[i, j] += dt * (∂vx∂z + ∂vz∂x) + # Update adjoint stress + adjσxz[i, j] += dt * (∂adjvx∂z + ∂adjvz∂x) return nothing end @@ -415,11 +317,15 @@ function forward_onestep_CPML!( _dz = 1.0 / dz # update velocity vx - @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, _dx, _dz, σxx, σxz, dt, ρ_ihalf, - ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) + @parallel (1:nx-1, 1:nz) update_4thord_vx!( + vx, σxx, σxz, dt, _dx, _dz, ρ_ihalf, + halo, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop + ) # update velocity vz - @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, _dx, _dz, σxz, σzz, dt, ρ_jhalf, - ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) + @parallel (1:nx, 1:nz-1) update_4thord_vz!( + vz, σxz, σzz, dt, _dx, _dz, ρ_jhalf, + halo, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop + ) # record receivers if save_trace @@ -438,12 +344,17 @@ function forward_onestep_CPML!( reduced_buf[2] .= 0.0 end - # update stresses σxx and σzz - @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, _dx, _dz, vx, vz, dt, λ, μ, - ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) + # update stresses σxx and σzz + idxzσxx = freetop ? (1:nz-1) : (2:nz-1) + @parallel (2:nx-1, idxzσxx) update_4thord_σxxσzz!( + σxx, σzz, vx, vz, dt, _dx, _dz, λ, μ, + halo, ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop + ) # update stress σxz - @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, _dx, _dz, vx, vz, dt, μ_ihalf_jhalf, - ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + @parallel (1:nx-1, 1:nz-1) update_4thord_σxz!( + σxz, vx, vz, dt, _dx, _dz, μ_ihalf_jhalf, + halo, ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half + ) # inject sources (moment tensor type of internal force) nsrcs = size(srccoeij_xx, 1) @@ -514,11 +425,15 @@ function forward_onestep_CPML!( _dz = 1.0 / dz # update velocity vx - @parallel (2:nx-2, 1:nz-2) update_4thord_vx!(nx, nz, halo, vx, _dx, _dz, σxx, σxz, dt, ρ_ihalf, - ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop) + @parallel (1:nx-1, 1:nz) update_4thord_vx!( + vx, σxx, σxz, dt, _dx, _dz, ρ_ihalf, + halo, ψ_∂σxx∂x, ψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z, freetop + ) # update velocity vz - @parallel (3:nx-2, 1:nz-2) update_4thord_vz!(nx, nz, halo, vz, _dx, _dz, σxz, σzz, dt, ρ_jhalf, - ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop) + @parallel (1:nx, 1:nz-1) update_4thord_vz!( + vz, σxz, σzz, dt, _dx, _dz, ρ_jhalf, + halo, ψ_∂σxz∂x, ψ_∂σzz∂z, b_x, b_z_half, a_x, a_z_half, freetop + ) # inject sources nsrcs = size(srccoeij_vx, 1) @@ -545,12 +460,17 @@ function forward_onestep_CPML!( reduced_buf[2] .= 0.0 end - # update stresses σxx and σzz - @parallel (3:nx-2, 1:nz-2) update_4thord_σxxσzz!(nx, nz, halo, σxx, σzz, _dx, _dz, vx, vz, dt, λ, μ, - ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop) + # update stresses σxx and σzz + idxzσxx = freetop ? (1:nz-2) : (2:nz-1) + @parallel (2:nx-1, idxzσxx) update_4thord_σxxσzz!( + σxx, σzz, vx, vz, dt, _dx, _dz, λ, μ, + halo, ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop + ) # update stress σxz - @parallel (2:nx-2, 1:nz-2) update_4thord_σxz!(nx, nz, halo, σxz, _dx, _dz, vx, vz, dt, μ_ihalf_jhalf, - ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half, freetop) + @parallel (1:nx-1, 1:nz-1) update_4thord_σxz!( + σxz, vx, vz, dt, _dx, _dz, μ_ihalf_jhalf, + halo, ψ_∂vx∂z, ψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half + ) return end @@ -604,24 +524,26 @@ function adjoint_onestep_CPML!( _dz = 1.0 / dz # update adjoint stresses σxx and σzz - @parallel (3:nx-2, 3:nz-2) update_4thord_adjσxxσzz!(nx, nz, halo, adjσxx, adjσzz, _dx, _dz, - adjvx, adjvz, dt, adjψ_∂vx∂x, adjψ_∂vz∂z, - b_x, b_z, a_x, a_z, freetop) + @parallel (1:nx-1, 1:nz-1) update_4thord_adjσxxσzz!( + adjσxx, adjσzz, adjvx, adjvz, dt, _dx, _dz, + halo, adjψ_∂vx∂x, adjψ_∂vz∂z, b_x, b_z, a_x, a_z + ) # update adjoint stress σxz - @parallel (2:nx-2, 2:nz-2) update_4thord_adjσxz!(nx, nz, halo, adjσxz, _dx, _dz, - adjvx, adjvz, dt, adjψ_∂vx∂z, adjψ_∂vz∂x, - b_x_half, b_z_half, a_x_half, a_z_half, freetop) + @parallel (1:nx-1, 1:nz-1) update_4thord_adjσxz!( + adjσxz, adjvx, adjvz, dt, _dx, _dz, + halo, adjψ_∂vx∂z, adjψ_∂vz∂x, b_x_half, b_z_half, a_x_half, a_z_half + ) # update adjoint velocity vx - @parallel (2:nx-2, 3:nz-2) update_4thord_adjvx!(nx, nz, halo, adjvx, _dx, _dz, - adjσxx, adjσzz, adjσxz, dt, ρ_ihalf, λ_ihalf, μ_ihalf, - adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, - b_x_half, b_z, a_x_half, a_z, freetop) + @parallel (1:nx-1, 1:nz) update_4thord_adjvx!( + adjvx, adjσxx, adjσzz, adjσxz, dt, _dx, _dz, ρ_ihalf, λ_ihalf, μ_ihalf, + halo, adjψ_∂σxx∂x, adjψ_∂σzz∂x, adjψ_∂σxz∂z, b_x_half, b_z, a_x_half, a_z + ) # update adjoint velocity vz - @parallel (3:nx-2, 2:nz-2) update_4thord_adjvz!(nx, nz, halo, adjvz, _dx, _dz, - adjσxx, adjσzz, adjσxz, dt, ρ_jhalf, λ_jhalf, μ_jhalf, - adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, - b_x, b_z_half, a_x, a_z_half, freetop) + @parallel (1:nx, 1:nz-1) update_4thord_adjvz!( + adjvz, adjσxx, adjσzz, adjσxz, dt, _dx, _dz, ρ_jhalf, λ_jhalf, μ_jhalf, + halo, adjψ_∂σxx∂z, adjψ_∂σzz∂z, adjψ_∂σxz∂x, b_x, b_z_half, a_x, a_z_half + ) # inject sources (residuals as velocities) nsrcs = size(srccoeij_vx, 1) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index 833b4e5..bf29d99 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -247,26 +247,26 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac # CPML memory variables addfield!(grid, "ψ_∂σ∂x" => MultiVariableField( [ - backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂σxx∂x - backend.zeros(T, 2halo , gridsize[2]-1) # ψ_∂σxz∂x + backend.zeros(T, 2halo , gridsize[2] ), # ψ_∂σxx∂x + backend.zeros(T, 2(halo+1), gridsize[2]-1) # ψ_∂σxz∂x ] )) addfield!(grid, "ψ_∂σ∂z" => MultiVariableField( [ - backend.zeros(T, gridsize[1] , 2(halo+1)), # ψ_∂σzz∂z - backend.zeros(T, gridsize[1]-1, 2halo ) # ψ_∂σxz∂z + backend.zeros(T, gridsize[1] , 2halo ), # ψ_∂σzz∂z + backend.zeros(T, gridsize[1]-1, 2(halo+1)) # ψ_∂σxz∂z ] )) addfield!(grid, "ψ_∂v∂x" => MultiVariableField( [ - backend.zeros(T, 2halo , gridsize[2] ), # ψ_∂vx∂x - backend.zeros(T, 2(halo+1), gridsize[2]-1) # ψ_∂vz∂x + backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂vx∂x + backend.zeros(T, 2halo , gridsize[2]-1) # ψ_∂vz∂x ] )) addfield!(grid, "ψ_∂v∂z" => MultiVariableField( [ - backend.zeros(T, gridsize[1]-1, 2(halo+1)), # ψ_∂vx∂z - backend.zeros(T, gridsize[1] , 2halo ) # ψ_∂vz∂z + backend.zeros(T, gridsize[1]-1, 2halo ), # ψ_∂vx∂z + backend.zeros(T, gridsize[1] , 2(halo+1)) # ψ_∂vz∂z ] )) # Initialize gradient arrays if needed @@ -301,28 +301,28 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac # CPML memory variables addfield!(grid, "adjψ_∂σ∂x" => MultiVariableField( [ - backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂σxx∂x - backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂σzz∂x - backend.zeros(T, 2halo , gridsize[2]-1) # ψ_∂σxz∂x + backend.zeros(T, 2halo , gridsize[2] ), # ψ_∂σxx∂x + backend.zeros(T, 2halo , gridsize[2] ), # ψ_∂σzz∂x + backend.zeros(T, 2(halo+1), gridsize[2]-1) # ψ_∂σxz∂x ] )) addfield!(grid, "adjψ_∂σ∂z" => MultiVariableField( [ - backend.zeros(T, gridsize[1] , 2(halo+1)), # ψ_∂σxx∂z - backend.zeros(T, gridsize[1] , 2(halo+1)), # ψ_∂σzz∂z - backend.zeros(T, gridsize[1]-1, 2halo ) # ψ_∂σxz∂z + backend.zeros(T, gridsize[1] , 2halo ), # ψ_∂σxx∂z + backend.zeros(T, gridsize[1] , 2halo ), # ψ_∂σzz∂z + backend.zeros(T, gridsize[1]-1, 2(halo+1)) # ψ_∂σxz∂z ] )) addfield!(grid, "adjψ_∂v∂x" => MultiVariableField( [ - backend.zeros(T, 2halo , gridsize[2] ), # ψ_∂vx∂x - backend.zeros(T, 2(halo+1), gridsize[2]-1) # ψ_∂vz∂x + backend.zeros(T, 2(halo+1), gridsize[2] ), # ψ_∂vx∂x + backend.zeros(T, 2halo , gridsize[2]-1) # ψ_∂vz∂x ] )) addfield!(grid, "adjψ_∂v∂z" => MultiVariableField( [ - backend.zeros(T, gridsize[1]-1, 2(halo+1)), # ψ_∂vx∂z - backend.zeros(T, gridsize[1] , 2halo ) # ψ_∂vz∂z + backend.zeros(T, gridsize[1]-1, 2halo ), # ψ_∂vx∂z + backend.zeros(T, gridsize[1] , 2(halo+1)) # ψ_∂vz∂z ] )) # Gradient arrays @@ -362,9 +362,6 @@ struct ElasticIsoCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac error("Only elastic 2D is currently implemented.") end - # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N]...) - if snapevery !== nothing # Initialize snapshotter snapshotter = LinearSnapshotter{Array{T, N}}(nt, snapevery, Dict( diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl index f8df962..8a96ece 100644 --- a/src/utils/fdgen.jl +++ b/src/utils/fdgen.jl @@ -58,10 +58,11 @@ function fdidxs(deriv::Int, order::Int, dim::Int, I...) return Is end -function ∂ⁿ_(A, dim::Int; I=[:i], _Δ=1.0, deriv::Int=1, order::Int=2, bdcheck::Bool=false, mirror=(false, false)) +function ∂ⁿ_(A, dim::Int; I=(:i,), _Δ=1.0, deriv::Int=1, order::Int=2, bdcheck::Bool=true, mirror=(false, false)) coeffs = fdcoeffs(deriv, order) Is = fdidxs(deriv, order, dim, I...) N = length(I) + @assert N > 0 "Need at least one index!" mirror_left, mirror_right = mirror # right boundary checks function right_checks_recursive(coeffs, Is, A, dim, _Δ, state) @@ -129,6 +130,30 @@ function ∂ⁿ_(A, dim::Int; I=[:i], _Δ=1.0, deriv::Int=1, order::Int=2, bdche return Expr(:call, :*, Expr(:call, :+, [:($c * $A[$(Is[i]...)]) for (i, c) in enumerate(coeffs)]...), _Δ) end +function ∂̃_(A, a, b, ψ, dim::Int; I=[:i], halo=:halo, halfgrid=true, kwargs...) + ψtemp = gensym(:ψ) + iidim = gensym(:i) + stencil = ∂ⁿ_(A, dim; I=I, deriv=1, kwargs...) + plusone = halfgrid ? 0 : 1 + idim = :( $(I[dim]) + $plusone ) + ndim = :( size($A, $dim) + $plusone ) + Iψ = [i == dim ? idim : I[i] for i in eachindex(I)] + IIψ = [i == dim ? iidim : I[i] for i in eachindex(I)] + return quote + $ψtemp = $stencil + if $idim <= ($halo + $plusone) + $ψ[$(Iψ...)] = $b[$idim ] * $ψ[$(Iψ...)] + $a[$idim ] * $ψtemp + $ψtemp + $ψ[$(Iψ...)] + elseif $idim >= $ndim - $halo + $iidim = $idim - ($ndim - $halo) + 1 + ($halo + $plusone) + $ψ[$(IIψ...)] = $b[$iidim] * $ψ[$(IIψ...)] + $a[$iidim] * $ψtemp + $ψtemp + $ψ[$(IIψ...)] + else + $ψtemp + end + end +end + function ∇ⁿ_(A; I=(), _Δ=(), kwargs...) @assert length(I) == length(_Δ) return Expr(:tuple, (∂ⁿ_(A, i; _Δ=_Δ[i], I=I, deriv=1, kwargs...) for i in eachindex(_Δ))...) @@ -168,4 +193,10 @@ macro ∂²y(args...) posargs, kwargs = extract_kwargs(args...); esc( macro ∂²z(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs..., deriv=2) ) end macro ∂ⁿx(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 1; kwargs...) ) end macro ∂ⁿy(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 2; kwargs...) ) end -macro ∂ⁿz(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs...) ) end \ No newline at end of file +macro ∂ⁿz(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs...) ) end + +# CPML partial scalar derivatives +macro ∂̃( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs...; kwargs...) ) end +macro ∂̃x( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 1; kwargs...) ) end +macro ∂̃y( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 2; kwargs...) ) end +macro ∂̃z( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 3; kwargs...) ) end \ No newline at end of file From edf5a8a5b7f9b0375838e74a1c001a046678db94 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 21 Nov 2024 19:11:21 +0100 Subject: [PATCH 090/111] Add macros for second order CPML derivatives --- src/utils/fdgen.jl | 56 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl index 8a96ece..cd82c32 100644 --- a/src/utils/fdgen.jl +++ b/src/utils/fdgen.jl @@ -130,8 +130,8 @@ function ∂ⁿ_(A, dim::Int; I=(:i,), _Δ=1.0, deriv::Int=1, order::Int=2, bdch return Expr(:call, :*, Expr(:call, :+, [:($c * $A[$(Is[i]...)]) for (i, c) in enumerate(coeffs)]...), _Δ) end -function ∂̃_(A, a, b, ψ, dim::Int; I=[:i], halo=:halo, halfgrid=true, kwargs...) - ψtemp = gensym(:ψ) +function ∂̃_(A, a, b, ψ, dim::Int; I=(:i,), halo=:halo, halfgrid=true, kwargs...) + ∂Atemp = gensym(:∂A) iidim = gensym(:i) stencil = ∂ⁿ_(A, dim; I=I, deriv=1, kwargs...) plusone = halfgrid ? 0 : 1 @@ -140,16 +140,44 @@ function ∂̃_(A, a, b, ψ, dim::Int; I=[:i], halo=:halo, halfgrid=true, kwargs Iψ = [i == dim ? idim : I[i] for i in eachindex(I)] IIψ = [i == dim ? iidim : I[i] for i in eachindex(I)] return quote - $ψtemp = $stencil + $∂Atemp = $stencil if $idim <= ($halo + $plusone) $ψ[$(Iψ...)] = $b[$idim ] * $ψ[$(Iψ...)] + $a[$idim ] * $ψtemp - $ψtemp + $ψ[$(Iψ...)] + $∂Atemp + $ψ[$(Iψ...)] elseif $idim >= $ndim - $halo $iidim = $idim - ($ndim - $halo) + 1 + ($halo + $plusone) $ψ[$(IIψ...)] = $b[$iidim] * $ψ[$(IIψ...)] + $a[$iidim] * $ψtemp - $ψtemp + $ψ[$(IIψ...)] + $∂Atemp + $ψ[$(IIψ...)] else - $ψtemp + $∂Atemp + end + end +end + +function ∂̃²_(A, a, b, ψ, ξ, dim::Int; I=(:i,), halo=:halo, kwargs...) + ∂²Atemp = gensym(:∂²A) + ∂ψtemp = gensym(:∂ψ) + iidim = gensym(:i) + Astencil = ∂ⁿ_(A, dim; I=I, deriv=2, kwargs...) + ψstencil_left = ∂ⁿ_(ψ, dim; I=I, deriv=1, kwargs..., bdcheck=false) + ψstencil_right = ∂ⁿ_(ψ, dim; I=I, deriv=1, kwargs..., bdcheck=false) + idim = :( $(I[dim]) ) + ndim = :( size($A, $dim) ) + Iξ = [i == dim ? idim : I[i] for i in eachindex(I)] + IIξ = [i == dim ? iidim : I[i] for i in eachindex(I)] + return quote + $∂²Atemp = $Astencil + if $idim <= ($halo + 1) + $∂ψtemp = $ψstencil_left + $ξ[$(Iξ...)] = $b[$idim ] * $ξ[$(Iξ...)] + $a[$idim ] * ($∂²Atemp + $∂ψtemp) + $∂²Atemp + $∂ψtemp + $ξ[$(Iξ...)] + elseif $idim >= $ndim - $halo + $∂ψtemp = $ψstencil_right + $iidim = $idim - ($ndim - $halo) + 1 + ($halo + 1) + $ξ[$(IIξ...)] = $b[$iidim] * $ξ[$(IIξ...)] + $a[$iidim] * ($∂²Atemp + $∂ψtemp) + $∂²Atemp + $∂ψtemp + $ξ[$(IIξ...)] + else + $∂²Atemp end end end @@ -159,6 +187,16 @@ function ∇ⁿ_(A; I=(), _Δ=(), kwargs...) return Expr(:tuple, (∂ⁿ_(A, i; _Δ=_Δ[i], I=I, deriv=1, kwargs...) for i in eachindex(_Δ))...) end +function ∇̃_(args...; I=(), _Δ=(), kwargs...) + @assert length(I) == length(_Δ) + return Expr(:tuple, (∂̃_(args...; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) +end + +function ∇̃²_(args...; I=(), _Δ=(), kwargs...) + @assert length(I) == length(_Δ) + return Expr(:tuple, (∂̃²_(args...; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) +end + function extract_kwargs(args...) kwargs = Dict{Symbol, Any}() positional = [] @@ -199,4 +237,8 @@ macro ∂ⁿz(args...) posargs, kwargs = extract_kwargs(args...); esc( macro ∂̃( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs...; kwargs...) ) end macro ∂̃x( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 1; kwargs...) ) end macro ∂̃y( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 2; kwargs...) ) end -macro ∂̃z( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 3; kwargs...) ) end \ No newline at end of file +macro ∂̃z( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 3; kwargs...) ) end +macro ∂̃²( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃²_(posargs...; kwargs...) ) end + +macro ∇̃( args...) posargs, kwargs = extract_kwargs(args...); esc( ∇̃_(posargs...; kwargs...) ) end +macro ∇̃²( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇̃²_(posargs...; kwargs...).args... ) ) end \ No newline at end of file From a4c59824249fe81e21e9818d6ab1cc74d263cc31 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 26 Nov 2024 12:48:29 +0100 Subject: [PATCH 091/111] Polished up macros --- src/utils/fdgen.jl | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl index cd82c32..7c799b0 100644 --- a/src/utils/fdgen.jl +++ b/src/utils/fdgen.jl @@ -142,11 +142,11 @@ function ∂̃_(A, a, b, ψ, dim::Int; I=(:i,), halo=:halo, halfgrid=true, kwarg return quote $∂Atemp = $stencil if $idim <= ($halo + $plusone) - $ψ[$(Iψ...)] = $b[$idim ] * $ψ[$(Iψ...)] + $a[$idim ] * $ψtemp + $ψ[$(Iψ...)] = $b[$idim ] * $ψ[$(Iψ...)] + $a[$idim ] * $∂Atemp $∂Atemp + $ψ[$(Iψ...)] elseif $idim >= $ndim - $halo $iidim = $idim - ($ndim - $halo) + 1 + ($halo + $plusone) - $ψ[$(IIψ...)] = $b[$iidim] * $ψ[$(IIψ...)] + $a[$iidim] * $ψtemp + $ψ[$(IIψ...)] = $b[$iidim] * $ψ[$(IIψ...)] + $a[$iidim] * $∂Atemp $∂Atemp + $ψ[$(IIψ...)] else $∂Atemp @@ -158,7 +158,7 @@ function ∂̃²_(A, a, b, ψ, ξ, dim::Int; I=(:i,), halo=:halo, kwargs...) ∂²Atemp = gensym(:∂²A) ∂ψtemp = gensym(:∂ψ) iidim = gensym(:i) - Astencil = ∂ⁿ_(A, dim; I=I, deriv=2, kwargs...) + Astencil = ∂ⁿ_(A, dim; I=I, deriv=2, kwargs...) ψstencil_left = ∂ⁿ_(ψ, dim; I=I, deriv=1, kwargs..., bdcheck=false) ψstencil_right = ∂ⁿ_(ψ, dim; I=I, deriv=1, kwargs..., bdcheck=false) idim = :( $(I[dim]) ) @@ -184,12 +184,12 @@ end function ∇ⁿ_(A; I=(), _Δ=(), kwargs...) @assert length(I) == length(_Δ) - return Expr(:tuple, (∂ⁿ_(A, i; _Δ=_Δ[i], I=I, deriv=1, kwargs...) for i in eachindex(_Δ))...) + return Expr(:tuple, (∂ⁿ_(A, i; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) end function ∇̃_(args...; I=(), _Δ=(), kwargs...) @assert length(I) == length(_Δ) - return Expr(:tuple, (∂̃_(args...; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) + return Expr(:tuple, (∂̃_(args...; _Δ=_Δ[i], I=I, kwargs..., deriv=1) for i in eachindex(_Δ))...) end function ∇̃²_(args...; I=(), _Δ=(), kwargs...) @@ -211,18 +211,10 @@ function extract_kwargs(args...) return positional, kwargs end -# General partial scalar derivatives +# SCALAR DERIVATIVES macro ∂( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs...; kwargs..., deriv=1) ) end macro ∂²( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs...; kwargs..., deriv=2) ) end macro ∂ⁿ( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs...; kwargs...) ) end - -# General partial vector derivatives (gradient, divergence and Laplacian) -macro ∇( args...) posargs, kwargs = extract_kwargs(args...); esc( ∇ⁿ_(posargs...; kwargs...) ) end -macro div(args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., deriv=1).args... ) ) end -macro ∇²( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., deriv=2).args... ) ) end -macro ∇ⁿ( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., ).args... ) ) end - -# Specialized partial scalar derivatives macro ∂x( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 1; kwargs..., deriv=1) ) end macro ∂y( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 2; kwargs..., deriv=1) ) end macro ∂z( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs..., deriv=1) ) end @@ -233,12 +225,22 @@ macro ∂ⁿx(args...) posargs, kwargs = extract_kwargs(args...); esc( macro ∂ⁿy(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 2; kwargs...) ) end macro ∂ⁿz(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂ⁿ_(posargs..., 3; kwargs...) ) end -# CPML partial scalar derivatives -macro ∂̃( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs...; kwargs...) ) end -macro ∂̃x( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 1; kwargs...) ) end -macro ∂̃y( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 2; kwargs...) ) end -macro ∂̃z( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 3; kwargs...) ) end -macro ∂̃²( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃²_(posargs...; kwargs...) ) end +# VECTOR DERIVATIVES (GRADIENT, DIVERGENCE, LAPLACIAN) +macro ∇( args...) posargs, kwargs = extract_kwargs(args...); esc( ∇ⁿ_(posargs...; kwargs...) ) end +macro div(args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., deriv=1).args... ) ) end +macro ∇²( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇ⁿ_(posargs...; kwargs..., deriv=2).args... ) ) end -macro ∇̃( args...) posargs, kwargs = extract_kwargs(args...); esc( ∇̃_(posargs...; kwargs...) ) end -macro ∇̃²( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇̃²_(posargs...; kwargs...).args... ) ) end \ No newline at end of file +# SCALAR DERIVATIVES WITH CPML DAMPING +macro ∂̃( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs...; kwargs...) ) end +macro ∂̃x( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 1; kwargs...) ) end +macro ∂̃y( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 2; kwargs...) ) end +macro ∂̃z( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃_(posargs..., 3; kwargs...) ) end +macro ∂̃²( args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃²_(posargs...; kwargs...) ) end +macro ∂̃²x(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃²_(posargs..., 1; kwargs...) ) end +macro ∂̃²y(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃²_(posargs..., 2; kwargs...) ) end +macro ∂̃²z(args...) posargs, kwargs = extract_kwargs(args...); esc( ∂̃²_(posargs..., 3; kwargs...) ) end + +# VECTOR DERIVATIVES (GRADIENT, DIVERGENCE, LAPLACIAN) WITH CPML DAMPING +macro ∇̃( args...) posargs, kwargs = extract_kwargs(args...); esc( ∇̃_(posargs...; kwargs...) ) end +macro diṽ(args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇̃_(posargs...; kwargs...).args... ) ) end +macro ∇̃²( args...) posargs, kwargs = extract_kwargs(args...); esc( Expr(:call, :+, ∇̃²_(posargs...; kwargs...).args... ) ) end \ No newline at end of file From cdab2c264660bef68f0466aa6dd350094b1a4070 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 26 Nov 2024 12:54:52 +0100 Subject: [PATCH 092/111] Formatting --- src/SeismicWaves.jl | 4 ++-- src/inversion/misfits/L2Misfit.jl | 4 ++-- src/shots/receivers.jl | 2 +- src/shots/shot.jl | 1 - src/utils/checks.jl | 8 ++++---- src/utils/interpolations.jl | 10 +++++----- src/utils/utils.jl | 6 +++--- test/utils/setup_models.jl | 4 ++-- 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 6410084..c67d822 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -30,8 +30,8 @@ export build_wavesim, swforward!, swmisfit!, swgradient! export gaussstf, gaussderivstf, rickerstf module FiniteDifferencesMacros - include("utils/fdgen.jl") - export @∂, @∂², @∂ⁿ, @∇, @∇², @∇ⁿ, @div, @∂x, @∂y, @∂z, @∂²x, @∂²y, @∂²z, @∂ⁿx, @∂ⁿy, @∂ⁿz, @∂̃, @∂̃x, @∂̃y, @∂̃z +include("utils/fdgen.jl") +export @∂, @∂², @∂ⁿ, @∇, @∇², @∇ⁿ, @div, @∂x, @∂y, @∂z, @∂²x, @∂²y, @∂²z, @∂ⁿx, @∂ⁿy, @∂ⁿz, @∂̃, @∂̃x, @∂̃y, @∂̃z end include("utils/abstract_types.jl") diff --git a/src/inversion/misfits/L2Misfit.jl b/src/inversion/misfits/L2Misfit.jl index 79a5116..efdc3f0 100644 --- a/src/inversion/misfits/L2Misfit.jl +++ b/src/inversion/misfits/L2Misfit.jl @@ -36,7 +36,7 @@ function (misfit::L2Misfit)(recs::VectorReceivers{T, N}, matprop::MaterialProper end residuals .= mask .* residuals # Inner product using inverse covariance matrix - msf = sum([dot(residuals[:,i,:], recs.invcov, residuals[:,i,:]) for i in 1:N]) / 2 + msf = sum([dot(residuals[:, i, :], recs.invcov, residuals[:, i, :]) for i in 1:N]) / 2 # Add regularization if needed if misfit.regularization !== nothing msf += misfit.regularization(matprop) @@ -74,7 +74,7 @@ function dχ_du(_::L2Misfit, recs::VectorReceivers{T}) where {T} residuals .= mask .* residuals # Multiply with inverse of covariance matrix for d in axes(residuals, 2) - residuals[:,d,:] .= recs.invcov * residuals[:,d,:] + residuals[:, d, :] .= recs.invcov * residuals[:, d, :] end return residuals end \ No newline at end of file diff --git a/src/shots/receivers.jl b/src/shots/receivers.jl index b80c225..e717c3a 100644 --- a/src/shots/receivers.jl +++ b/src/shots/receivers.jl @@ -85,7 +85,7 @@ struct VectorReceivers{T, N} <: Receivers{T} ndim::Int=2; observed::Union{Array{T}, Nothing}=nothing, invcov::Union{AbstractMatrix{T}, Nothing}=nothing, - windows::Union{Vector{Pair{Int,Int}}, Nothing}=nothing + windows::Union{Vector{Pair{Int, Int}}, Nothing}=nothing ) where {T} @assert size(positions, 1) > 0 "There must be at least one receiver!" seismograms = zeros(T, nt, ndim, size(positions, 1)) ## N+1 !!! <<<<<<<<--------------<<<< diff --git a/src/shots/shot.jl b/src/shots/shot.jl index e4d8f46..576b8ba 100644 --- a/src/shots/shot.jl +++ b/src/shots/shot.jl @@ -27,7 +27,6 @@ Base.@kwdef struct MomentTensorShot{T, N, M <: MomentTensor{T, N}} <: Shot{T} recs::VectorReceivers{T, N} end - """ $(TYPEDEF) diff --git a/src/utils/checks.jl b/src/utils/checks.jl index d21b1c3..efd41ed 100644 --- a/src/utils/checks.jl +++ b/src/utils/checks.jl @@ -30,10 +30,10 @@ function check_sim_consistency(model::WaveSimulation{T, N}, matprop::MaterialPro return elseif model isa ElasticIsoCPMLWaveSimulation{T, 2} && # <<<<<---------<<<< - matprop isa ElasticIsoMaterialProperties{T, 2} && - tysource <: ExternalForceSources{T, 2} && - tyreceiver <: VectorReceivers{T, N} - return + matprop isa ElasticIsoMaterialProperties{T, 2} && + tysource <: ExternalForceSources{T, 2} && + tyreceiver <: VectorReceivers{T, N} + return end return error("Types of WaveSimulation, MaterialProperties and Sources/Receivers are inconsistent \ diff --git a/src/utils/interpolations.jl b/src/utils/interpolations.jl index 341d5c4..542f795 100644 --- a/src/utils/interpolations.jl +++ b/src/utils/interpolations.jl @@ -5,7 +5,7 @@ interp(method::AbstractInterpolationMethod, m::Array{<:Real, N}, dims::Vector{In function binary_permutations(N::Int) permutations = [] - for i in 0:(2^N - 1) + for i in 0:(2^N-1) binary_str = bitstring(i)[end-N+1:end] push!(permutations, [parse(Int, c) for c in binary_str]) end @@ -20,7 +20,7 @@ back_interp(method, m::Array{T, N}, ∂χ∂m_interp::Array{T, N}, dims::Vector{ pp = zeros(Int, N) pp[dims] .= p idxs = CartesianIndices(Tuple( - i in dims ? (1:size(m, i) - 1) .+ pp[i] : (1:size(m, i)) for i in 1:N + i in dims ? (1:size(m, i)-1) .+ pp[i] : (1:size(m, i)) for i in 1:N )) res[idxs] .+= ∂χ∂m_interp .* ∂f∂m(method, m, idxs, dims) end @@ -34,14 +34,14 @@ struct HarmonicAverageInterpolation <: AbstractInterpolationMethod end @views function (itp::ArithmeticAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} itp = Interpolations.interpolate(m, BSpline(Linear())) - return itp([i in dims ? (1.5:size(m,i)-0.5) : (1:size(m,i)) for i in 1:N]...) + return itp([i in dims ? (1.5:size(m, i)-0.5) : (1:size(m, i)) for i in 1:N]...) end @views function (itp::HarmonicAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} itp = Interpolations.interpolate(1 ./ m, BSpline(Linear())) - return 1 ./ itp([i in dims ? (1.5:size(m,i)-0.5) : (1:size(m,i)) for i in 1:N]...) + return 1 ./ itp([i in dims ? (1.5:size(m, i)-0.5) : (1:size(m, i)) for i in 1:N]...) end ∂f∂m(_::ArithmeticAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (2^length(dims)) -∂f∂m(itp::HarmonicAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = (itp(m, dims).^2) ./ (m[idxs] .^2) ./ (2^length(dims)) \ No newline at end of file +∂f∂m(itp::HarmonicAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = (itp(m, dims) .^ 2) ./ (m[idxs] .^ 2) ./ (2^length(dims)) \ No newline at end of file diff --git a/src/utils/utils.jl b/src/utils/utils.jl index 91adac6..5a0e881 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -231,12 +231,12 @@ function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter:: end function modd_2D_grid(x0::T, y0::T, dx::T, dy::T, nx::Int, ny::Int, r::Int=4, β::Int=10, xstart::T=0, ystart::T=0) where {T} - xs = range(xstart, length=nx, step=dx) - ys = range(ystart, length=ny, step=dy) + xs = range(xstart; length=nx, step=dx) + ys = range(ystart; length=ny, step=dy) dd_coeffs = Vector{Tuple{Int, Int, T}}() kaiser(x, r, β) = (-r <= x <= r ? besseli(0, β * sqrt(1 - (x / r)^2)) / besseli(0, β) : 0.0) - modd_(x, x0, r, β, Δx) = 1/Δx * kaiser(x - x0, r, β) * sinc((x - x0)/Δx) + modd_(x, x0, r, β, Δx) = 1 / Δx * kaiser(x - x0, r, β) * sinc((x - x0) / Δx) modd(x, x0, r, β, Δx) = begin res = modd_(x, x0, r * Δx, β, Δx) return res ≈ 0 ? 0.0 : res diff --git a/test/utils/setup_models.jl b/test/utils/setup_models.jl index e622a59..4b19455 100644 --- a/test/utils/setup_models.jl +++ b/test/utils/setup_models.jl @@ -135,8 +135,8 @@ function setup_constant_elastic_2D_CPML(nt, dt, nx, ny, dx, dy, ρ0, λ0, μ0, h srcs = MomentTensorSources(possrcs, srctf, [MomentTensor2D(; Mxx=5e10, Mzz=5e10, Mxz=0.98e10)], f0) observed = zeros(nt, 2, 1) - observed[:,1,1] .= srctf[:,1] - observed[:,2,1] .= srctf[:,1] + observed[:, 1, 1] .= srctf[:, 1] + observed[:, 2, 1] .= srctf[:, 1] recs = VectorReceivers(posrecs, nt, 2; observed=observed, invcov=1.0 * I(nt)) shots = [MomentTensorShot(; srcs=srcs, recs=recs)] return params, shots, matprop From de2244127ffa27a4985ef744433346bc08084025 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 26 Nov 2024 13:43:06 +0100 Subject: [PATCH 093/111] Remove error print when boundary checking --- src/utils/fdgen.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl index 7c799b0..7b3d435 100644 --- a/src/utils/fdgen.jl +++ b/src/utils/fdgen.jl @@ -73,8 +73,7 @@ function ∂ⁿ_(A, dim::Int; I=(:i,), _Δ=1.0, deriv::Int=1, order::Int=2, bdch head = :elseif # zero if out of boundaries else - Aname = string(A) - return Expr(:elseif, :(size($A, $dim) < $width), :(error("Size of array (size($($Aname), $($dim)) = $(size($A, $dim))) is smaller than stancil width ($($width))")), :(0)) + return :(0.0) end condition = :(1 <= $(is[1]) <= $(is[state-1]) <= size($A, $dim) && $(is[state]) > size($A, $dim)) if mirror_right From bcfb2e7e8eb2fb01060a598dfe66cb919a91c98d Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 26 Nov 2024 15:40:44 +0100 Subject: [PATCH 094/111] Refactor VD acoustic with new macros --- src/models/acoustic/acou_forward.jl | 2 +- src/models/acoustic/acou_gradient.jl | 6 +- src/models/acoustic/acou_init_bc.jl | 28 +++ src/models/acoustic/acou_models.jl | 46 +--- .../backends/Acoustic1D_VD_CPML_AMDGPU.jl | 3 +- .../backends/Acoustic1D_VD_CPML_CUDA.jl | 3 +- .../backends/Acoustic1D_VD_CPML_Threads.jl | 3 +- .../backends/Acoustic2D_VD_CPML_AMDGPU.jl | 3 +- .../backends/Acoustic2D_VD_CPML_CUDA.jl | 3 +- .../backends/Acoustic2D_VD_CPML_Threads.jl | 3 +- .../backends/shared/acoustic1D_VD_xPU.jl | 125 ++++++----- .../backends/shared/acoustic2D_VD_xPU.jl | 197 +++++++++--------- .../fourth_order_FiniteDifferences1D.jl | 3 - .../fourth_order_FiniteDifferences2D.jl | 7 - 14 files changed, 227 insertions(+), 205 deletions(-) delete mode 100644 src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl delete mode 100644 src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 360326e..2e7469e 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -106,7 +106,7 @@ end # Time loop for it in 1:nt # Compute one forward step - backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) + backend.forward_onestep_CPML!(model, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Iteration: %d, simulation time: %g [s]", it, model.dt * (it - 1)) diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 5de9337..58b5922 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -122,7 +122,7 @@ end # Forward time loop for it in 1:nt # Compute one forward step - backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) + backend.forward_onestep_CPML!(model, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) @@ -147,7 +147,7 @@ end # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step - backend.adjoint_onestep_CPML!(grid, posrecs_bk, residuals_bk, it) + backend.adjoint_onestep_CPML!(model, posrecs_bk, residuals_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Backward iteration: %d", it) @@ -163,7 +163,7 @@ end recover!( checkpointer, recit -> begin - backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false) + backend.forward_onestep_CPML!(model, possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false) return ["pcur" => grid.fields["pcur"]] end ) diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index 0c86f17..7f347ce 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -29,3 +29,31 @@ init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimulation, srcs::So model.cpmlcoeffs[N].b_hl .= 1.0 end end + +@views function init_bdc!( + ::CPMLBoundaryCondition, + model::AcousticVDStaggeredCPMLWaveSimulation, + srcs::Sources +) + N = length(model.cpmlcoeffs) + for n in 1:N + compute_CPML_coefficientsAxis!( + model.cpmlcoeffs[n], + get_maximum_func(model)(model.matprop.vp), + model.dt, + model.cpmlparams.halo, + model.cpmlparams.rcoef, + model.grid.spacing[n] * model.cpmlparams.halo, + srcs.domfreq + ) + end + + if model.cpmlparams.freeboundtop && N >= 1 + lastcoe = model.cpmlcoeffs[N] + + lastcoe.a[1:length(lastcoe.a)÷2] .= 0.0 + lastcoe.a_h[1:length(lastcoe.a_h)÷2] .= 0.0 + lastcoe.b[1:length(lastcoe.b)÷2] .= 1.0 + lastcoe.b_h[1:length(lastcoe.b_h)÷2] .= 1.0 + end +end diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 8c93720..58032ad 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -330,7 +330,7 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < # Material properties matprop::VpRhoAcousticVDMaterialProperties{T, N} # CPML coefficients - cpmlcoeffs::NTuple{N, CPMLCoefficients{T, V}} + cpmlcoeffs::NTuple{N, CPMLCoefficientsAxis{T, V}} # Checkpointing setup checkpointer::Union{Nothing, LinearCheckpointer{T}} # Smooth radius for gradient @@ -370,7 +370,7 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < # Initialize computational grid grid = UniformFiniteDifferenceGrid(gridsize, gridspacing) # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients{T, V}(halo, backend, true) for _ in 1:N]...) + cpmlcoeffs = tuple([CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N]...) # Populate computational grid addfield!(grid, "fact_m0" => ScalarVariableField(backend.zeros(T, gridsize...))) @@ -391,54 +391,30 @@ struct AcousticVDStaggeredCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V < [backend.zeros(T, (gridsize .- [i == j ? 1 : 0 for j in 1:N])...) for i in 1:N] )) end - # CPML coefficients - addfield!( - grid, - "a_pml" => MultiVariableField( - cat([[cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr] for i in 1:N]...; dims=1) - ) - ) - addfield!( - grid, - "b_pml" => MultiVariableField( - cat([[cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr] for i in 1:N]...; dims=1) - ) - ) # CPML memory variables addfield!( grid, - "ψ" => MultiVariableField( - cat( - [[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; - dims=1 - ) + "ψ" => MultiVariableField( # memory variables for velocities + [backend.zeros(T, [j == i ? 2halo : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) addfield!( grid, - "ξ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + "ξ" => MultiVariableField( # memory variables for pressure + [backend.zeros(T, [j == i ? 2(halo+1) : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) if gradient addfield!( grid, - "ψ_adj" => MultiVariableField( - cat( - [ - [backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N - ]...; - dims=1 - ) + "ψ_adj" => MultiVariableField( # memory variables for velocities + [backend.zeros(T, [j == i ? 2halo : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) addfield!( grid, - "ξ_adj" => MultiVariableField( - cat( - [[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; - dims=1 - ) + "ξ_adj" => MultiVariableField( # memory variables for pressure + [backend.zeros(T, [j == i ? 2(halo+1) : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) end @@ -497,7 +473,7 @@ end @views function reset!(model::AcousticVDStaggeredCPMLWaveSimulation) # Reset computational arrays - reset!(model.grid; except=["fact_m0", "fact_m1_stag", "a_pml", "b_pml"]) + reset!(model.grid; except=["fact_m0", "fact_m1_stag"]) if model.checkpointer !== nothing reset!(model.checkpointer) end diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl index 17b294b..3175a12 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl @@ -3,7 +3,8 @@ module Acoustic1D_VD_CPML_AMDGPU using AMDGPU using ParallelStencil using ParallelStencil.FiniteDifferences1D -include("shared/fourth_order_FiniteDifferences1D.jl") + +using SeismicWaves.FiniteDifferencesMacros @init_parallel_stencil(package = AMDGPU, ndims = 1, inbounds = true) diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl index fabe805..fce0325 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl @@ -3,7 +3,8 @@ module Acoustic1D_VD_CPML_CUDA using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences1D -include("shared/fourth_order_FiniteDifferences1D.jl") + +using SeismicWaves.FiniteDifferencesMacros @init_parallel_stencil(package = CUDA, ndims = 1, inbounds = true) diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl index cca1f40..0cfd641 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl @@ -2,7 +2,8 @@ module Acoustic1D_VD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences1D -include("shared/fourth_order_FiniteDifferences1D.jl") + +using SeismicWaves.FiniteDifferencesMacros @init_parallel_stencil(package = Threads, ndims = 1, inbounds = true) diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl index 7117b54..ff4f3de 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl @@ -3,7 +3,8 @@ module Acoustic2D_VD_CPML_AMDGPU using AMDGPU using ParallelStencil using ParallelStencil.FiniteDifferences2D -include("shared/fourth_order_FiniteDifferences2D.jl") + +using SeismicWaves.FiniteDifferencesMacros @init_parallel_stencil(package = AMDGPU, ndims = 2, inbounds = true) diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl index 3ccdfc5..9fa3c1f 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl @@ -3,7 +3,8 @@ module Acoustic2D_VD_CPML_CUDA using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences2D -include("shared/fourth_order_FiniteDifferences2D.jl") + +using SeismicWaves.FiniteDifferencesMacros @init_parallel_stencil(package = CUDA, ndims = 2, inbounds = true) diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl index f441a62..eaa1372 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl @@ -2,7 +2,8 @@ module Acoustic2D_VD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences2D -include("shared/fourth_order_FiniteDifferences2D.jl") + +using SeismicWaves.FiniteDifferencesMacros @init_parallel_stencil(package = Threads, ndims = 2, inbounds = true) diff --git a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl index 1c0b35f..0d6656b 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl @@ -12,44 +12,40 @@ end return nothing end -@parallel_indices (i) function update_p_CPML!(pcur, vx_cur, halo, fact_m0, nx, _dx, - ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) - # Compute velocity derivatives - dv_dx = @d_dx_4th(vx_cur, i) * _dx - # Update CPML memory arrays if on the boundary - if i <= halo + 1 - # left boundary - ξ_l[i-1] = b_x_l[i-1] * ξ_l[i-1] + a_x_l[i-1] * dv_dx - dv_dx += ξ_l[i-1] - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 1 - ξ_r[ii] = b_x_r[ii] * ξ_r[ii] + a_x_r[ii] * dv_dx - dv_dx += ξ_r[ii] - end +@parallel_indices (i) function update_p_CPML!( + pcur, vx_cur, fact_m0, _dx, + halo, ξ_x, b_x, a_x +) + ######################### + # ∂p/∂t = -∂vx/∂x / m0 # + # fact_m0 = 1 / m0 / dt # + ######################### + + # Compute velocity derivative + ∂vx∂x = @∂̃x(vx_cur, a_x, b_x, ξ_x, + order=4, I=(i-1,), _Δ=_dx, + halo=halo, halfgrid=false) # Update pressure - pcur[i] -= fact_m0[i] * dv_dx + pcur[i] -= fact_m0[i] * ∂vx∂x return nothing end -@parallel_indices (i) function update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - # Compute pressure derivative in x direction - dp_dx = @d_dx_4th(pcur, i + 1) * _dx - # Update CPML memory arrays if on the boundary - if i <= halo + 1 - # left boundary - ψ_l[i] = b_x_hl[i] * ψ_l[i] + a_x_hl[i] * dp_dx - dp_dx += ψ_l[i] - elseif i >= nx - halo - 1 - # right boundary - ii = i - (nx - halo - 1) + 1 - ψ_r[ii] = b_x_hr[ii] * ψ_r[ii] + a_x_hr[ii] * dp_dx - dp_dx += ψ_r[ii] - end +@parallel_indices (i) function update_vx_CPML!( + pcur, vx_cur, fact_m1_x, _dx, + halo, ψ_x, b_x_half, a_x_half +) + ############################ + # ∂vx/∂t = -∂p/∂x * m1 # + # fact_m1_x = m1 / dt # + ############################ + + # Compute pressure derivative + ∂p∂x = @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=4, I=(i,), _Δ=_dx, + halo=halo, halfgrid=true) # Update velocity - vx_cur[i] -= fact_m1_x[i] * dp_dx + vx_cur[i] -= fact_m1_x[i] * ∂p∂x return nothing end @@ -68,65 +64,80 @@ end end @views function forward_onestep_CPML!( - grid, possrcs, srctf, posrecs, traces, it; + model, possrcs, srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx = grid.size[1] dx = grid.spacing[1] pcur, vx_cur = grid.fields["pcur"].value, grid.fields["vcur"].value[1] fact_m0 = grid.fields["fact_m0"].value fact_m1_x = grid.fields["fact_m1_stag"].value[1] - ψ_l, ψ_r = grid.fields["ψ"].value - ξ_l, ξ_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x = grid.fields["ψ"].value[1] + ξ_x = grid.fields["ξ"].value[1] + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / (dx * 24) + _dx = 1 / dx - @parallel (3:(nx-2)) update_p_CPML!(pcur, vx_cur, halo, fact_m0, nx, _dx, - ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) + @parallel (2:(nx-1)) update_p_CPML!( + pcur, vx_cur, fact_m0, _dx, + halo, ξ_x, b_x, a_x + ) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) - @parallel (2:(nx-2)) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) + @parallel (1:(nx-1)) update_vx_CPML!( + pcur, vx_cur, fact_m1_x, _dx, + halo, ψ_x, b_x_half, a_x_half + ) if save_trace @parallel (1:size(posrecs, 1)) record_receivers!(pcur, traces, posrecs, it) end end @views function adjoint_onestep_CPML!( - grid, possrcs, srctf, it + model, possrcs, srctf, it ) # Extract info from grid + grid = model.grid nx = grid.size[1] dx = grid.spacing[1] pcur, vx_cur = grid.fields["adjpcur"].value, grid.fields["adjvcur"].value[1] fact_m0 = grid.fields["fact_m0"].value fact_m1_x = grid.fields["fact_m1_stag"].value[1] - ψ_l, ψ_r = grid.fields["ψ_adj"].value - ξ_l, ξ_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x = grid.fields["ψ_adj"].value[1] + ξ_x = grid.fields["ξ_adj"].value[1] + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / (dx * 24) - - @parallel (2:(nx-2)) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_l, ψ_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - @parallel (3:(nx-2)) update_p_CPML!(pcur, vx_cur, halo, fact_m0, nx, _dx, - ξ_l, ξ_r, a_x_l, a_x_r, b_x_l, b_x_r) + _dx = 1 / dx + + @parallel (1:(nx-1)) update_vx_CPML!( + pcur, vx_cur, fact_m1_x, _dx, + halo, ψ_x, b_x_half, a_x_half + ) + @parallel (2:(nx-1)) update_p_CPML!( + pcur, vx_cur, fact_m0, _dx, + halo, ξ_x, b_x, a_x + ) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) end @views function correlate_gradient_m1!(curgrad_m1_stag, adjvcur, pold, gridspacing) - _gridspacing = 1 ./ (gridspacing .* 24) + _gridspacing = 1 ./ gridspacing nx = length(pold) @parallel (2:nx-2) correlate_gradient_m1_kernel_x!(curgrad_m1_stag[1], adjvcur[1], pold, _gridspacing[1]) end @parallel_indices (i) function correlate_gradient_m1_kernel_x!(curgrad_m1_stag_x, adjvcur_x, pold, _dx) - curgrad_m1_stag_x[i] = curgrad_m1_stag_x[i] + adjvcur_x[i] * @d_dx_4th(pold, i + 1) * _dx + ∂p∂x = @∂x(pold, order=4, I=(i,), _Δ=_dx) + curgrad_m1_stag_x[i] = curgrad_m1_stag_x[i] + adjvcur_x[i] * ∂p∂x return nothing end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl index eec5186..2342ca6 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl @@ -14,77 +14,62 @@ end return nothing end -@parallel_indices (i, j) function update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, - ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, - ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) +@parallel_indices (i, j) function update_p_CPML!( + pcur, vx_cur, vy_cur, fact_m0, _dx, _dy, + halo, ξ_x, ξ_y, b_x, b_y, a_x, a_y +) + ################################## + # ∂p/∂t = (∂vx/∂x + ∂vy/∂y) / m0 # + # fact_m0 = 1 / m0 / dt # + ################################## + # Compute velocity derivatives - dv_dx = @d_dx_4th(vx_cur, i, j) * _dx - dv_dy = @d_dy_4th(vy_cur, i, j) * _dy - # Update CPML memory arrays if on the boundary - if i <= halo + 1 - # left boundary - ξ_x_l[i-1, j] = b_x_l[i-1] * ξ_x_l[i-1, j] + a_x_l[i-1] * dv_dx - dv_dx += ξ_x_l[i-1, j] - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 1 - ξ_x_r[ii, j] = b_x_r[ii] * ξ_x_r[ii, j] + a_x_r[ii] * dv_dx - dv_dx += ξ_x_r[ii, j] - end - if j <= halo + 1 - # top boundary - ξ_y_l[i, j-1] = b_y_l[j-1] * ξ_y_l[i, j-1] + a_y_l[j-1] * dv_dy - dv_dy += ξ_y_l[i, j-1] - elseif j >= ny - halo - # bottom boundary - jj = j - (ny - halo) + 1 - ξ_y_r[i, jj] = b_y_r[jj] * ξ_y_r[i, jj] + a_y_r[jj] * dv_dy - dv_dy += ξ_y_r[i, jj] - end + ∂vx∂x = @∂̃x(vx_cur, a_x, b_x, ξ_x, + order=4, I=(i-1,j), _Δ=_dx, + halo=halo, halfgrid=false) + ∂vy∂y = @∂̃y(vy_cur, a_y, b_y, ξ_y, + order=4, I=(i,j-1), _Δ=_dy, + halo=halo, halfgrid=false) # Update pressure - pcur[i, j] -= fact_m0[i, j] * (dv_dx + dv_dy) + pcur[i, j] -= fact_m0[i, j] * (∂vx∂x + ∂vy∂y) return nothing end -@parallel_indices (i, j) function update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) +@parallel_indices (i, j) function update_vx_CPML!( + pcur, vx_cur, fact_m1_x, _dx, + halo, ψ_x, b_x_half, a_x_half +) + ######################## + # ∂vx/∂t = -∂p/∂x * m1 # + # fact_m1_x = m1 / dt # + ######################## + # Compute pressure derivative in x direction - dp_dx = @d_dx_4th(pcur, i + 1, j) * _dx - # Update CPML memory arrays if on the boundary - if i <= halo + 1 - # left boundary - ψ_x_l[i, j] = b_x_hl[i] * ψ_x_l[i, j] + a_x_hl[i] * dp_dx - dp_dx += ψ_x_l[i, j] - elseif i >= nx - halo - 1 - # right boundary - ii = i - (nx - halo - 1) + 1 - ψ_x_r[ii, j] = b_x_hr[ii] * ψ_x_r[ii, j] + a_x_hr[ii] * dp_dx - dp_dx += ψ_x_r[ii, j] - end + ∂p∂x = @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=4, I=(i,j), _Δ=_dx, + halo=halo, halfgrid=true) # Update velocity - vx_cur[i, j] -= fact_m1_x[i, j] * dp_dx + vx_cur[i, j] -= fact_m1_x[i, j] * ∂p∂x return nothing end -@parallel_indices (i, j) function update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, - ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) +@parallel_indices (i, j) function update_vy_CPML!( + pcur, vy_cur, fact_m1_y, _dy, + halo, ψ_y, b_y_half, a_y_half +) + ######################## + # ∂vy/∂t = -∂p/∂y * m1 # + # fact_m1_y = m1 / dt # + ######################## + # Compute pressure derivative in y direction - dp_dy = @d_dy_4th(pcur, i, j + 1) * _dy - # Update CPML memory arrays if on the boundary - if j <= halo + 1 - # top boundary - ψ_y_l[i, j] = b_y_hl[j] * ψ_y_l[i, j] + a_y_hl[j] * dp_dy - dp_dy += ψ_y_l[i, j] - elseif j >= ny - halo - 1 - # bottom boundary - jj = j - (ny - halo - 1) + 1 - ψ_y_r[i, jj] = b_y_hr[jj] * ψ_y_r[i, jj] + a_y_hr[jj] * dp_dy - dp_dy += ψ_y_r[i, jj] - end + ∂p∂y = @∂̃y(pcur, a_y_half, b_y_half, ψ_y, + order=4, I=(i,j), _Δ=_dy, + halo=halo, halfgrid=true) # Update velocity - vy_cur[i, j] -= fact_m1_y[i, j] * dp_dy + vy_cur[i, j] -= fact_m1_y[i, j] * ∂p∂y return nothing end @@ -104,34 +89,46 @@ end end @views function forward_onestep_CPML!( - grid, possrcs, srctf, posrecs, traces, it; + model, possrcs, srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx, ny = grid.size dx, dy = grid.spacing pcur = grid.fields["pcur"].value vx_cur, vy_cur = grid.fields["vcur"].value fact_m0 = grid.fields["fact_m0"].value fact_m1_x, fact_m1_y = grid.fields["fact_m1_stag"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y = grid.fields["ψ"].value + ξ_x, ξ_y = grid.fields["ξ"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / (dx * 24) - _dy = 1 / (dy * 24) + _dx = 1 / dx + _dy = 1 / dy - @parallel (3:(nx-2), 3:(ny-2)) update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, - ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, - ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) + @parallel (2:(nx-1),2:(ny-1)) update_p_CPML!( + pcur, vx_cur, vy_cur, fact_m0, _dx, _dy, + halo, ξ_x, ξ_y, b_x, b_y, a_x, a_y + ) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) - @parallel_async (2:(nx-2), 1:ny) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - @parallel_async (1:nx, 2:(ny-2)) update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, - ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) + @parallel_async (1:(nx-1), 1:ny) update_vx_CPML!( + pcur, vx_cur, fact_m1_x, _dx, + halo, ψ_x, b_x_half, a_x_half + ) + @parallel_async (1:nx, 1:(ny-1)) update_vy_CPML!( + pcur, vy_cur, fact_m1_y, _dy, + halo, ψ_y, b_y_half, a_y_half + ) @synchronize if save_trace @@ -140,51 +137,65 @@ end end @views function adjoint_onestep_CPML!( - grid, possrcs, srctf, it + model, possrcs, srctf, it ) # Extract info from grid + grid = model.grid nx, ny = grid.size dx, dy = grid.spacing pcur = grid.fields["adjpcur"].value vx_cur, vy_cur = grid.fields["adjvcur"].value fact_m0 = grid.fields["fact_m0"].value fact_m1_x, fact_m1_y = grid.fields["fact_m1_stag"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y = grid.fields["ψ_adj"].value + ξ_x, ξ_y = grid.fields["ξ_adj"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / (dx * 24) - _dy = 1 / (dy * 24) - - @parallel_async (2:(nx-2), 1:ny) update_vx_CPML!(pcur, vx_cur, halo, fact_m1_x, nx, _dx, - ψ_x_l, ψ_x_r, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - @parallel_async (1:nx, 2:(ny-2)) update_vy_CPML!(pcur, vy_cur, halo, fact_m1_y, ny, _dy, - ψ_y_l, ψ_y_r, a_y_hl, a_y_hr, b_y_hl, b_y_hr) + _dx = 1 / dx + _dy = 1 / dy + + @parallel_async (1:(nx-1), 1:ny) update_vx_CPML!( + pcur, vx_cur, fact_m1_x, _dx, + halo, ψ_x, b_x_half, a_x_half + ) + @parallel_async (1:nx, 1:(ny-1)) update_vy_CPML!( + pcur, vy_cur, fact_m1_y, _dy, + halo, ψ_y, b_y_half, a_y_half + ) @synchronize - @parallel (3:(nx-2), 3:(ny-2)) update_p_CPML!(pcur, vx_cur, vy_cur, halo, fact_m0, nx, ny, _dx, _dy, - ξ_x_l, ξ_x_r, a_x_l, a_x_r, b_x_l, b_x_r, - ξ_y_l, ξ_y_r, a_y_l, a_y_r, b_y_l, b_y_r) + @parallel (2:(nx-1),2:(ny-1)) update_p_CPML!( + pcur, vx_cur, vy_cur, fact_m0, _dx, _dy, + halo, ξ_x, ξ_y, b_x, b_y, a_x, a_y + ) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) end @views function correlate_gradient_m1!(curgrad_m1_stag, adjvcur, pold, gridspacing) - _gridspacing = 1 ./ (gridspacing .* 24) + _gridspacing = 1 ./ gridspacing nx, ny = size(pold) - @parallel (2:nx-2, 1:ny) correlate_gradient_m1_kernel_x!(curgrad_m1_stag[1], adjvcur[1], pold, _gridspacing[1]) - @parallel (1:nx, 2:nx-2) correlate_gradient_m1_kernel_y!(curgrad_m1_stag[2], adjvcur[2], pold, _gridspacing[2]) + @parallel (1:(nx-1), 1:ny) correlate_gradient_m1_kernel_x!(curgrad_m1_stag[1], adjvcur[1], pold, _gridspacing[1]) + @parallel (1:nx, 1:(ny-1)) correlate_gradient_m1_kernel_y!(curgrad_m1_stag[2], adjvcur[2], pold, _gridspacing[2]) end @parallel_indices (i, j) function correlate_gradient_m1_kernel_x!(curgrad_m1_stag_x, adjvcur_x, pold, _dx) - curgrad_m1_stag_x[i, j] = curgrad_m1_stag_x[i, j] + adjvcur_x[i, j] * @d_dx_4th(pold, i + 1, j) * _dx + ∂p∂x = @∂x(pold, order=4, I=(i,j), _Δ=_dx) + curgrad_m1_stag_x[i, j] = curgrad_m1_stag_x[i, j] + adjvcur_x[i, j] * ∂p∂x return nothing end @parallel_indices (i, j) function correlate_gradient_m1_kernel_y!(curgrad_m1_stag_y, adjvcur_y, pold, _dy) - curgrad_m1_stag_y[i, j] = curgrad_m1_stag_y[i, j] + adjvcur_y[i, j] * @d_dy_4th(pold, i, j + 1) * _dy + ∂p∂y = @∂y(pold, order=4, I=(i,j), _Δ=_dy) + curgrad_m1_stag_y[i, j] = curgrad_m1_stag_y[i, j] + adjvcur_y[i, j] * ∂p∂y return nothing end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl deleted file mode 100644 index 3ad648a..0000000 --- a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl +++ /dev/null @@ -1,3 +0,0 @@ -macro d_dx_4th(a, i) - return esc(:((-$a[$i+1] + 27.0 * $a[$i] - 27.0 * $a[$i-1] + $a[$i-2]))) -end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl deleted file mode 100644 index 2dce407..0000000 --- a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl +++ /dev/null @@ -1,7 +0,0 @@ -macro d_dx_4th(a, i, j) - return esc(:((-$a[$i+1, $j] + 27.0 * $a[$i, $j] - 27.0 * $a[$i-1, $j] + $a[$i-2, $j]))) -end - -macro d_dy_4th(a, i, j) - return esc(:((-$a[$i, $j+1] + 27.0 * $a[$i, $j] - 27.0 * $a[$i, $j-1] + $a[$i, $j-2]))) -end From d37f1debce0f1d290f53956ba40624dfa667e0a4 Mon Sep 17 00:00:00 2001 From: Andrea Zunino <6928707-anzun@users.noreply.gitlab.com> Date: Wed, 27 Nov 2024 15:40:08 +0100 Subject: [PATCH 095/111] fix indices free surface --- src/models/elastic/backends/shared/elastic2D_iso_xPU.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl index 6bcd7cd..395fb4c 100644 --- a/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl +++ b/src/models/elastic/backends/shared/elastic2D_iso_xPU.jl @@ -461,7 +461,7 @@ function forward_onestep_CPML!( end # update stresses σxx and σzz - idxzσxx = freetop ? (1:nz-2) : (2:nz-1) + idxzσxx = freetop ? (1:nz-1) : (2:nz-1) @parallel (2:nx-1, idxzσxx) update_4thord_σxxσzz!( σxx, σzz, vx, vz, dt, _dx, _dz, λ, μ, halo, ψ_∂vx∂x, ψ_∂vz∂z, b_x, b_z, a_x, a_z, freetop @@ -524,7 +524,7 @@ function adjoint_onestep_CPML!( _dz = 1.0 / dz # update adjoint stresses σxx and σzz - @parallel (1:nx-1, 1:nz-1) update_4thord_adjσxxσzz!( + @parallel (2:nx-1, 2:nz-1) update_4thord_adjσxxσzz!( adjσxx, adjσzz, adjvx, adjvz, dt, _dx, _dz, halo, adjψ_∂vx∂x, adjψ_∂vz∂z, b_x, b_z, a_x, a_z ) @@ -555,4 +555,4 @@ function adjoint_onestep_CPML!( end return -end \ No newline at end of file +end From 1906a6ba5732e2927aae97b1b739d725a03ef0e1 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 27 Nov 2024 16:41:08 +0100 Subject: [PATCH 096/111] Add support for different fields in gradient macro --- src/utils/fdgen.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl index 7b3d435..7081163 100644 --- a/src/utils/fdgen.jl +++ b/src/utils/fdgen.jl @@ -181,9 +181,9 @@ function ∂̃²_(A, a, b, ψ, ξ, dim::Int; I=(:i,), halo=:halo, kwargs...) end end -function ∇ⁿ_(A; I=(), _Δ=(), kwargs...) +function ∇ⁿ_(args...; I=(), _Δ=(), kwargs...) @assert length(I) == length(_Δ) - return Expr(:tuple, (∂ⁿ_(A, i; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) + return Expr(:tuple, (∂ⁿ_(length(args) == 1 ? args[1] : args[i], i; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) end function ∇̃_(args...; I=(), _Δ=(), kwargs...) From ae558e4016508cabe1f2431d68ebaeb90c311bae Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Thu, 28 Nov 2024 11:05:37 +0100 Subject: [PATCH 097/111] Refactor acoustic backends with new macros --- src/SeismicWaves.jl | 14 +- src/models/acoustic/acou_forward.jl | 2 +- src/models/acoustic/acou_gradient.jl | 8 +- src/models/acoustic/acou_init_bc.jl | 26 -- src/models/acoustic/acou_models.jl | 47 +--- .../backends/Acoustic1D_CD_CPML_AMDGPU.jl | 3 + .../backends/Acoustic1D_CD_CPML_CUDA.jl | 3 + .../backends/Acoustic1D_CD_CPML_Serial.jl | 152 +++++----- .../backends/Acoustic1D_CD_CPML_Threads.jl | 3 + .../backends/Acoustic2D_CD_CPML_AMDGPU.jl | 2 + .../backends/Acoustic2D_CD_CPML_CUDA.jl | 2 + .../backends/Acoustic2D_CD_CPML_Serial.jl | 167 +++++------ .../backends/Acoustic2D_CD_CPML_Threads.jl | 2 + .../backends/Acoustic3D_CD_CPML_AMDGPU.jl | 2 + .../backends/Acoustic3D_CD_CPML_CUDA.jl | 2 + .../backends/Acoustic3D_CD_CPML_Serial.jl | 231 +++++++-------- .../backends/Acoustic3D_CD_CPML_Threads.jl | 2 + .../backends/shared/acoustic1D_VD_xPU.jl | 4 +- .../backends/shared/acoustic1D_xPU.jl | 149 ++++------ .../backends/shared/acoustic2D_VD_xPU.jl | 4 +- .../backends/shared/acoustic2D_xPU.jl | 170 +++++------ .../backends/shared/acoustic3D_xPU.jl | 264 +++++++----------- src/utils/fdgen.jl | 30 +- src/utils/interpolations.jl | 16 +- ..._vs_numerical_acoustic_constant_density.jl | 4 + ..._vs_numerical_acoustic_variable_density.jl | 4 + test/test_forward_constant_density.jl | 4 + ...test_gradient_acoustic_constant_density.jl | 4 + ...test_gradient_acoustic_variable_density.jl | 4 + ...l => test_gradient_elastic_homogeneous.jl} | 4 + test/test_misfit_acoustic_constant_density.jl | 4 + test/test_snapshotting_constant_density.jl | 4 + 32 files changed, 569 insertions(+), 768 deletions(-) rename test/{test_gradient_elastic_constant_density.jl => test_gradient_elastic_homogeneous.jl} (98%) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index c67d822..079abd3 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -30,8 +30,16 @@ export build_wavesim, swforward!, swmisfit!, swgradient! export gaussstf, gaussderivstf, rickerstf module FiniteDifferencesMacros -include("utils/fdgen.jl") -export @∂, @∂², @∂ⁿ, @∇, @∇², @∇ⁿ, @div, @∂x, @∂y, @∂z, @∂²x, @∂²y, @∂²z, @∂ⁿx, @∂ⁿy, @∂ⁿz, @∂̃, @∂̃x, @∂̃y, @∂̃z + include("utils/fdgen.jl") + export @∂, @∂², @∂ⁿ + export @∂x, @∂y, @∂z + export @∂²x, @∂²y, @∂²z + export @∂ⁿx, @∂ⁿy, @∂ⁿz + export @∇, @div, @∇² + export @∂̃, @∂̃x, @∂̃y, @∂̃z + export @∂̃², @∂̃²x, @∂̃²y, @∂̃²z + export @∇̃, @diṽ, @∇̃² + end include("utils/abstract_types.jl") @@ -112,7 +120,9 @@ include("models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl") ## HMC stuff include("HMCseiswaves.jl") + using .HMCseiswaves export AcouWavCDProb +export FiniteDifferencesMacros end # module diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index 2e7469e..cc9dc70 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -45,7 +45,7 @@ end # Time loop for it in 1:nt # Compute one forward step - backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) + backend.forward_onestep_CPML!(model, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Iteration: %d, simulation time: %g [s]", it, model.dt * (it - 1)) diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 58b5922..678aebd 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -29,7 +29,7 @@ swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = # Forward time loop for it in 1:nt # Compute one forward step - backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) + backend.forward_onestep_CPML!(model, possrcs_bk, srctf_bk, posrecs_bk, traces_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Forward iteration: %d, simulation time: %g [s]", it, model.dt * it) @@ -53,7 +53,7 @@ swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = # Adjoint time loop (backward in time) for it in nt:-1:1 # Compute one adjoint step - backend.adjoint_onestep_CPML!(grid, posrecs_bk, residuals_bk, it) + backend.adjoint_onestep_CPML!(model, posrecs_bk, residuals_bk, it) # Print timestep info if it % model.infoevery == 0 @info @sprintf("Backward iteration: %d", it) @@ -69,7 +69,7 @@ swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = recover!( checkpointer, recit -> begin - backend.forward_onestep_CPML!(grid, possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false) + backend.forward_onestep_CPML!(model, possrcs_bk, srctf_bk, nothing, nothing, recit; save_trace=false) return ["pcur" => grid.fields["pcur"]] end ) @@ -183,8 +183,6 @@ end for i in eachindex(grid.fields["grad_m1_stag"].value) # Accumulate and back interpolate staggered gradients gradient_m1 .+= back_interp(model.matprop.interp_method, 1 ./ model.matprop.rho, Array(grid.fields["grad_m1_stag"].value[i]), i) - # gradient_m1[CartesianIndices(Tuple(j == i ? (2:grid.size[j]-1) : (1:grid.size[j]) for j in 1:N))] .+= - # interp(model.matprop.interp_method, Array(grid.fields["grad_m1_stag"].value[i]), i) end # Smooth gradients backend.smooth_gradient!(gradient_m0, possrcs, model.smooth_radius) diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index 7f347ce..7960cf9 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -8,32 +8,6 @@ init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimulation, srcs::So ::CPMLBoundaryCondition, model::AcousticWaveSimulation, srcs::Sources -) - N = length(model.cpmlcoeffs) - for n in 1:N - compute_CPML_coefficients!( - model.cpmlcoeffs[n], - get_maximum_func(model)(model.matprop.vp), - model.dt, - model.cpmlparams.halo, - model.cpmlparams.rcoef, - model.grid.spacing[n] * model.cpmlparams.halo, - srcs.domfreq - ) - end - - if model.cpmlparams.freeboundtop && N >= 1 - model.cpmlcoeffs[N].a_l .= 0.0 - model.cpmlcoeffs[N].a_hl .= 0.0 - model.cpmlcoeffs[N].b_l .= 1.0 - model.cpmlcoeffs[N].b_hl .= 1.0 - end -end - -@views function init_bdc!( - ::CPMLBoundaryCondition, - model::AcousticVDStaggeredCPMLWaveSimulation, - srcs::Sources ) N = length(model.cpmlcoeffs) for n in 1:N diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 58032ad..31a0244 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -67,7 +67,7 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac # Material properties matprop::VpAcousticCDMaterialProperties{T, N} # CPML coefficients - cpmlcoeffs::NTuple{N, CPMLCoefficients{T, V}} + cpmlcoeffs::NTuple{N, CPMLCoefficientsAxis{T, V}} # Checkpointing setup checkpointer::Union{Nothing, LinearCheckpointer{T}} # Smooth radius for gradient @@ -107,7 +107,7 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac # Initialize computational grid grid = UniformFiniteDifferenceGrid(gridsize, gridspacing) # Initialize CPML coefficients - cpmlcoeffs = tuple([CPMLCoefficients{T, V}(halo, backend, true) for _ in 1:N]...) + cpmlcoeffs = tuple([CPMLCoefficientsAxis{T, V}(halo, backend) for _ in 1:N]...) # Populate computational grid addfield!(grid, "fact" => ScalarVariableField(backend.zeros(T, gridsize...))) @@ -120,54 +120,31 @@ struct AcousticCDCPMLWaveSimulation{T, N, A <: AbstractArray{T, N}, V <: Abstrac addfield!(grid, "adjcur" => ScalarVariableField(backend.zeros(T, gridsize...))) addfield!(grid, "adjnew" => ScalarVariableField(backend.zeros(T, gridsize...))) end - # CPML coefficients - addfield!( - grid, - "a_pml" => MultiVariableField( - cat([[cpmlcoeffs[i].a_l, cpmlcoeffs[i].a_r, cpmlcoeffs[i].a_hl, cpmlcoeffs[i].a_hr] for i in 1:N]...; dims=1) - ) - ) - addfield!( - grid, - "b_pml" => MultiVariableField( - cat([[cpmlcoeffs[i].b_l, cpmlcoeffs[i].b_r, cpmlcoeffs[i].b_hl, cpmlcoeffs[i].b_hr] for i in 1:N]...; dims=1) - ) - ) # CPML memory variables addfield!( grid, - "ψ" => MultiVariableField( - cat( - [[backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N]...; - dims=1 - ) + "ψ" => MultiVariableField( # memory variables for velocities + [backend.zeros(T, [j == i ? 2halo : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) addfield!( grid, - "ξ" => MultiVariableField( - cat([[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; dims=1) + "ξ" => MultiVariableField( # memory variables for pressure + [backend.zeros(T, [j == i ? 2(halo+1) : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) if gradient + # CPML memory variables addfield!( grid, - "ψ_adj" => MultiVariableField( - cat( - [ - [backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo + 1 : gridsize[j] for j in 1:N]...)] for i in 1:N - ]...; - dims=1 - ) + "ψ_adj" => MultiVariableField( # memory variables for velocities + [backend.zeros(T, [j == i ? 2halo : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) addfield!( grid, - "ξ_adj" => MultiVariableField( - cat( - [[backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...), backend.zeros(T, [j == i ? halo : gridsize[j] for j in 1:N]...)] for i in 1:N]...; - dims=1 - ) + "ξ_adj" => MultiVariableField( # memory variables for pressure + [backend.zeros(T, [j == i ? 2(halo+1) : gridsize[j] for j in 1:N]...) for i in 1:N] ) ) end @@ -237,7 +214,7 @@ end # Specific functions for AcousticCDCPMLWaveSimulation @views function reset!(model::AcousticCDCPMLWaveSimulation) - reset!(model.grid; except=["fact", "a_pml", "b_pml"]) + reset!(model.grid; except=["fact"]) if model.checkpointer !== nothing reset!(model.checkpointer) end diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl index 37284dc..e49ca7e 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl @@ -3,6 +3,9 @@ module Acoustic1D_CD_CPML_AMDGPU using AMDGPU using ParallelStencil using ParallelStencil.FiniteDifferences1D + +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = AMDGPU, ndims = 1, inbound = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl index 26b826e..3fb8694 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl @@ -3,6 +3,9 @@ module Acoustic1D_CD_CPML_CUDA using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences1D + +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = CUDA, ndims = 1, inbound = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index 4581bdf..052f757 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -1,5 +1,7 @@ module Acoustic1D_CD_CPML_Serial +using SeismicWaves.FiniteDifferencesMacros + include("shared/smooth_gradient_1D.jl") # Dummy data module @@ -27,48 +29,33 @@ end end end -@views update_p!(pold, pcur, pnew, fact, nx, _dx2) = - for i in 2:(nx-1) - d2p_dx2 = (pcur[i-1] - 2.0 * pcur[i] + pcur[i-1]) * _dx2 - pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * (d2p_dx2) - end - -@views update_ψ!(ψ_l, ψ_r, pcur, halo, nx, _dx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) = - for i in 1:(halo+1) - ii = i + nx - halo - 2 # shift for right boundary pressure indices - # left boundary - ψ_l[i] = b_x_hl[i] * ψ_l[i] + a_x_hl[i] * (pcur[i+1] - pcur[i]) * _dx - # right boundary - ψ_r[i] = b_x_hr[i] * ψ_r[i] + a_x_hr[i] * (pcur[ii+1] - pcur[ii]) * _dx +function update_ψ!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + for i in 1:2halo + # Shift index to right side if beyond left boundary + ii = i > halo ? size(pcur, 1) - halo - 1 + (i - halo) : i + # Update CPML memory variable + @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=2, I=(ii,), _Δ=_dx, + halo=halo, halfgrid=true) end +end @views function update_p_CPML!( - pold, pcur, pnew, halo, fact, nx, _dx, _dx2, - ψ_l, ψ_r, - ξ_l, ξ_r, - a_x_l, a_x_r, - b_x_l, b_x_r + pold, pcur, pnew, fact, _dx, nx, + halo, ψ_x, ξ_x, b_x, a_x ) + ########################## + # ∂²p/∂t² = c² * ∇²p # + # fact = c² * dt² # + ########################## + for i in 2:(nx-1) - d2p_dx2 = (pcur[i+1] - 2.0 * pcur[i] + pcur[i-1]) * _dx2 - - if i <= halo + 1 - # left boundary - dψ_dx = (ψ_l[i] - ψ_l[i-1]) * _dx - ξ_l[i-1] = b_x_l[i-1] * ξ_l[i-1] + a_x_l[i-1] * (d2p_dx2 + dψ_dx) - damp = fact[i] * (dψ_dx + ξ_l[i-1]) - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 - dψ_dx = (ψ_r[ii] - ψ_r[ii-1]) * _dx - ξ_r[ii-1] = b_x_r[ii-1] * ξ_r[ii-1] + a_x_r[ii-1] * (d2p_dx2 + dψ_dx) - damp = fact[i] * (dψ_dx + ξ_r[ii-1]) - else - damp = 0.0 - end - - # update pressure - pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * (d2p_dx2) + damp + # Compute pressure Laplacian + ∇²p = @∇̃²(pcur, a_x, b_x, ψ_x, ξ_x, + order=2, I=(i,), _Δ=(_dx,), + halo=halo) + # Update pressure + pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * ∇²p end end @@ -80,48 +67,36 @@ end end end -@views function forward_onestep!( - pold, pcur, pnew, fact, dx, - possrcs, dt2srctf, posrecs, traces, it -) - nx = length(pcur) - _dx2 = 1 / dx^2 - - update_p!(pold, pcur, pnew, fact, nx, _dx2) - inject_sources!(pnew, dt2srctf, possrcs, it) - record_receivers!(pnew, traces, posrecs, it) - - return pcur, pnew, pold -end - -@views function forward_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; +function forward_onestep_CPML!( + model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx = grid.size[1] dx = grid.spacing[1] pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value - ψ_l, ψ_r = grid.fields["ψ"].value - ξ_l, ξ_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x = grid.fields["ψ"].value[1] + ξ_x = grid.fields["ξ"].value[1] + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / dx - _dx2 = 1 / dx^2 - - update_ψ!(ψ_l, ψ_r, pcur, - halo, nx, _dx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - update_p_CPML!(pold, pcur, pnew, halo, fact, nx, _dx, _dx2, - ψ_l, ψ_r, - ξ_l, ξ_r, - a_x_l, a_x_r, - b_x_l, b_x_r) + _dx = 1 / dx + + # update ψ arrays + update_ψ!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + # update pressure and ξ arrays + update_p_CPML!( + pold, pcur, pnew, fact, _dx, nx, + halo, ψ_x, ξ_x, b_x, a_x + ) + # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) + # record receivers if save_trace record_receivers!(pnew, traces, posrecs, it) end @@ -134,30 +109,31 @@ end return nothing end -@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) +function adjoint_onestep_CPML!(model, possrcs, dt2srctf, it) # Extract info from grid + grid = model.grid nx = grid.size[1] dx = grid.spacing[1] pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value - ψ_l, ψ_r = grid.fields["ψ_adj"].value - ξ_l, ξ_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x = grid.fields["ψ_adj"].value[1] + ξ_x = grid.fields["ξ_adj"].value[1] + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / dx - _dx2 = 1 / dx^2 - - update_ψ!(ψ_l, ψ_r, pcur, - halo, nx, _dx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - update_p_CPML!(pold, pcur, pnew, halo, fact, nx, _dx, _dx2, - ψ_l, ψ_r, - ξ_l, ξ_r, - a_x_l, a_x_r, - b_x_l, b_x_r) + _dx = 1 / dx + + # update ψ arrays + update_ψ!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + # update pressure and ξ arrays + update_p_CPML!( + pold, pcur, pnew, fact, _dx, nx, + halo, ψ_x, ξ_x, b_x, a_x + ) + # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) # Exchange pressures in grid diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl index f855b3a..9338458 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl @@ -2,6 +2,9 @@ module Acoustic1D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences1D + +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = Threads, ndims = 1, inbounds = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl index fb0e476..55fbbbc 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl @@ -4,6 +4,8 @@ using AMDGPU using ParallelStencil using ParallelStencil.FiniteDifferences2D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = AMDGPU, ndims = 2, inbounds = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl index 85d8f79..2a5d400 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl @@ -4,6 +4,8 @@ using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences2D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = CUDA, ndims = 2, inbounds = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl index 21909ef..ce83f15 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl @@ -1,6 +1,8 @@ module Acoustic2D_CD_CPML_Serial +using SeismicWaves.FiniteDifferencesMacros + include("shared/smooth_gradient_2D.jl") # Dummy data module @@ -12,77 +14,55 @@ end ones = Base.ones zeros = Base.zeros -function update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - ny = size(ψ_x_l, 2) +function update_ψ_x!( + pcur, _dx, ny, halo, ψ_x, b_x_half, a_x_half +) for j in 1:ny - for i in 1:(halo+1) - ii = i + nx - halo - 2 # shift for right boundary pressure indices - # left boundary - ψ_x_l[i, j] = b_x_hl[i] * ψ_x_l[i, j] + a_x_hl[i] * (pcur[i+1, j] - pcur[i, j]) * _dx - # right boundary - ψ_x_r[i, j] = b_x_hr[i] * ψ_x_r[i, j] + a_x_hr[i] * (pcur[ii+1, j] - pcur[ii, j]) * _dx + for i in 1:2halo + # Shift index to right side if beyond left boundary + ii = i > halo ? size(pcur, 1) - halo - 1 + (i - halo) : i + # Update CPML memory variable + @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=2, I=(ii,j), _Δ=_dx, + halo=halo, halfgrid=true) end end end -function update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) - nx = size(ψ_y_l, 1) - for j in 1:(halo+1) +function update_ψ_y!( + pcur, _dy, nx, halo, ψ_y, b_y_half, a_y_half +) + for j in 1:2halo for i in 1:nx - jj = j + ny - halo - 2 # shift for bottom boundary pressure indices - # top boundary - ψ_y_l[i, j] = b_y_hl[j] * ψ_y_l[i, j] + a_y_hl[j] * (pcur[i, j+1] - pcur[i, j]) * _dy - # bottom boundary - ψ_y_r[i, j] = b_y_hr[j] * ψ_y_r[i, j] + a_y_hr[j] * (pcur[i, jj+1] - pcur[i, jj]) * _dy + # Shift index to right side if beyond left boundary + jj = j > halo ? size(pcur, 2) - halo - 1 + (j - halo) : j + # Update CPML memory variable + @∂̃y(pcur, a_y_half, b_y_half, ψ_y, + order=2, I=(i,jj), _Δ=_dy, + halo=halo, halfgrid=true) end end end function update_p_CPML!( - pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, nx, ny, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r + pold, pcur, pnew, fact, _dx, _dy, nx, ny, + halo, ψ_x, ψ_y, ξ_x, ξ_y, b_x, b_y, a_x, a_y ) + + ########################## + # ∂²p/∂t² = c² * ∇²p # + # fact = c² * dt² # + ########################## + for j in 2:(ny-1) for i in 2:(nx-1) - - # pressure derivatives in space - d2p_dx2 = (pcur[i+1, j] - 2.0 * pcur[i, j] + pcur[i-1, j]) * _dx2 - d2p_dy2 = (pcur[i, j+1] - 2.0 * pcur[i, j] + pcur[i, j-1]) * _dy2 - - damp = 0.0 - # x boundaries - if i <= halo + 1 - # left boundary - dψ_x_dx = (ψ_x_l[i, j] - ψ_x_l[i-1, j]) * _dx - ξ_x_l[i-1, j] = b_x_l[i-1] * ξ_x_l[i-1, j] + a_x_l[i-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j] * (dψ_x_dx + ξ_x_l[i-1, j]) - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 - dψ_x_dx = (ψ_x_r[ii, j] - ψ_x_r[ii-1, j]) * _dx - ξ_x_r[ii-1, j] = b_x_r[ii-1] * ξ_x_r[ii-1, j] + a_x_r[ii-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j] * (dψ_x_dx + ξ_x_r[ii-1, j]) - end - # y boundaries - if j <= halo + 1 - # top boundary - dψ_y_dy = (ψ_y_l[i, j] - ψ_y_l[i, j-1]) * _dy - ξ_y_l[i, j-1] = b_y_l[j-1] * ξ_y_l[i, j-1] + a_y_l[j-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j] * (dψ_y_dy + ξ_y_l[i, j-1]) - elseif j >= ny - halo - # bottom boundary - jj = j - (ny - halo) + 2 - dψ_y_dy = (ψ_y_r[i, jj] - ψ_y_r[i, jj-1]) * _dy - ξ_y_r[i, jj-1] = b_y_r[jj-1] * ξ_y_r[i, jj-1] + a_y_r[jj-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j] * (dψ_y_dy + ξ_y_r[i, jj-1]) - end + # Compute pressure Laplacian + ∇²p = @∇̃²(pcur, a_x, b_x, ψ_x, ξ_x, a_y, b_y, ψ_y, ξ_y, + order=2, I=(i,j), _Δ=(_dx, _dy), + halo=halo) # update pressure - pnew[i, j] = 2.0 * pcur[i, j] - pold[i, j] + fact[i, j] * (d2p_dx2 + d2p_dy2) + damp + pnew[i, j] = 2.0 * pcur[i, j] - pold[i, j] + fact[i, j] * ∇²p end end end @@ -111,37 +91,38 @@ prescale_residuals!(residuals, posrecs, fact) = end function forward_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; + model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx, ny = grid.size dx, dy = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y = grid.fields["ψ"].value + ξ_x, ξ_y = grid.fields["ξ"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + halo = model.cpmlparams.halo + # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 # update ψ arrays - update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - - update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) - + update_ψ_x!(pcur, _dx, ny, halo, ψ_x, b_x_half, a_x_half) + update_ψ_y!(pcur, _dy, nx, halo, ψ_y, b_y_half, a_y_half) # update pressure and ξ arrays - update_p_CPML!(pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, nx, ny, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r) - + update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, nx, ny, + halo, ψ_x, ψ_y, ξ_x, ξ_y, b_x, b_y, a_x, a_y + ) # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) # record receivers @@ -156,36 +137,36 @@ function forward_onestep_CPML!( return nothing end -function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) +function adjoint_onestep_CPML!(model, possrcs, dt2srctf, it) # Extract info from grid + grid = model.grid nx, ny = grid.size dx, dy = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y = grid.fields["ψ_adj"].value + ξ_x, ξ_y = grid.fields["ξ_adj"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + halo = model.cpmlparams.halo # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 # update ψ arrays - update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - - update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) - + update_ψ_x!(pcur, _dx, ny, halo, ψ_x, b_x_half, a_x_half) + update_ψ_y!(pcur, _dy, nx, halo, ψ_y, b_y_half, a_y_half) # update pressure and ξ arrays - update_p_CPML!(pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, nx, ny, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r) - + update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, nx, ny, + halo, ψ_x, ψ_y, ξ_x, ξ_y, b_x, b_y, a_x, a_y + ) # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl index 38569ad..952a8cb 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl @@ -3,6 +3,8 @@ module Acoustic2D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences2D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = Threads, ndims = 2, inbounds = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl index e52f097..90ca7ad 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl @@ -4,6 +4,8 @@ using AMDGPU using ParallelStencil using ParallelStencil.FiniteDifferences3D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = AMDGPU, ndims = 3, inbounds = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl index c4b53fa..af44d5b 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl @@ -4,6 +4,8 @@ using CUDA using ParallelStencil using ParallelStencil.FiniteDifferences3D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = CUDA, ndims = 3, inbounds = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl index 4e12c9a..7d9ab1f 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl @@ -1,6 +1,8 @@ module Acoustic3D_CD_CPML_Serial +using SeismicWaves.FiniteDifferencesMacros + include("shared/smooth_gradient_3D.jl") # Dummy data module @@ -14,115 +16,78 @@ zeros = Base.zeros ######################################## -function update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - ny = size(ψ_x_l, 2) - nz = size(ψ_x_l, 3) +function update_ψ_x!( + pcur, _dx, ny, nz, halo, ψ_x, b_x_half, a_x_half +) for k in 1:nz for j in 1:ny - for i in 1:(halo+1) - ii = i + nx - halo - 2 # shift for right boundary pressure indices - # left boundary - ψ_x_l[i, j, k] = b_x_hl[i] * ψ_x_l[i, j, k] + a_x_hl[i] * (pcur[i+1, j, k] - pcur[i, j, k]) * _dx - # right boundary - ψ_x_r[i, j, k] = b_x_hr[i] * ψ_x_r[i, j, k] + a_x_hr[i] * (pcur[ii+1, j, k] - pcur[ii, j, k]) * _dx + for i in 1:2halo + # Shift index to right side if beyond left boundary + ii = i > halo ? size(pcur, 1) - halo - 1 + (i - halo) : i + # Update CPML memory variable + @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=2, I=(ii,j,k), _Δ=_dx, + halo=halo, halfgrid=true) end end end end -function update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) - nx = size(ψ_y_l, 1) - nz = size(ψ_y_l, 3) +function update_ψ_y!( + pcur, _dy, nx, nz, halo, ψ_y, b_y_half, a_y_half +) for k in 1:nz - for j in 1:1:(halo+1) + for j in 1:2halo for i in 1:nx - jj = j + ny - halo - 2 # shift for bottom boundary pressure indices - # top boundary - ψ_y_l[i, j, k] = b_y_hl[j] * ψ_y_l[i, j, k] + a_y_hl[j] * (pcur[i, j+1, k] - pcur[i, j, k]) * _dy - # bottom boundary - ψ_y_r[i, j, k] = b_y_hr[j] * ψ_y_r[i, j, k] + a_y_hr[j] * (pcur[i, jj+1, k] - pcur[i, jj, k]) * _dy + # Shift index to right side if beyond left boundary + jj = j > halo ? size(pcur, 2) - halo - 1 + (j - halo) : j + # Update CPML memory variable + @∂̃y(pcur, a_y_half, b_y_half, ψ_y, + order=2, I=(i,jj,k), _Δ=_dy, + halo=halo, halfgrid=true) end end end end -function update_ψ_z!(ψ_z_l, ψ_z_r, pcur, halo, _dz, nz, a_z_hl, a_z_hr, b_z_hl, b_z_hr) - nx = size(ψ_z_l, 1) - ny = size(ψ_z_l, 2) - for k in 1:1:(halo+1) - for j in 1:1:ny +function update_ψ_z!( + pcur, _dz, nx, ny, halo, ψ_z, b_z_half, a_z_half +) + for k in 1:2halo + for j in 1:ny for i in 1:nx - kk = k + nz - halo - 2 # shift for bottom boundary pressure indices - # front boundary - ψ_z_l[i, j, k] = b_z_hl[k] * ψ_z_l[i, j, k] + a_z_hl[k] * (pcur[i, j, k+1] - pcur[i, j, k]) * _dz - # back boundary - ψ_z_r[i, j, k] = b_z_hr[k] * ψ_z_r[i, j, k] + a_z_hr[k] * (pcur[i, j, kk+1] - pcur[i, j, kk]) * _dz + # Shift index to right side if beyond left boundary + kk = k > halo ? size(pcur, 3) - halo - 1 + (k - halo) : k + # Update CPML memory variable + @∂̃z(pcur, a_z_half, b_z_half, ψ_z, + order=2, I=(i,j,kk), _Δ=_dz, + halo=halo, halfgrid=true) end end end end function update_p_CPML!( - pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, _dz, _dz2, nx, ny, nz, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r, - a_z_l, a_z_r, b_z_l, b_z_r + pold, pcur, pnew, fact, _dx, _dy, _dz, nx, ny, nz, + halo, ψ_x, ψ_y, ψ_z, ξ_x, ξ_y, ξ_z, b_x, b_y, b_z, a_x, a_y, a_z ) + ########################## + # ∂²p/∂t² = c² * ∇²p # + # fact = c² * dt² # + ########################## + for k in 2:(nz-1) for j in 2:(ny-1) for i in 2:(nx-1) - - # pressure derivatives in space - d2p_dx2 = (pcur[i+1, j, k] - 2.0 * pcur[i, j, k] + pcur[i-1, j, k]) * _dx2 - d2p_dy2 = (pcur[i, j+1, k] - 2.0 * pcur[i, j, k] + pcur[i, j-1, k]) * _dy2 - d2p_dz2 = (pcur[i, j, k+1] - 2.0 * pcur[i, j, k] + pcur[i, j, k-1]) * _dz2 - - damp = 0.0 - # x boundaries - if i <= halo + 1 - # left boundary - dψ_x_dx = (ψ_x_l[i, j, k] - ψ_x_l[i-1, j, k]) * _dx - ξ_x_l[i-1, j, k] = b_x_l[i-1] * ξ_x_l[i-1, j, k] + a_x_l[i-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j, k] * (dψ_x_dx + ξ_x_l[i-1, j, k]) - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 - dψ_x_dx = (ψ_x_r[ii, j, k] - ψ_x_r[ii-1, j, k]) * _dx - ξ_x_r[ii-1, j, k] = b_x_r[ii-1] * ξ_x_r[ii-1, j, k] + a_x_r[ii-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j, k] * (dψ_x_dx + ξ_x_r[ii-1, j, k]) - end - # y boundaries - if j <= halo + 1 - # top boundary - dψ_y_dy = (ψ_y_l[i, j, k] - ψ_y_l[i, j-1, k]) * _dy - ξ_y_l[i, j-1, k] = b_y_l[j-1] * ξ_y_l[i, j-1, k] + a_y_l[j-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j, k] * (dψ_y_dy + ξ_y_l[i, j-1, k]) - elseif j >= ny - halo - # bottom boundary - jj = j - (ny - halo) + 2 - dψ_y_dy = (ψ_y_r[i, jj, k] - ψ_y_r[i, jj-1, k]) * _dy - ξ_y_r[i, jj-1, k] = b_y_r[jj-1] * ξ_y_r[i, jj-1, k] + a_y_r[jj-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j, k] * (dψ_y_dy + ξ_y_r[i, jj-1, k]) - end - # z boundaries - if k <= halo + 1 - # front boundary - dψ_z_dz = (ψ_z_l[i, j, k] - ψ_z_l[i, j, k-1]) * _dz - ξ_z_l[i, j, k-1] = b_z_l[k-1] * ξ_z_l[i, j, k-1] + a_z_l[k-1] * (d2p_dz2 + dψ_z_dz) - damp += fact[i, j, k] * (dψ_z_dz + ξ_z_l[i, j, k-1]) - elseif k >= nz - halo - # back boundary - kk = k - (nz - halo) + 2 - dψ_z_dz = (ψ_z_r[i, j, kk] - ψ_z_r[i, j, kk-1]) * _dz - ξ_z_r[i, j, kk-1] = b_z_r[kk-1] * ξ_z_r[i, j, kk-1] + a_z_r[kk-1] * (d2p_dz2 + dψ_z_dz) - damp += fact[i, j, k] * (dψ_z_dz + ξ_z_r[i, j, kk-1]) - end - - # update pressure - pnew[i, j, k] = 2.0 * pcur[i, j, k] - pold[i, j, k] + fact[i, j, k] * (d2p_dx2 + d2p_dy2 + d2p_dz2) + damp + # Compute pressure Laplacian + ∇²p = @∇̃²(pcur, + a_x, b_x, ψ_x, ξ_x, + a_y, b_y, ψ_y, ξ_y, + a_z, b_z, ψ_z, ξ_z, + order=2, I=(i,j,k), _Δ=(_dx, _dy, _dz), + halo=halo) + # Update pressure + pnew[i, j, k] = 2.0 * pcur[i, j, k] - pold[i, j, k] + fact[i, j, k] * ∇²p end end end @@ -155,45 +120,44 @@ prescale_residuals!(residuals, posrecs, fact) = end function forward_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; + model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx, ny, nz = grid.size dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y, ψ_z = grid.fields["ψ"].value + ξ_x, ξ_y, ξ_z = grid.fields["ξ"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + a_z = model.cpmlcoeffs[3].a + a_z_half = model.cpmlcoeffs[3].a_h + b_z = model.cpmlcoeffs[3].b + b_z_half = model.cpmlcoeffs[3].b_h + halo = model.cpmlparams.halo # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 _dz = 1 / dz - _dz2 = 1 / dz^2 # update ψ arrays - update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) - update_ψ_z!(ψ_z_l, ψ_z_r, pcur, halo, _dz, nz, a_z_hl, a_z_hr, b_z_hl, b_z_hr) - + update_ψ_x!(pcur, _dx, ny, nz, halo, ψ_x, b_x_half, a_x_half) + update_ψ_y!(pcur, _dy, nx, nz, halo, ψ_y, b_y_half, a_y_half) + update_ψ_z!(pcur, _dz, nx, ny, halo, ψ_z, b_z_half, a_z_half) # update presure and ξ arrays - update_p_CPML!(pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, _dz, _dz2, nx, ny, nz, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r, - a_z_l, a_z_r, b_z_l, b_z_r) - + update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, _dz, nx, ny, nz, + halo, ψ_x, ψ_y, ψ_z, ξ_x, ξ_y, ξ_z, b_x, b_y, b_z, a_x, a_y, a_z + ) # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) # record receivers @@ -209,43 +173,42 @@ function forward_onestep_CPML!( return nothing end -function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) +function adjoint_onestep_CPML!(model, possrcs, dt2srctf, it) # Extract info from grid + grid = model.grid nx, ny, nz = grid.size dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ_adj"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y, ψ_z = grid.fields["ψ_adj"].value + ξ_x, ξ_y, ξ_z = grid.fields["ξ_adj"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + a_z = model.cpmlcoeffs[3].a + a_z_half = model.cpmlcoeffs[3].a_h + b_z = model.cpmlcoeffs[3].b + b_z_half = model.cpmlcoeffs[3].b_h + halo = model.cpmlparams.halo # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 _dz = 1 / dz - _dz2 = 1 / dz^2 # update ψ arrays - update_ψ_x!(ψ_x_l, ψ_x_r, pcur, halo, _dx, nx, a_x_hl, a_x_hr, b_x_hl, b_x_hr) - update_ψ_y!(ψ_y_l, ψ_y_r, pcur, halo, _dy, ny, a_y_hl, a_y_hr, b_y_hl, b_y_hr) - update_ψ_z!(ψ_z_l, ψ_z_r, pcur, halo, _dz, nz, a_z_hl, a_z_hr, b_z_hl, b_z_hr) - + update_ψ_x!(pcur, _dx, ny, nz, halo, ψ_x, b_x_half, a_x_half) + update_ψ_y!(pcur, _dy, nx, nz, halo, ψ_y, b_y_half, a_y_half) + update_ψ_z!(pcur, _dz, nx, ny, halo, ψ_z, b_z_half, a_z_half) # update presure and ξ arrays - update_p_CPML!(pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, _dz, _dz2, nx, ny, nz, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r, - a_z_l, a_z_r, b_z_l, b_z_r) - + update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, _dz, nx, ny, nz, + halo, ψ_x, ψ_y, ψ_z, ξ_x, ξ_y, ξ_z, b_x, b_y, b_z, a_x, a_y, a_z + ) # inject sources inject_sources!(pnew, dt2srctf, possrcs, it) diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl index 3b32dcc..8dadc79 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl @@ -3,6 +3,8 @@ module Acoustic3D_CD_CPML_Threads using ParallelStencil using ParallelStencil.FiniteDifferences3D +using SeismicWaves.FiniteDifferencesMacros + @init_parallel_stencil(package = Threads, ndims = 3, inbounds = true) include("shared/standard_xPU.jl") diff --git a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl index 0d6656b..4f70b72 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl @@ -98,9 +98,7 @@ end end end -@views function adjoint_onestep_CPML!( - model, possrcs, srctf, it -) +function adjoint_onestep_CPML!(model, possrcs, srctf, it) # Extract info from grid grid = model.grid nx = grid.size[1] diff --git a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl index f729b0e..b02a01c 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl @@ -12,54 +12,32 @@ end return nothing end -@parallel_indices (i) function update_p!(pold, pcur, pnew, fact, _dx2) - d2p_dx2 = (pcur[i+1] - 2.0 * pcur[i] + pcur[i-1]) * _dx2 - pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * (d2p_dx2) - - return nothing -end - -@parallel_indices (i) function update_ψ!( - ψ_l, ψ_r, pcur, - halo, nx, _dx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr -) - ii = i + nx - halo - 2 # shift for right boundary pressure indices - # left boundary - ψ_l[i] = b_x_hl[i] * ψ_l[i] + a_x_hl[i] * (pcur[i+1] - pcur[i]) * _dx - # right boundary - ψ_r[i] = b_x_hr[i] * ψ_r[i] + a_x_hr[i] * (pcur[ii+1] - pcur[ii]) * _dx +@parallel_indices (i) function update_ψ!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + # Shift index to right side if beyond left boundary + ii = i > halo ? size(pcur, 1) - halo - 1 + (i - halo) : i + # Update CPML memory variable + @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=2, I=(ii,), _Δ=_dx, + halo=halo, halfgrid=true) return nothing end @parallel_indices (i) function update_p_CPML!( - pold, pcur, pnew, halo, fact, nx, _dx, _dx2, - ψ_l, ψ_r, - ξ_l, ξ_r, - a_x_l, a_x_r, - b_x_l, b_x_r + pold, pcur, pnew, fact, _dx, + halo, ψ_x, ξ_x, b_x, a_x ) - d2p_dx2 = (pcur[i+1] - 2.0 * pcur[i] + pcur[i-1]) * _dx2 - - if i <= halo + 1 - # left boundary - dψ_dx = (ψ_l[i] - ψ_l[i-1]) * _dx - ξ_l[i-1] = b_x_l[i-1] * ξ_l[i-1] + a_x_l[i-1] * (d2p_dx2 + dψ_dx) - damp = fact[i] * (dψ_dx + ξ_l[i-1]) - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 - dψ_dx = (ψ_r[ii] - ψ_r[ii-1]) * _dx - ξ_r[ii-1] = b_x_r[ii-1] * ξ_r[ii-1] + a_x_r[ii-1] * (d2p_dx2 + dψ_dx) - damp = fact[i] * (dψ_dx + ξ_r[ii-1]) - else - damp = 0.0 - end - - # update pressure - pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * (d2p_dx2) + damp + ########################## + # ∂²p/∂t² = c² * ∇²p # + # fact = c² * dt² # + ########################## + + # Compute pressure Laplacian + ∇²p = @∇̃²(pcur, a_x, b_x, ψ_x, ξ_x, + order=2, I=(i,), _Δ=(_dx,), + halo=halo) + # Update pressure + pnew[i] = 2.0 * pcur[i] - pold[i] + fact[i] * ∇²p return nothing end @@ -77,51 +55,33 @@ end @parallel (1:nt, 1:nrecs) prescale_residuals_kernel!(residuals, posrecs, fact) end -@views function forward_onestep!( - pold, pcur, pnew, fact, dx, - possrcs, dt2srctf, posrecs, traces, it; - save_trace=true -) - nx = length(pcur) - _dx2 = 1 / dx^2 - - @parallel (2:(nx-1)) update_p!(pold, pcur, pnew, fact, _dx2) - @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) - if save_trace - @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) - end - - return pcur, pnew, pold -end - @views function forward_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; + model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx = grid.size[1] dx = grid.spacing[1] pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value - ψ_l, ψ_r = grid.fields["ψ"].value - ξ_l, ξ_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x = grid.fields["ψ"].value[1] + ξ_x = grid.fields["ξ"].value[1] + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / dx - _dx2 = 1 / dx^2 - - @parallel (1:(halo+1)) update_ψ!(ψ_l, ψ_r, pcur, - halo, nx, _dx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - @parallel (2:(nx-1)) update_p_CPML!(pold, pcur, pnew, halo, fact, nx, _dx, _dx2, - ψ_l, ψ_r, - ξ_l, ξ_r, - a_x_l, a_x_r, - b_x_l, b_x_r) + _dx = 1 / dx + + # update ψ arrays + @parallel (1:2halo) update_ψ!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + # update pressure and ξ arrays + @parallel (2:(nx-1)) update_p_CPML!(pold, pcur, pnew, fact, _dx, halo, ψ_x, ξ_x, b_x, a_x) + # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) + # record receivers if save_trace @parallel (1:size(posrecs, 1)) record_receivers!(pnew, traces, posrecs, it) end @@ -133,36 +93,33 @@ end return nothing end -@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) +function adjoint_onestep_CPML!(model, possrcs, dt2srctf, it) # Extract info from grid + grid = model.grid nx = grid.size[1] dx = grid.spacing[1] pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value - ψ_l, ψ_r = grid.fields["ψ_adj"].value - ξ_l, ξ_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x = grid.fields["ψ_adj"].value[1] + ξ_x = grid.fields["ξ_adj"].value[1] + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + halo = model.cpmlparams.halo # Precompute divisions - _dx = 1 / dx - _dx2 = 1 / dx^2 - - @parallel (1:(halo+1)) update_ψ!(ψ_l, ψ_r, pcur, - halo, nx, _dx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - @parallel (2:(nx-1)) update_p_CPML!(pold, pcur, pnew, halo, fact, nx, _dx, _dx2, - ψ_l, ψ_r, - ξ_l, ξ_r, - a_x_l, a_x_r, - b_x_l, b_x_r) + _dx = 1 / dx + + # update ψ arrays + @parallel (1:2halo) update_ψ!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + # update pressure and ξ arrays + @parallel (2:(nx-1)) update_p_CPML!(pold, pcur, pnew, fact, _dx, halo, ψ_x, ξ_x, b_x, a_x) + # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) # Exchange pressures in grid grid.fields["adjold"] = grid.fields["adjcur"] grid.fields["adjcur"] = grid.fields["adjnew"] grid.fields["adjnew"] = grid.fields["adjold"] - return nothing end diff --git a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl index 2342ca6..b4ff275 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl @@ -136,9 +136,7 @@ end end end -@views function adjoint_onestep_CPML!( - model, possrcs, srctf, it -) +function adjoint_onestep_CPML!(model, possrcs, srctf, it) # Extract info from grid grid = model.grid nx, ny = grid.size diff --git a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl index 40e2092..0416361 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl @@ -1,75 +1,46 @@ @parallel_indices (i, j) function update_ψ_x!( - ψ_x_l, ψ_x_r, pcur, - halo, _dx, nx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr + pcur, _dx, halo, ψ_x, b_x_half, a_x_half ) - ii = i + nx - halo - 2 # shift for right boundary pressure indices - # left boundary - ψ_x_l[i, j] = b_x_hl[i] * ψ_x_l[i, j] + a_x_hl[i] * (pcur[i+1, j] - pcur[i, j]) * _dx - # right boundary - ψ_x_r[i, j] = b_x_hr[i] * ψ_x_r[i, j] + a_x_hr[i] * (pcur[ii+1, j] - pcur[ii, j]) * _dx + # Shift index to right side if beyond left boundary + ii = i > halo ? size(pcur, 1) - halo - 1 + (i - halo) : i + # Update CPML memory variable + @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=2, I=(ii,j), _Δ=_dx, + halo=halo, halfgrid=true) return nothing end @parallel_indices (i, j) function update_ψ_y!( - ψ_y_l, ψ_y_r, pcur, - halo, _dy, ny, - a_y_hl, a_y_hr, - b_y_hl, b_y_hr + pcur, _dy, halo, ψ_y, b_y_half, a_y_half ) - jj = j + ny - halo - 2 # shift for bottom boundary pressure indices - # top boundary - ψ_y_l[i, j] = b_y_hl[j] * ψ_y_l[i, j] + a_y_hl[j] * (pcur[i, j+1] - pcur[i, j]) * _dy - # bottom boundary - ψ_y_r[i, j] = b_y_hr[j] * ψ_y_r[i, j] + a_y_hr[j] * (pcur[i, jj+1] - pcur[i, jj]) * _dy + # Shift index to right side if beyond left boundary + jj = j > halo ? size(pcur, 2) - halo - 1 + (j - halo) : j + # Update CPML memory variable + @∂̃y(pcur, a_y_half, b_y_half, ψ_y, + order=2, I=(i,jj), _Δ=_dy, + halo=halo, halfgrid=true) return nothing end @parallel_indices (i, j) function update_p_CPML!( - pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, nx, ny, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r + pold, pcur, pnew, fact, _dx, _dy, + halo, ψ_x, ψ_y, ξ_x, ξ_y, b_x, b_y, a_x, a_y ) - # pressure derivatives in space - d2p_dx2 = (pcur[i+1, j] - 2.0 * pcur[i, j] + pcur[i-1, j]) * _dx2 - d2p_dy2 = (pcur[i, j+1] - 2.0 * pcur[i, j] + pcur[i, j-1]) * _dy2 - - damp = 0.0 - # x boundaries - if i <= halo + 1 - # left boundary - dψ_x_dx = (ψ_x_l[i, j] - ψ_x_l[i-1, j]) * _dx - ξ_x_l[i-1, j] = b_x_l[i-1] * ξ_x_l[i-1, j] + a_x_l[i-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j] * (dψ_x_dx + ξ_x_l[i-1, j]) - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 - dψ_x_dx = (ψ_x_r[ii, j] - ψ_x_r[ii-1, j]) * _dx - ξ_x_r[ii-1, j] = b_x_r[ii-1] * ξ_x_r[ii-1, j] + a_x_r[ii-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j] * (dψ_x_dx + ξ_x_r[ii-1, j]) - end - # y boundaries - if j <= halo + 1 - # top boundary - dψ_y_dy = (ψ_y_l[i, j] - ψ_y_l[i, j-1]) * _dy - ξ_y_l[i, j-1] = b_y_l[j-1] * ξ_y_l[i, j-1] + a_y_l[j-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j] * (dψ_y_dy + ξ_y_l[i, j-1]) - elseif j >= ny - halo - # bottom boundary - jj = j - (ny - halo) + 2 - dψ_y_dy = (ψ_y_r[i, jj] - ψ_y_r[i, jj-1]) * _dy - ξ_y_r[i, jj-1] = b_y_r[jj-1] * ξ_y_r[i, jj-1] + a_y_r[jj-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j] * (dψ_y_dy + ξ_y_r[i, jj-1]) - end - # update pressure - pnew[i, j] = 2.0 * pcur[i, j] - pold[i, j] + fact[i, j] * (d2p_dx2 + d2p_dy2) + damp + ########################## + # ∂²p/∂t² = c² * ∇²p # + # fact = c² * dt² # + ########################## + + # Compute pressure Laplacian + ∇²p = @∇̃²(pcur, a_x, b_x, ψ_x, ξ_x, a_y, b_y, ψ_y, ξ_y, + order=2, I=(i,j), _Δ=(_dx, _dy), + halo=halo) + + # Update pressure + pnew[i, j] = 2.0 * pcur[i, j] - pold[i, j] + fact[i, j] * ∇²p return nothing end @@ -104,43 +75,41 @@ end @parallel (1:nt, 1:nrecs) prescale_residuals_kernel!(residuals, posrecs, fact) end -@views function forward_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; +function forward_onestep_CPML!( + model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx, ny = grid.size dx, dy = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y = grid.fields["ψ"].value + ξ_x, ξ_y = grid.fields["ξ"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + halo = model.cpmlparams.halo + # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 # update ψ arrays - @parallel_async (1:(halo+1), 1:ny) update_ψ_x!(ψ_x_l, ψ_x_r, pcur, - halo, _dx, nx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - @parallel_async (1:nx, 1:(halo+1)) update_ψ_y!(ψ_y_l, ψ_y_r, pcur, - halo, _dy, ny, - a_y_hl, a_y_hr, - b_y_hl, b_y_hr) + @parallel_async (1:2halo, 1:ny) update_ψ_x!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + @parallel_async (1:nx, 1:2halo) update_ψ_y!(pcur, _dy, halo, ψ_y, b_y_half, a_y_half) @synchronize # update pressure and ξ arrays - @parallel (2:(nx-1), 2:(ny-1)) update_p_CPML!(pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, nx, ny, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r) + @parallel (2:(nx-1), 2:(ny-1)) update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, + halo, ψ_x, ψ_y, ξ_x, ξ_y, b_x, b_y, a_x, a_y + ) # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) @@ -156,41 +125,38 @@ end return nothing end -@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) +function adjoint_onestep_CPML!(model, possrcs, dt2srctf, it) # Extract info from grid + grid = model.grid nx, ny = grid.size dx, dy = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r = grid.fields["ψ_adj"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, a_y_l, a_y_r, a_y_hl, a_y_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, b_y_l, b_y_r, b_y_hl, b_y_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y = grid.fields["ψ_adj"].value + ξ_x, ξ_y = grid.fields["ξ_adj"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + halo = model.cpmlparams.halo # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 # update ψ arrays - @parallel_async (1:(halo+1), 1:ny) update_ψ_x!(ψ_x_l, ψ_x_r, pcur, - halo, _dx, nx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - @parallel_async (1:nx, 1:(halo+1)) update_ψ_y!(ψ_y_l, ψ_y_r, pcur, - halo, _dy, ny, - a_y_hl, a_y_hr, - b_y_hl, b_y_hr) + @parallel_async (1:2halo, 1:ny) update_ψ_x!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) + @parallel_async (1:nx, 1:2halo) update_ψ_y!(pcur, _dy, halo, ψ_y, b_y_half, a_y_half) @synchronize # update pressure and ξ arrays - @parallel (2:(nx-1), 2:(ny-1)) update_p_CPML!(pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, nx, ny, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r) + @parallel (2:(nx-1), 2:(ny-1)) update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, + halo, ψ_x, ψ_y, ξ_x, ξ_y, b_x, b_y, a_x, a_y + ) # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) diff --git a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl index 0796aa2..b3c190b 100644 --- a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl @@ -1,109 +1,61 @@ @parallel_indices (i, j, k) function update_ψ_x!( - ψ_x_l, ψ_x_r, pcur, - halo, _dx, nx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr + pcur, _dx, halo, ψ_x, b_x_half, a_x_half ) - ii = i + nx - halo - 2 # shift for right boundary pressure indices - # left boundary - ψ_x_l[i, j, k] = b_x_hl[i] * ψ_x_l[i, j, k] + a_x_hl[i] * (pcur[i+1, j, k] - pcur[i, j, k]) * _dx - # right boundary - ψ_x_r[i, j, k] = b_x_hr[i] * ψ_x_r[i, j, k] + a_x_hr[i] * (pcur[ii+1, j, k] - pcur[ii, j, k]) * _dx + # Shift index to right side if beyond left boundary + ii = i > halo ? size(pcur, 1) - halo - 1 + (i - halo) : i + # Update CPML memory variable + @∂̃x(pcur, a_x_half, b_x_half, ψ_x, + order=2, I=(ii,j,k), _Δ=_dx, + halo=halo, halfgrid=true) return nothing end @parallel_indices (i, j, k) function update_ψ_y!( - ψ_y_l, ψ_y_r, pcur, - halo, _dy, ny, - a_y_hl, a_y_hr, - b_y_hl, b_y_hr + pcur, _dy, halo, ψ_y, b_y_half, a_y_half ) - jj = j + ny - halo - 2 # shift for bottom boundary pressure indices - # top boundary - ψ_y_l[i, j, k] = b_y_hl[j] * ψ_y_l[i, j, k] + a_y_hl[j] * (pcur[i, j+1, k] - pcur[i, j, k]) * _dy - # bottom boundary - ψ_y_r[i, j, k] = b_y_hr[j] * ψ_y_r[i, j, k] + a_y_hr[j] * (pcur[i, jj+1, k] - pcur[i, jj, k]) * _dy + # Shift index to right side if beyond left boundary + jj = j > halo ? size(pcur, 2) - halo - 1 + (j - halo) : j + # Update CPML memory variable + @∂̃y(pcur, a_y_half, b_y_half, ψ_y, + order=2, I=(i,jj,k), _Δ=_dy, + halo=halo, halfgrid=true) return nothing end @parallel_indices (i, j, k) function update_ψ_z!( - ψ_z_l, ψ_z_r, pcur, - halo, _dz, nz, - a_z_hl, a_z_hr, - b_z_hl, b_z_hr + pcur, _dz, halo, ψ_z, b_z_half, a_z_half ) - kk = k + nz - halo - 2 # shift for bottom boundary pressure indices - # front boundary - ψ_z_l[i, j, k] = b_z_hl[k] * ψ_z_l[i, j, k] + a_z_hl[k] * (pcur[i, j, k+1] - pcur[i, j, k]) * _dz - # back boundary - ψ_z_r[i, j, k] = b_z_hr[k] * ψ_z_r[i, j, k] + a_z_hr[k] * (pcur[i, j, kk+1] - pcur[i, j, kk]) * _dz + # Shift index to right side if beyond left boundary + kk = k > halo ? size(pcur, 3) - halo - 1 + (k - halo) : k + # Update CPML memory variable + @∂̃z(pcur, a_z_half, b_z_half, ψ_z, + order=2, I=(i,j,kk), _Δ=_dz, + halo=halo, halfgrid=true) return nothing end @parallel_indices (i, j, k) function update_p_CPML!( - pold, pcur, pnew, halo, fact, - _dx, _dx2, _dy, _dy2, _dz, _dz2, nx, ny, - nz, - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, - ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, - ξ_z_r, - a_x_l, a_x_r, b_x_l, b_x_r, - a_y_l, a_y_r, b_y_l, b_y_r, - a_z_l, a_z_r, b_z_l, b_z_r + pold, pcur, pnew, fact, _dx, _dy, _dz, + halo, ψ_x, ψ_y, ψ_z, ξ_x, ξ_y, ξ_z, b_x, b_y, b_z, a_x, a_y, a_z ) - # pressure derivatives in space - d2p_dx2 = (pcur[i+1, j, k] - 2.0 * pcur[i, j, k] + pcur[i-1, j, k]) * _dx2 - d2p_dy2 = (pcur[i, j+1, k] - 2.0 * pcur[i, j, k] + pcur[i, j-1, k]) * _dy2 - d2p_dz2 = (pcur[i, j, k+1] - 2.0 * pcur[i, j, k] + pcur[i, j, k-1]) * _dz2 - - damp = 0.0 - # x boundaries - if i <= halo + 1 - # left boundary - dψ_x_dx = (ψ_x_l[i, j, k] - ψ_x_l[i-1, j, k]) * _dx - ξ_x_l[i-1, j, k] = b_x_l[i-1] * ξ_x_l[i-1, j, k] + a_x_l[i-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j, k] * (dψ_x_dx + ξ_x_l[i-1, j, k]) - elseif i >= nx - halo - # right boundary - ii = i - (nx - halo) + 2 - dψ_x_dx = (ψ_x_r[ii, j, k] - ψ_x_r[ii-1, j, k]) * _dx - ξ_x_r[ii-1, j, k] = b_x_r[ii-1] * ξ_x_r[ii-1, j, k] + a_x_r[ii-1] * (d2p_dx2 + dψ_x_dx) - damp += fact[i, j, k] * (dψ_x_dx + ξ_x_r[ii-1, j, k]) - end - # y boundaries - if j <= halo + 1 - # top boundary - dψ_y_dy = (ψ_y_l[i, j, k] - ψ_y_l[i, j-1, k]) * _dy - ξ_y_l[i, j-1, k] = b_y_l[j-1] * ξ_y_l[i, j-1, k] + a_y_l[j-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j, k] * (dψ_y_dy + ξ_y_l[i, j-1, k]) - elseif j >= ny - halo - # bottom boundary - jj = j - (ny - halo) + 2 - dψ_y_dy = (ψ_y_r[i, jj, k] - ψ_y_r[i, jj-1, k]) * _dy - ξ_y_r[i, jj-1, k] = b_y_r[jj-1] * ξ_y_r[i, jj-1, k] + a_y_r[jj-1] * (d2p_dy2 + dψ_y_dy) - damp += fact[i, j, k] * (dψ_y_dy + ξ_y_r[i, jj-1, k]) - end - # z boundaries - if k <= halo + 1 - # front boundary - dψ_z_dz = (ψ_z_l[i, j, k] - ψ_z_l[i, j, k-1]) * _dz - ξ_z_l[i, j, k-1] = b_z_l[k-1] * ξ_z_l[i, j, k-1] + a_z_l[k-1] * (d2p_dz2 + dψ_z_dz) - damp += fact[i, j, k] * (dψ_z_dz + ξ_z_l[i, j, k-1]) - elseif k >= nz - halo - # back boundary - kk = k - (nz - halo) + 2 - dψ_z_dz = (ψ_z_r[i, j, kk] - ψ_z_r[i, j, kk-1]) * _dz - ξ_z_r[i, j, kk-1] = b_z_r[kk-1] * ξ_z_r[i, j, kk-1] + a_z_r[kk-1] * (d2p_dz2 + dψ_z_dz) - damp += fact[i, j, k] * (dψ_z_dz + ξ_z_r[i, j, kk-1]) - end + ########################## + # ∂²p/∂t² = c² * ∇²p # + # fact = c² * dt² # + ########################## + + # Compute pressure Laplacian + ∇²p = @∇̃²(pcur, + a_x, b_x, ψ_x, ξ_x, + a_y, b_y, ψ_y, ξ_y, + a_z, b_z, ψ_z, ξ_z, + order=2, I=(i,j,k), _Δ=(_dx, _dy, _dz), + halo=halo) # update pressure - pnew[i, j, k] = - 2.0 * pcur[i, j, k] - pold[i, j, k] + fact[i, j, k] * (d2p_dx2 + d2p_dy2 + d2p_dz2) + damp + pnew[i, j, k] = 2.0 * pcur[i, j, k] - pold[i, j, k] + fact[i, j, k] * ∇²p return nothing end @@ -142,61 +94,55 @@ end end @views function forward_onestep_CPML!( - grid, possrcs, dt2srctf, posrecs, traces, it; + model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) # Extract info from grid + grid = model.grid nx, ny, nz = grid.size dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["pold"].value, grid.fields["pcur"].value, grid.fields["pnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y, ψ_z = grid.fields["ψ"].value + ξ_x, ξ_y, ξ_z = grid.fields["ξ"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + a_z = model.cpmlcoeffs[3].a + a_z_half = model.cpmlcoeffs[3].a_h + b_z = model.cpmlcoeffs[3].b + b_z_half = model.cpmlcoeffs[3].b_h + halo = model.cpmlparams.halo # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 _dz = 1 / dz - _dz2 = 1 / dz^2 # update ψ arrays - @parallel_async (1:(halo+1), 1:ny, 1:nz) update_ψ_x!(ψ_x_l, ψ_x_r, pcur, - halo, _dx, nx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - @parallel_async (1:nx, 1:(halo+1), 1:nz) update_ψ_y!(ψ_y_l, ψ_y_r, pcur, - halo, _dy, ny, - a_y_hl, a_y_hr, - b_y_hl, b_y_hr) - @parallel_async (1:nx, 1:ny, 1:(halo+1)) update_ψ_z!(ψ_z_l, ψ_z_r, pcur, - halo, _dz, nz, - a_z_hl, a_z_hr, - b_z_hl, b_z_hr) + @parallel_async (1:2halo, 1:ny, 1:nz) update_ψ_x!( + pcur, _dx, halo, ψ_x, b_x_half, a_x_half + ) + @parallel_async (1:nx, 1:2halo, 1:nz) update_ψ_y!( + pcur, _dy, halo, ψ_y, b_y_half, a_y_half + ) + @parallel_async (1:nx, 1:ny, 1:2halo) update_ψ_z!( + pcur, _dz, halo, ψ_z, b_z_half, a_z_half + ) @synchronize # update presure and ξ arrays - @parallel (2:(nx-1), 2:(ny-1), 2:(nz-1)) update_p_CPML!(pold, pcur, pnew, halo, - fact, - _dx, _dx2, _dy, _dy2, _dz, - _dz2, nx, ny, nz, - ψ_x_l, ψ_x_r, ψ_y_l, - ψ_y_r, ψ_z_l, ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, - ξ_y_r, ξ_z_l, ξ_z_r, - a_x_l, a_x_r, b_x_l, - b_x_r, - a_y_l, a_y_r, b_y_l, - b_y_r, - a_z_l, a_z_r, b_z_l, - b_z_r) + @parallel (2:(nx-1), 2:(ny-1), 2:(nz-1)) update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, _dz, + halo, ψ_x, ψ_y, ψ_z, + ξ_x, ξ_y, ξ_z, + b_x, b_y, b_z, + a_x, a_y, a_z + ) # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) @@ -213,59 +159,53 @@ end return nothing end -@views function adjoint_onestep_CPML!(grid, possrcs, dt2srctf, it) +function adjoint_onestep_CPML!(model, possrcs, dt2srctf, it) # Extract info from grid + grid = model.grid nx, ny, nz = grid.size dx, dy, dz = grid.spacing pold, pcur, pnew = grid.fields["adjold"].value, grid.fields["adjcur"].value, grid.fields["adjnew"].value fact = grid.fields["fact"].value - ψ_x_l, ψ_x_r, ψ_y_l, ψ_y_r, ψ_z_l, ψ_z_r = grid.fields["ψ_adj"].value - ξ_x_l, ξ_x_r, ξ_y_l, ξ_y_r, ξ_z_l, ξ_z_r = grid.fields["ξ_adj"].value - a_x_l, a_x_r, a_x_hl, a_x_hr, - a_y_l, a_y_r, a_y_hl, a_y_hr, - a_z_l, a_z_r, a_z_hl, a_z_hr = grid.fields["a_pml"].value - b_x_l, b_x_r, b_x_hl, b_x_hr, - b_y_l, b_y_r, b_y_hl, b_y_hr, - b_z_l, b_z_r, b_z_hl, b_z_hr = grid.fields["b_pml"].value - halo = length(a_x_r) + ψ_x, ψ_y, ψ_z = grid.fields["ψ_adj"].value + ξ_x, ξ_y, ξ_z = grid.fields["ξ_adj"].value + a_x = model.cpmlcoeffs[1].a + a_x_half = model.cpmlcoeffs[1].a_h + b_x = model.cpmlcoeffs[1].b + b_x_half = model.cpmlcoeffs[1].b_h + a_y = model.cpmlcoeffs[2].a + a_y_half = model.cpmlcoeffs[2].a_h + b_y = model.cpmlcoeffs[2].b + b_y_half = model.cpmlcoeffs[2].b_h + a_z = model.cpmlcoeffs[3].a + a_z_half = model.cpmlcoeffs[3].a_h + b_z = model.cpmlcoeffs[3].b + b_z_half = model.cpmlcoeffs[3].b_h + halo = model.cpmlparams.halo # Precompute divisions _dx = 1 / dx - _dx2 = 1 / dx^2 _dy = 1 / dy - _dy2 = 1 / dy^2 _dz = 1 / dz - _dz2 = 1 / dz^2 # update ψ arrays - @parallel_async (1:(halo+1), 1:ny, 1:nz) update_ψ_x!(ψ_x_l, ψ_x_r, pcur, - halo, _dx, nx, - a_x_hl, a_x_hr, - b_x_hl, b_x_hr) - @parallel_async (1:nx, 1:(halo+1), 1:nz) update_ψ_y!(ψ_y_l, ψ_y_r, pcur, - halo, _dy, ny, - a_y_hl, a_y_hr, - b_y_hl, b_y_hr) - @parallel_async (1:nx, 1:ny, 1:(halo+1)) update_ψ_z!(ψ_z_l, ψ_z_r, pcur, - halo, _dz, nz, - a_z_hl, a_z_hr, - b_z_hl, b_z_hr) + @parallel_async (1:2halo, 1:ny, 1:nz) update_ψ_x!( + pcur, _dx, halo, ψ_x, b_x_half, a_x_half + ) + @parallel_async (1:nx, 1:2halo, 1:nz) update_ψ_y!( + pcur, _dy, halo, ψ_y, b_y_half, a_y_half + ) + @parallel_async (1:nx, 1:ny, 1:2halo) update_ψ_z!( + pcur, _dz, halo, ψ_z, b_z_half, a_z_half + ) @synchronize # update presure and ξ arrays - @parallel (2:(nx-1), 2:(ny-1), 2:(nz-1)) update_p_CPML!(pold, pcur, pnew, halo, - fact, - _dx, _dx2, _dy, _dy2, _dz, - _dz2, nx, ny, nz, - ψ_x_l, ψ_x_r, ψ_y_l, - ψ_y_r, ψ_z_l, ψ_z_r, - ξ_x_l, ξ_x_r, ξ_y_l, - ξ_y_r, ξ_z_l, ξ_z_r, - a_x_l, a_x_r, b_x_l, - b_x_r, - a_y_l, a_y_r, b_y_l, - b_y_r, - a_z_l, a_z_r, b_z_l, - b_z_r) + @parallel (2:(nx-1), 2:(ny-1), 2:(nz-1)) update_p_CPML!( + pold, pcur, pnew, fact, _dx, _dy, _dz, + halo, ψ_x, ψ_y, ψ_z, + ξ_x, ξ_y, ξ_z, + b_x, b_y, b_z, + a_x, a_y, a_z + ) # inject sources @parallel (1:size(possrcs, 1)) inject_sources!(pnew, dt2srctf, possrcs, it) diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl index 7081163..6e8c5b4 100644 --- a/src/utils/fdgen.jl +++ b/src/utils/fdgen.jl @@ -64,6 +64,7 @@ function ∂ⁿ_(A, dim::Int; I=(:i,), _Δ=1.0, deriv::Int=1, order::Int=2, bdch N = length(I) @assert N > 0 "Need at least one index!" mirror_left, mirror_right = mirror + _Δ = deriv == 1 ? :( $_Δ ) : :( $_Δ ^ $deriv ) # right boundary checks function right_checks_recursive(coeffs, Is, A, dim, _Δ, state) is = Tuple(Is[i][dim] for i in eachindex(Is)) @@ -158,21 +159,23 @@ function ∂̃²_(A, a, b, ψ, ξ, dim::Int; I=(:i,), halo=:halo, kwargs...) ∂ψtemp = gensym(:∂ψ) iidim = gensym(:i) Astencil = ∂ⁿ_(A, dim; I=I, deriv=2, kwargs...) - ψstencil_left = ∂ⁿ_(ψ, dim; I=I, deriv=1, kwargs..., bdcheck=false) - ψstencil_right = ∂ⁿ_(ψ, dim; I=I, deriv=1, kwargs..., bdcheck=false) idim = :( $(I[dim]) ) ndim = :( size($A, $dim) ) + Iψ = [i == dim ? :($idim - 1) : I[i] for i in eachindex(I)] + IIψ = [i == dim ? :($iidim - 1) : I[i] for i in eachindex(I)] Iξ = [i == dim ? idim : I[i] for i in eachindex(I)] IIξ = [i == dim ? iidim : I[i] for i in eachindex(I)] + ψstencil_left = ∂ⁿ_(ψ, dim; I=Iψ, deriv=1, kwargs..., bdcheck=false) + ψstencil_right = ∂ⁿ_(ψ, dim; I=IIψ, deriv=1, kwargs..., bdcheck=false) return quote $∂²Atemp = $Astencil - if $idim <= ($halo + 1) + if $idim <= $halo $∂ψtemp = $ψstencil_left $ξ[$(Iξ...)] = $b[$idim ] * $ξ[$(Iξ...)] + $a[$idim ] * ($∂²Atemp + $∂ψtemp) $∂²Atemp + $∂ψtemp + $ξ[$(Iξ...)] - elseif $idim >= $ndim - $halo + elseif $idim >= $ndim - $halo + 1 + $iidim = $idim - ($ndim - $halo) + 1 + $halo $∂ψtemp = $ψstencil_right - $iidim = $idim - ($ndim - $halo) + 1 + ($halo + 1) $ξ[$(IIξ...)] = $b[$iidim] * $ξ[$(IIξ...)] + $a[$iidim] * ($∂²Atemp + $∂ψtemp) $∂²Atemp + $∂ψtemp + $ξ[$(IIξ...)] else @@ -182,18 +185,25 @@ function ∂̃²_(A, a, b, ψ, ξ, dim::Int; I=(:i,), halo=:halo, kwargs...) end function ∇ⁿ_(args...; I=(), _Δ=(), kwargs...) - @assert length(I) == length(_Δ) + N = length(I) + @assert N == length(_Δ) return Expr(:tuple, (∂ⁿ_(length(args) == 1 ? args[1] : args[i], i; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) end function ∇̃_(args...; I=(), _Δ=(), kwargs...) - @assert length(I) == length(_Δ) - return Expr(:tuple, (∂̃_(args...; _Δ=_Δ[i], I=I, kwargs..., deriv=1) for i in eachindex(_Δ))...) + N = length(I) + @assert N == length(_Δ) + A = args[1] + cpml_args = collect(args[1+(1+3*(i-1)):1+3*(i-1)+3] for i in 1:N) + return Expr(:tuple, (∂̃_(A, cpml_args[i]..., i; _Δ=_Δ[i], I=I, kwargs..., deriv=1) for i in eachindex(_Δ))...) end function ∇̃²_(args...; I=(), _Δ=(), kwargs...) - @assert length(I) == length(_Δ) - return Expr(:tuple, (∂̃²_(args...; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) + N = length(I) + @assert N == length(_Δ) + A = args[1] + cpml_args = collect(args[1+(1+4*(i-1)):1+4*(i-1)+4] for i in 1:N) + return Expr(:tuple, (∂̃²_(A, cpml_args[i]..., i; _Δ=_Δ[i], I=I, kwargs...) for i in eachindex(_Δ))...) end function extract_kwargs(args...) diff --git a/src/utils/interpolations.jl b/src/utils/interpolations.jl index 542f795..886fe6e 100644 --- a/src/utils/interpolations.jl +++ b/src/utils/interpolations.jl @@ -32,16 +32,16 @@ struct ArithmeticAverageInterpolation <: AbstractInterpolationMethod end # Harmonic average interpolation struct HarmonicAverageInterpolation <: AbstractInterpolationMethod end -@views function (itp::ArithmeticAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} - itp = Interpolations.interpolate(m, BSpline(Linear())) - return itp([i in dims ? (1.5:size(m, i)-0.5) : (1:size(m, i)) for i in 1:N]...) +function (itp::ArithmeticAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} + itp_obj = Interpolations.interpolate(m, BSpline(Linear())) + return itp_obj([i in dims ? (1.5:size(m, i)-0.5) : (1:size(m, i)) for i in 1:N]...) end -@views function (itp::HarmonicAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} - itp = Interpolations.interpolate(1 ./ m, BSpline(Linear())) - return 1 ./ itp([i in dims ? (1.5:size(m, i)-0.5) : (1:size(m, i)) for i in 1:N]...) +function (itp::HarmonicAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{Int}) where {N} + itp_obj = Interpolations.interpolate(1 ./ m, BSpline(Linear())) + return 1 ./ itp_obj([i in dims ? (1.5:size(m, i)-0.5) : (1:size(m, i)) for i in 1:N]...) end -∂f∂m(_::ArithmeticAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (2^length(dims)) +@views ∂f∂m(_::ArithmeticAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (2^length(dims)) -∂f∂m(itp::HarmonicAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = (itp(m, dims) .^ 2) ./ (m[idxs] .^ 2) ./ (2^length(dims)) \ No newline at end of file +@views ∂f∂m(itp::HarmonicAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = (itp(m, dims) .^ 2) ./ (m[idxs] .^ 2) ./ (2^length(dims)) \ No newline at end of file diff --git a/test/test_analytical_vs_numerical_acoustic_constant_density.jl b/test/test_analytical_vs_numerical_acoustic_constant_density.jl index 8c6cf74..ffc1093 100644 --- a/test/test_analytical_vs_numerical_acoustic_constant_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_constant_density.jl @@ -8,6 +8,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test analytical vs numerical solution (acoustic CD)" begin + for parall in test_backends @testset "Test 1D $(parall) analytical solution" begin @testset "Test 1D $(parall) constant velocity halo 0" begin @@ -146,4 +148,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do end end end + + end end diff --git a/test/test_analytical_vs_numerical_acoustic_variable_density.jl b/test/test_analytical_vs_numerical_acoustic_variable_density.jl index 113e667..4c7f7de 100644 --- a/test/test_analytical_vs_numerical_acoustic_variable_density.jl +++ b/test/test_analytical_vs_numerical_acoustic_variable_density.jl @@ -14,6 +14,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test analytical vs numerical solution (acoustic VD)" begin + for parall in test_backends @testset "Test 1D $(parall) analytical solution" begin @testset "Test 1D $(parall) constant velocity constant density halo 0" begin @@ -115,4 +117,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do end end end + + end end diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index ceebbcb..8b580b2 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -14,6 +14,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test forward (acoustic CD)" begin + for parall in test_backends @testset "Test 1D $(parall) single precision" begin # constant velocity setup @@ -265,4 +267,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do end end end + + end end diff --git a/test/test_gradient_acoustic_constant_density.jl b/test/test_gradient_acoustic_constant_density.jl index 7a906ae..3e9d6af 100644 --- a/test/test_gradient_acoustic_constant_density.jl +++ b/test/test_gradient_acoustic_constant_density.jl @@ -14,6 +14,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test gradient (acoustic CD)" begin + for parall in test_backends @testset "Test 1D $(parall) swgradient! with compute misfit" begin # Physics @@ -260,4 +262,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do @test grad["vp"] ≈ grad_check["vp"] end end + + end end diff --git a/test/test_gradient_acoustic_variable_density.jl b/test/test_gradient_acoustic_variable_density.jl index ce2c2d3..28d6dc0 100644 --- a/test/test_gradient_acoustic_variable_density.jl +++ b/test/test_gradient_acoustic_variable_density.jl @@ -14,6 +14,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test gradient (acoustic VD)" begin + for parall in test_backends @testset "Test 1D $(parall) swgradient! with compute misfit" begin # Physics @@ -169,4 +171,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do @test grad["rho"] ≈ grad_check["rho"] end end + + end end diff --git a/test/test_gradient_elastic_constant_density.jl b/test/test_gradient_elastic_homogeneous.jl similarity index 98% rename from test/test_gradient_elastic_constant_density.jl rename to test/test_gradient_elastic_homogeneous.jl index f7125de..9311649 100644 --- a/test/test_gradient_elastic_constant_density.jl +++ b/test/test_gradient_elastic_homogeneous.jl @@ -14,6 +14,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test gradient (elastic homogeneous)" begin + for parall in test_backends @testset "Test 2D (P-SV) $(parall) swgradient! with compute misfit" begin # Physics @@ -113,4 +115,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do @test grad["mu"] ≈ grad_check["mu"] end end + + end end diff --git a/test/test_misfit_acoustic_constant_density.jl b/test/test_misfit_acoustic_constant_density.jl index ca922f2..5492ac4 100644 --- a/test/test_misfit_acoustic_constant_density.jl +++ b/test/test_misfit_acoustic_constant_density.jl @@ -14,6 +14,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test misfit (acoustic CD)" begin + for parall in test_backends @testset "Test 1D $(parall) swmisfit!" begin # Physics @@ -75,4 +77,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do @test mis > 0 end end + + end end diff --git a/test/test_snapshotting_constant_density.jl b/test/test_snapshotting_constant_density.jl index 61ce3b4..652c0ba 100644 --- a/test/test_snapshotting_constant_density.jl +++ b/test/test_snapshotting_constant_density.jl @@ -14,6 +14,8 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do push!(test_backends, :AMDGPU) end + @testset "Test snapshotting (acoustic CD)" begin + for parall in test_backends @testset "Test 1D $(parall) single-shot snapshotting" begin # velocity setup @@ -128,4 +130,6 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do @test all(it -> !(snaps[1][it]["pcur"].value ≈ snaps[2][it]["pcur"].value), [it for it in keys(snaps[2])]) end end + + end end From ba1d9af68ebefbb38f1c2101e7528f2d097832c0 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 3 Dec 2024 11:45:20 +0100 Subject: [PATCH 098/111] Remove unnecessary @views --- src/apis/forward.jl | 4 ++-- src/apis/gradient.jl | 4 ++-- src/apis/misfit.jl | 2 +- src/apis/utils.jl | 2 +- src/models/acoustic/acou_forward.jl | 8 ++++---- src/models/acoustic/acou_gradient.jl | 4 ++-- src/models/acoustic/acou_init_bc.jl | 2 +- src/models/acoustic/acou_models.jl | 20 +++++++++---------- .../backends/Acoustic1D_CD_CPML_Serial.jl | 8 ++++---- .../backends/shared/acoustic1D_VD_xPU.jl | 6 +++--- .../backends/shared/acoustic1D_xPU.jl | 4 ++-- .../backends/shared/acoustic2D_VD_xPU.jl | 6 +++--- .../backends/shared/acoustic2D_xPU.jl | 2 +- .../backends/shared/acoustic3D_xPU.jl | 4 ++-- .../backends/shared/correlate_gradient_xPU.jl | 4 ++-- .../backends/Elastic2D_Iso_CPML_Serial.jl | 2 +- .../backends/shared/correlate_gradient_xPU.jl | 2 +- src/models/elastic/ela_forward.jl | 4 ++-- src/models/elastic/ela_gradient.jl | 4 ++-- src/models/elastic/ela_init_bc.jl | 2 +- src/models/elastic/ela_models.jl | 10 +++++----- src/utils/interpolations.jl | 4 ++-- src/utils/utils.jl | 2 +- 23 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/apis/forward.jl b/src/apis/forward.jl index 3195c55..6967b82 100644 --- a/src/apis/forward.jl +++ b/src/apis/forward.jl @@ -86,7 +86,7 @@ end ####################################################### ## single WaveSimulation object -@views function run_swforward!( +function run_swforward!( model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; @@ -131,7 +131,7 @@ end end ## :threadpersrc, multiple WaveSimulation objects -@views function run_swforward!( +function run_swforward!( model::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; diff --git a/src/apis/gradient.jl b/src/apis/gradient.jl index 37e7411..fc9b9b2 100644 --- a/src/apis/gradient.jl +++ b/src/apis/gradient.jl @@ -105,7 +105,7 @@ end ####################################################### ## single WaveSimulation object -@views function run_swgradient!( +function run_swgradient!( model::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; @@ -149,7 +149,7 @@ end end ## :threadpersrc, multiple WaveSimulation objects -@views function run_swgradient!( +function run_swgradient!( model::Vector{<:WaveSimulation{T, N}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; diff --git a/src/apis/misfit.jl b/src/apis/misfit.jl index 19daf1f..6ee0015 100644 --- a/src/apis/misfit.jl +++ b/src/apis/misfit.jl @@ -79,7 +79,7 @@ end ### MISFITS ### ## single or multiple WaveSimulation objects -@views function run_swmisfit!( +function run_swmisfit!( model::Union{WaveSimulation{T, N}, Vector{<:WaveSimulation{T, N}}}, matprop::MaterialProperties{T, N}, shots::Vector{<:Shot{T}}; diff --git a/src/apis/utils.jl b/src/apis/utils.jl index 01369fc..9a1d649 100644 --- a/src/apis/utils.jl +++ b/src/apis/utils.jl @@ -1,6 +1,6 @@ ### UPDATE MATERIAL PROPERTIES ## -@views function set_wavesim_matprop!(wavesim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}) where {T, N} +function set_wavesim_matprop!(wavesim::WaveSimulation{T, N}, matprop::MaterialProperties{T, N}) where {T, N} @debug "Checking new material properties" check_matprop(wavesim, matprop) @debug "Updating WaveSimulation material properties" diff --git a/src/models/acoustic/acou_forward.jl b/src/models/acoustic/acou_forward.jl index cc9dc70..6bf9c0d 100644 --- a/src/models/acoustic/acou_forward.jl +++ b/src/models/acoustic/acou_forward.jl @@ -3,7 +3,7 @@ swforward_1shot!(model::AcousticWaveSimulation, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) # Scaling for AcousticCDWaveSimulation -@views function possrcrec_scaletf(model::AcousticWaveSimulation{T}, shot::ScalarShot{T}) where {T} +function possrcrec_scaletf(model::AcousticWaveSimulation{T}, shot::ScalarShot{T}) where {T} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(model, shot.srcs.positions) posrecs = find_nearest_grid_points(model, shot.recs.positions) @@ -19,7 +19,7 @@ swforward_1shot!(model::AcousticWaveSimulation, args...) = swforward_1shot!(Boun return possrcs, posrecs, scal_srctf end -@views function swforward_1shot!( +function swforward_1shot!( ::CPMLBoundaryCondition, model::AcousticCDCPMLWaveSimulation{T, N}, shot::ScalarShot{T} @@ -64,7 +64,7 @@ end ##################################################### # Scaling for AcousticVDStaggeredCPMLWaveSimulation -@views function possrcrec_scaletf(model::AcousticVDStaggeredCPMLWaveSimulation{T}, shot::ScalarShot{T}) where {T} +function possrcrec_scaletf(model::AcousticVDStaggeredCPMLWaveSimulation{T}, shot::ScalarShot{T}) where {T} # find nearest grid points indexes for both sources and receivers possrcs = find_nearest_grid_points(model, shot.srcs.positions) posrecs = find_nearest_grid_points(model, shot.recs.positions) @@ -80,7 +80,7 @@ end return possrcs, posrecs, scal_srctf end -@views function swforward_1shot!( +function swforward_1shot!( ::CPMLBoundaryCondition, model::AcousticVDStaggeredCPMLWaveSimulation{T, N}, shot::ScalarShot{T} diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 678aebd..22b2d0b 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -1,7 +1,7 @@ swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = swgradient_1shot!(BoundaryConditionTrait(model), model, args...; kwargs...) -@views function swgradient_1shot!( +function swgradient_1shot!( ::CPMLBoundaryCondition, model::AcousticCDWaveSimulation{T, N}, shot::ScalarShot{T}, @@ -94,7 +94,7 @@ swgradient_1shot!(model::AcousticWaveSimulation, args...; kwargs...) = return Dict("vp" => gradient) end -@views function swgradient_1shot!( +function swgradient_1shot!( ::CPMLBoundaryCondition, model::AcousticVDStaggeredCPMLWaveSimulation{T, N}, shot::ScalarShot{T}, diff --git a/src/models/acoustic/acou_init_bc.jl b/src/models/acoustic/acou_init_bc.jl index 7960cf9..0f47f16 100644 --- a/src/models/acoustic/acou_init_bc.jl +++ b/src/models/acoustic/acou_init_bc.jl @@ -4,7 +4,7 @@ init_bdc!(model::AcousticWaveSimulation, srcs::Sources) = init_bdc!(::ReflectiveBoundaryCondition, model::AcousticWaveSimulation, srcs::Sources) = nothing -@views function init_bdc!( +function init_bdc!( ::CPMLBoundaryCondition, model::AcousticWaveSimulation, srcs::Sources diff --git a/src/models/acoustic/acou_models.jl b/src/models/acoustic/acou_models.jl index 31a0244..344c06c 100644 --- a/src/models/acoustic/acou_models.jl +++ b/src/models/acoustic/acou_models.jl @@ -2,7 +2,7 @@ # Functions for all AcousticWaveSimulation subtypes -@views function check_courant_condition(model::AcousticWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} +function check_courant_condition(model::AcousticWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.grid.spacing .^ 2)) courant = vel_max * model.dt * tmp @@ -29,7 +29,7 @@ end # Functions for all AcousticCDWaveSimulation subtypes -@views function check_matprop(model::AcousticCDWaveSimulation{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +function check_matprop(model::AcousticCDWaveSimulation{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == model.grid.size "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(model.grid.size)" @@ -38,7 +38,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticCDWaveSimulation{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} +function update_matprop!(model::AcousticCDWaveSimulation{T, N}, matprop::VpAcousticCDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) # Precompute factors @@ -198,7 +198,7 @@ end ########################################################### -@views function find_nearest_grid_points(model::AcousticCDCPMLWaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} +function find_nearest_grid_points(model::AcousticCDCPMLWaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} # source time functions nsrcs = size(positions, 1) # number of sources ncoos = size(positions, 2) # number of coordinates @@ -213,7 +213,7 @@ end # Specific functions for AcousticCDCPMLWaveSimulation -@views function reset!(model::AcousticCDCPMLWaveSimulation) +function reset!(model::AcousticCDCPMLWaveSimulation) reset!(model.grid; except=["fact"]) if model.checkpointer !== nothing reset!(model.checkpointer) @@ -232,7 +232,7 @@ GridTrait(::Type{<:AcousticCDCPMLWaveSimulation}) = LocalGrid() # Functions for all AcousticVDStaggeredWaveSimulation subtypes -@views function check_courant_condition(model::AcousticVDStaggeredWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} +function check_courant_condition(model::AcousticVDStaggeredWaveSimulation{T, N}, vp::Array{T, N}) where {T, N} vel_max = get_maximum_func(model)(vp) tmp = sqrt(sum(1 ./ model.grid.spacing .^ 2)) courant = vel_max * model.dt * tmp * 7 / 6 # 7/6 comes from the higher order stencil @@ -255,7 +255,7 @@ function check_numerics( @assert ppw >= min_ppw "Not enough points per wavelengh!" end -@views function check_matprop(model::AcousticVDStaggeredWaveSimulation{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +function check_matprop(model::AcousticVDStaggeredWaveSimulation{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Checks @assert ndims(matprop.vp) == ndims(matprop.rho) == N "Material property dimensionality must be the same as the wavesim!" @assert size(matprop.vp) == size(matprop.rho) == model.grid.size "Material property number of grid points must be the same as the wavesim! \n $(size(matprop.vp)), $(size(matprop.rho)), $(model.grid.size)" @@ -265,7 +265,7 @@ end check_courant_condition(model, matprop.vp) end -@views function update_matprop!(model::AcousticVDStaggeredWaveSimulation{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} +function update_matprop!(model::AcousticVDStaggeredWaveSimulation{T, N}, matprop::VpRhoAcousticVDMaterialProperties{T, N}) where {T, N} # Update material properties copyto!(model.matprop.vp, matprop.vp) copyto!(model.matprop.rho, matprop.rho) @@ -274,7 +274,7 @@ end precompute_fact!(model) end -@views function precompute_fact!(model::AcousticVDStaggeredWaveSimulation{T, N}) where {T, N} +function precompute_fact!(model::AcousticVDStaggeredWaveSimulation{T, N}) where {T, N} # Precompute 1/m0 * dt factor copyto!(model.grid.fields["fact_m0"].value, model.matprop.vp .^ 2 .* model.matprop.rho .* model.dt) # Precompute m1 * dt factor by interpolation @@ -448,7 +448,7 @@ end # Specific functions for AcousticVDStaggeredCPMLWaveSimulation -@views function reset!(model::AcousticVDStaggeredCPMLWaveSimulation) +function reset!(model::AcousticVDStaggeredCPMLWaveSimulation) # Reset computational arrays reset!(model.grid; except=["fact_m0", "fact_m1_stag"]) if model.checkpointer !== nothing diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index 052f757..635b433 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -13,7 +13,7 @@ end ones = Base.ones zeros = Base.zeros -@views function inject_sources!(pnew, dt2srctf, possrcs, it) +function inject_sources!(pnew, dt2srctf, possrcs, it) _, nsrcs = size(dt2srctf) for i in 1:nsrcs isrc = floor(Int, possrcs[i, 1]) @@ -21,7 +21,7 @@ zeros = Base.zeros end end -@views function record_receivers!(pnew, traces, posrecs, it) +function record_receivers!(pnew, traces, posrecs, it) _, nrecs = size(traces) for s in 1:nrecs irec = floor(Int, posrecs[s, 1]) @@ -40,7 +40,7 @@ function update_ψ!(pcur, _dx, halo, ψ_x, b_x_half, a_x_half) end end -@views function update_p_CPML!( +function update_p_CPML!( pold, pcur, pnew, fact, _dx, nx, halo, ψ_x, ξ_x, b_x, a_x ) @@ -59,7 +59,7 @@ end end end -@views prescale_residuals!(residuals, posrecs, fact) = +prescale_residuals!(residuals, posrecs, fact) = for ir in axes(posrecs, 1) irec = floor(Int, posrecs[ir, 1]) for it in axes(residuals, 1) # nt diff --git a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl index 4f70b72..dec4e14 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_VD_xPU.jl @@ -57,13 +57,13 @@ end return nothing end -@views function prescale_residuals!(residuals, posrecs, fact) +function prescale_residuals!(residuals, posrecs, fact) nrecs = size(posrecs, 1) nt = size(residuals, 1) @parallel (1:nt, 1:nrecs) prescale_residuals_kernel!(residuals, posrecs, fact) end -@views function forward_onestep_CPML!( +function forward_onestep_CPML!( model, possrcs, srctf, posrecs, traces, it; save_trace=true ) @@ -127,7 +127,7 @@ function adjoint_onestep_CPML!(model, possrcs, srctf, it) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) end -@views function correlate_gradient_m1!(curgrad_m1_stag, adjvcur, pold, gridspacing) +function correlate_gradient_m1!(curgrad_m1_stag, adjvcur, pold, gridspacing) _gridspacing = 1 ./ gridspacing nx = length(pold) @parallel (2:nx-2) correlate_gradient_m1_kernel_x!(curgrad_m1_stag[1], adjvcur[1], pold, _gridspacing[1]) diff --git a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl index b02a01c..6989b33 100644 --- a/src/models/acoustic/backends/shared/acoustic1D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic1D_xPU.jl @@ -49,13 +49,13 @@ end return nothing end -@views function prescale_residuals!(residuals, posrecs, fact) +function prescale_residuals!(residuals, posrecs, fact) nrecs = size(posrecs, 1) nt = size(residuals, 1) @parallel (1:nt, 1:nrecs) prescale_residuals_kernel!(residuals, posrecs, fact) end -@views function forward_onestep_CPML!( +function forward_onestep_CPML!( model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) diff --git a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl index b4ff275..977ec78 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_VD_xPU.jl @@ -82,13 +82,13 @@ end return nothing end -@views function prescale_residuals!(residuals, posrecs, fact) +function prescale_residuals!(residuals, posrecs, fact) nrecs = size(posrecs, 1) nt = size(residuals, 1) @parallel (1:nt, 1:nrecs) prescale_residuals_kernel!(residuals, posrecs, fact) end -@views function forward_onestep_CPML!( +function forward_onestep_CPML!( model, possrcs, srctf, posrecs, traces, it; save_trace=true ) @@ -177,7 +177,7 @@ function adjoint_onestep_CPML!(model, possrcs, srctf, it) @parallel (1:size(possrcs, 1)) inject_sources!(pcur, srctf, possrcs, it) end -@views function correlate_gradient_m1!(curgrad_m1_stag, adjvcur, pold, gridspacing) +function correlate_gradient_m1!(curgrad_m1_stag, adjvcur, pold, gridspacing) _gridspacing = 1 ./ gridspacing nx, ny = size(pold) @parallel (1:(nx-1), 1:ny) correlate_gradient_m1_kernel_x!(curgrad_m1_stag[1], adjvcur[1], pold, _gridspacing[1]) diff --git a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl index 0416361..370e4a8 100644 --- a/src/models/acoustic/backends/shared/acoustic2D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic2D_xPU.jl @@ -69,7 +69,7 @@ end return nothing end -@views function prescale_residuals!(residuals, posrecs, fact) +function prescale_residuals!(residuals, posrecs, fact) nrecs = size(posrecs, 1) nt = size(residuals, 1) @parallel (1:nt, 1:nrecs) prescale_residuals_kernel!(residuals, posrecs, fact) diff --git a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl index b3c190b..48fd374 100644 --- a/src/models/acoustic/backends/shared/acoustic3D_xPU.jl +++ b/src/models/acoustic/backends/shared/acoustic3D_xPU.jl @@ -87,13 +87,13 @@ end return nothing end -@views function prescale_residuals!(residuals, posrecs, fact) +function prescale_residuals!(residuals, posrecs, fact) nrecs = size(posrecs, 1) nt = size(residuals, 1) @parallel (1:nt, 1:nrecs) prescale_residuals_kernel!(residuals, posrecs, fact) end -@views function forward_onestep_CPML!( +function forward_onestep_CPML!( model, possrcs, dt2srctf, posrecs, traces, it; save_trace=true ) diff --git a/src/models/acoustic/backends/shared/correlate_gradient_xPU.jl b/src/models/acoustic/backends/shared/correlate_gradient_xPU.jl index 55ec59b..b30d47d 100644 --- a/src/models/acoustic/backends/shared/correlate_gradient_xPU.jl +++ b/src/models/acoustic/backends/shared/correlate_gradient_xPU.jl @@ -4,7 +4,7 @@ return nothing end -@views function correlate_gradient!(curgrad, adjcur, pcur, pold, pveryold, dt) +function correlate_gradient!(curgrad, adjcur, pcur, pold, pveryold, dt) _dt2 = 1 / dt^2 @parallel correlate_gradient_kernel!(curgrad, adjcur, pcur, pold, pveryold, _dt2) end @@ -15,7 +15,7 @@ end return nothing end -@views function correlate_gradient_m0!(curgrad_m0, adjpcur, pcur_corr, pcur_old, dt) +function correlate_gradient_m0!(curgrad_m0, adjpcur, pcur_corr, pcur_old, dt) _dt = 1 / dt @parallel correlate_gradient_m0_kernel!(curgrad_m0, adjpcur, pcur_corr, pcur_old, _dt) end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index 748bd9e..da40f45 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -688,7 +688,7 @@ function correlate_gradient_jhalf_kernel!(grad_μ_jhalf, adjσxz, vx, vz, factx, return nothing end -@views function correlate_gradients!(grid, vcurr, vold, dt, freetop) +function correlate_gradients!(grid, vcurr, vold, dt, freetop) nx, nz = grid.size correlate_gradient_ρ_kernel!(grid.fields["grad_ρ"].value, grid.fields["adjv"].value[1], vcurr[1], vold[1], 1 / dt) correlate_gradient_ρ_kernel!(grid.fields["grad_ρ_ihalf_jhalf"].value, grid.fields["adjv"].value[2], vcurr[2], vold[2], 1 / dt) diff --git a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl index 04b78a4..6917741 100644 --- a/src/models/elastic/backends/shared/correlate_gradient_xPU.jl +++ b/src/models/elastic/backends/shared/correlate_gradient_xPU.jl @@ -30,7 +30,7 @@ end return nothing end -@views function correlate_gradients!(grid, vcurr, vold, dt, freetop) +function correlate_gradients!(grid, vcurr, vold, dt, freetop) nx, nz = grid.size @parallel correlate_gradient_ρ_kernel!( grid.fields["grad_ρ_ihalf"].value, diff --git a/src/models/elastic/ela_forward.jl b/src/models/elastic/ela_forward.jl index 28989ba..b28be45 100644 --- a/src/models/elastic/ela_forward.jl +++ b/src/models/elastic/ela_forward.jl @@ -1,7 +1,7 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(BoundaryConditionTrait(model), model, args...) -@views function swforward_1shot!( +function swforward_1shot!( ::CPMLBoundaryCondition, model::ElasticIsoCPMLWaveSimulation{T, 2}, shot::MomentTensorShot{T, 2, MomentTensor2D{T}} @@ -90,7 +90,7 @@ swforward_1shot!(model::ElasticWaveSimulation, args...) = swforward_1shot!(Bound return end -@views function swforward_1shot!( +function swforward_1shot!( ::CPMLBoundaryCondition, model::ElasticIsoCPMLWaveSimulation{T, 2}, shot::ExternalForceShot{T, 2} diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index 27efacb..434d6c5 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -1,7 +1,7 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = swgradient_1shot!(BoundaryConditionTrait(model), model, args...; kwargs...) -@views function swgradient_1shot!( +function swgradient_1shot!( ::CPMLBoundaryCondition, model::ElasticIsoCPMLWaveSimulation{T, 2}, shot::MomentTensorShot{T, 2, MomentTensor2D{T}}, @@ -178,7 +178,7 @@ swgradient_1shot!(model::ElasticWaveSimulation, args...; kwargs...) = ) end -@views function swgradient_1shot!( +function swgradient_1shot!( ::CPMLBoundaryCondition, model::ElasticIsoCPMLWaveSimulation{T, 2}, shot::ExternalForceShot{T, 2}, diff --git a/src/models/elastic/ela_init_bc.jl b/src/models/elastic/ela_init_bc.jl index aa85256..32cc5ab 100644 --- a/src/models/elastic/ela_init_bc.jl +++ b/src/models/elastic/ela_init_bc.jl @@ -4,7 +4,7 @@ init_bdc!(model::ElasticWaveSimulation, srcs::Sources) = init_bdc!(::ReflectiveBoundaryCondition, model::ElasticWaveSimulation, srcs::Sources) = nothing -@views function init_bdc!( +function init_bdc!( ::CPMLBoundaryCondition, model::ElasticIsoWaveSimulation, srcs::Sources diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index bf29d99..a59b279 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -3,7 +3,7 @@ # Functions for all ElasticIsoWaveSimulation subtypes # Scaling for ElasticIsoWaveSimulation -@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalForceShot{T, 2}; sincinterp=false) where {T} +function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalForceShot{T, 2}; sincinterp=false) where {T} if sincinterp # interpolation coefficients for sources in vx nsrcs = size(shot.srcs.positions, 1) @@ -33,7 +33,7 @@ return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, shot.srcs.tf end -@views function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}; sincinterp=false) where {T} +function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}; sincinterp=false) where {T} if sincinterp nsrcs = size(shot.srcs.positions, 1) # interpolation coefficients for sources in σxx and σzz @@ -65,7 +65,7 @@ end -@views function check_matprop(model::ElasticIsoWaveSimulation{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} +function check_matprop(model::ElasticIsoWaveSimulation{T, N}, matprop::ElasticIsoMaterialProperties{T, N}) where {T, N} # Checks @assert all(matprop.λ .>= 0) "Lamè coefficient λ must be positive!" @assert all(matprop.μ .>= 0) "Lamè coefficient μ must be positive!" @@ -108,7 +108,7 @@ function check_numerics( return end -@views function update_matprop!(model::ElasticIsoWaveSimulation{T, 2}, matprop::ElasticIsoMaterialProperties{T, 2}) where {T} +function update_matprop!(model::ElasticIsoWaveSimulation{T, 2}, matprop::ElasticIsoMaterialProperties{T, 2}) where {T} # Update material properties copyto!(model.matprop.λ, matprop.λ) @@ -413,7 +413,7 @@ end # Specific functions for ElasticIsoCPMLWaveSimulation -@views function reset!(model::ElasticIsoCPMLWaveSimulation{T, N}) where {T, N} +function reset!(model::ElasticIsoCPMLWaveSimulation{T, N}) where {T, N} # Reset computational arrays reset!(model.grid; except=["λ", "μ", "ρ_ihalf", "ρ_jhalf", "λ_ihalf", "λ_jhalf", "μ_ihalf", "μ_jhalf", "μ_ihalf_jhalf"]) if model.checkpointer !== nothing diff --git a/src/utils/interpolations.jl b/src/utils/interpolations.jl index 886fe6e..f340a55 100644 --- a/src/utils/interpolations.jl +++ b/src/utils/interpolations.jl @@ -42,6 +42,6 @@ function (itp::HarmonicAverageInterpolation)(m::Array{<:Real, N}, dims::Vector{I return 1 ./ itp_obj([i in dims ? (1.5:size(m, i)-0.5) : (1:size(m, i)) for i in 1:N]...) end -@views ∂f∂m(_::ArithmeticAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (2^length(dims)) +∂f∂m(_::ArithmeticAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = ones(T, size(m) .- Tuple(i in dims ? 1 : 0 for i in 1:N)) ./ (2^length(dims)) -@views ∂f∂m(itp::HarmonicAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = (itp(m, dims) .^ 2) ./ (m[idxs] .^ 2) ./ (2^length(dims)) \ No newline at end of file +∂f∂m(itp::HarmonicAverageInterpolation, m::Array{T, N}, idxs, dims::Vector{Int}) where {T, N} = (itp(m, dims) .^ 2) ./ (m[idxs] .^ 2) ./ (2^length(dims)) \ No newline at end of file diff --git a/src/utils/utils.jl b/src/utils/utils.jl index 5a0e881..108a461 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -44,7 +44,7 @@ function distribsrcs(nsrc::Int, nw::Int) return grpsrc end -@views function find_nearest_grid_points(model::WaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} +function find_nearest_grid_points(model::WaveSimulation{T}, positions::Matrix{T})::Matrix{Int} where {T} # source time functions nsrcs = size(positions, 1) # number of sources ncoos = size(positions, 2) # number of coordinates From a418952b6a551402af4010882498192c675d74cf Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 3 Dec 2024 11:47:18 +0100 Subject: [PATCH 099/111] Keep only one CPML coefficients implementation --- src/models/cpmlcoeffs.jl | 140 +-------------------------------------- 1 file changed, 3 insertions(+), 137 deletions(-) diff --git a/src/models/cpmlcoeffs.jl b/src/models/cpmlcoeffs.jl index af66e6e..d34cad5 100644 --- a/src/models/cpmlcoeffs.jl +++ b/src/models/cpmlcoeffs.jl @@ -31,8 +31,8 @@ function compute_CPML_coefficientsAxis!( if halo == 0 # fix for thickness == 0 generating NaNs d0 = convert(T, 0.0) end - a_l, a_r, b_l, b_r = calc_Kab_CPML2(halo, dt, npower, d0, alpha_max, "ongrd") - a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML2(halo, dt, npower, d0, alpha_max, "halfgrd") + a_l, a_r, b_l, b_r = calc_Kab_CPML_axis(halo, dt, npower, d0, alpha_max, "ongrd") + a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML_axis(halo, dt, npower, d0, alpha_max, "halfgrd") copyto!(cpmlcoeffs.a, vcat(a_l, a_r)) copyto!(cpmlcoeffs.a_h, vcat(a_hl, a_hr)) @@ -40,7 +40,7 @@ function compute_CPML_coefficientsAxis!( copyto!(cpmlcoeffs.b_h, vcat(b_hl, b_hr)) end -function calc_Kab_CPML2( +function calc_Kab_CPML_axis( halo::Int, dt::T, npower::T, @@ -100,137 +100,3 @@ function calc_Kab_CPML2( end ################################################################# - -struct CPMLCoefficients{T, V <: AbstractVector{T}} - a_l::V - a_r::V - a_hl::V - a_hr::V - b_l::V - b_r::V - b_hl::V - b_hr::V - - function CPMLCoefficients{T, V}(halo::Int, backend::Module, sizehalfgrdplusone::Bool=false) where {T, V <: AbstractVector{T}} - if sizehalfgrdplusone - return new{T, V}( - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo + 1), - backend.zeros(T, halo + 1), - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo + 1), - backend.zeros(T, halo + 1) - ) - else - return new{T, V}( - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo), - backend.zeros(T, halo) - ) - end - end -end - -##################################### - -function compute_CPML_coefficients!( - cpmlcoeffs::CPMLCoefficients{T, V}, - vel_max::T, - dt::T, - halo::Int, - rcoef::T, - thickness::T, - f0::T -) where {T, V <: AbstractVector{T}} - # CPML coefficients (l = left, r = right, h = staggered in betweeen grid points) - alpha_max = convert(T, π * f0) # CPML α multiplicative factor (half of dominating angular frequency) - npower = convert(T, 2.0) # CPML power coefficient - d0 = convert(T, -(npower + 1) * vel_max * log(rcoef) / (2.0 * thickness)) # damping profile - if halo == 0 # fix for thickness == 0 generating NaNs - d0 = convert(T, 0.0) - end - a_l, a_r, b_l, b_r = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "ongrd") - a_hl, a_hr, b_hl, b_hr = calc_Kab_CPML(halo, dt, npower, d0, alpha_max, "halfgrd") - - copyto!(cpmlcoeffs.a_l, a_l) - copyto!(cpmlcoeffs.a_r, a_r) - copyto!(cpmlcoeffs.a_hl, a_hl) - copyto!(cpmlcoeffs.a_hr, a_hr) - copyto!(cpmlcoeffs.b_l, b_l) - copyto!(cpmlcoeffs.b_r, b_r) - copyto!(cpmlcoeffs.b_hl, b_hl) - copyto!(cpmlcoeffs.b_hr, b_hr) -end - -##################################### - -function calc_Kab_CPML( - halo::Int, - dt::T, - npower::T, - d0::T, - alpha_max_pml::T, - onwhere::String; - K_max_pml::Union{T, Nothing}=nothing -)::Tuple{Array{T}, Array{T}, Array{T}, Array{T}} where {T} - @assert halo >= 0.0 - - Kab_size = halo - # shift for half grid coefficients - if onwhere == "halfgrd" - Kab_size += 1 - shift = 0.5 - elseif onwhere == "ongrd" - shift = 0.0 - else - error("Wrong onwhere parameter!") - end - - # distance from edge node - dist = collect(LinRange(0 - shift, Kab_size - shift - 1, Kab_size)) - if onwhere == "halfgrd" - dist[1] = 0 - end - if halo != 0 - normdist_left = reverse(dist) ./ halo - normdist_right = dist ./ halo - else - normdist_left = reverse(dist) - normdist_right = dist - end - - if K_max_pml === nothing - K_left = 1.0 - else - K_left = 1.0 .+ (K_max_pml - 1.0) .* (normdist_left .^ npower) - end - d_left = d0 .* (normdist_left .^ npower) - alpha_left = alpha_max_pml .* (1.0 .- normdist_left) - b_left = exp.(.-(d_left ./ K_left .+ alpha_left) .* dt) - a_left = d_left .* (b_left .- 1.0) ./ (K_left .* (d_left .+ K_left .* alpha_left)) - - if K_max_pml === nothing - K_right = 1.0 - else - K_right = 1.0 .+ (K_max_pml - 1.0) .* (normdist_right .^ npower) - end - d_right = d0 .* (normdist_right .^ npower) - alpha_right = alpha_max_pml .* (1.0 .- normdist_right) - b_right = exp.(.-(d_right ./ K_right .+ alpha_right) .* dt) - a_right = d_right .* (b_right .- 1.0) ./ (K_right .* (d_right .+ K_right .* alpha_right)) - - if K_max_pml === nothing - return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right) - else - return convert.(T, a_left), convert.(T, a_right), convert.(T, b_left), convert.(T, b_right), convert.(T, K_left), convert.(T, K_right) - end -end - -##################################### From 25b4ea63fa1c0f6191143e519263d2b506d18aba Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 3 Dec 2024 15:07:35 +0100 Subject: [PATCH 100/111] Fix mirroring for free surface --- src/utils/fdgen.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/fdgen.jl b/src/utils/fdgen.jl index 6e8c5b4..ddc8221 100644 --- a/src/utils/fdgen.jl +++ b/src/utils/fdgen.jl @@ -106,7 +106,7 @@ function ∂ⁿ_(A, dim::Int; I=(:i,), _Δ=1.0, deriv::Int=1, order::Int=2, bdch if mirror_left # construct the mirrored stencil original_stencil = Expr(:call, :+, [:($(coeffs[i]) * $A[$(Is[i]...)]) for i in state+1:width]...) # original stencil with indices beyond boundary - mirrored_Is = Tuple( Tuple(i == dim ? :($(Is[state+1][i])+$(j-1)) : Is[state+1][i] for i in 1:N) for j in 1:state) # indices mirrored around boundary + mirrored_Is = Tuple( Tuple(i == dim ? :($(Is[state+1][i])+$(state-j)) : Is[state+1][i] for i in 1:N) for j in 1:state) # indices mirrored around boundary mirrored_stencil = Expr(:call, :+, [:($(coeffs[i]) * -$A[$(mirrored_Is[i]...)]) for i in 1:state]...) # mirrored stencil with indices up to boundary but mirrored stencil = Expr(:call, :*, Expr(:call, :+, mirrored_stencil, original_stencil), _Δ) # sum the original and mirrored stencils else From f5e81f7c946e8586f02b8ae1cbdf59d1e88a0474 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Tue, 21 Jan 2025 13:50:21 +0100 Subject: [PATCH 101/111] Fix arbitrary source / receivers interpolations with corrected mirrored coefficients --- src/SeismicWaves.jl | 2 +- src/models/elastic/ela_models.jl | 16 +- src/utils/utils.jl | 300 +++++++++++++------------------ 3 files changed, 137 insertions(+), 181 deletions(-) diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index 079abd3..b1f83b4 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -52,10 +52,10 @@ include("traits/grid.jl") # Utils include("utils/interpolations.jl") +include("utils/grids.jl") include("utils/utils.jl") include("utils/checks.jl") include("utils/fields.jl") -include("utils/grids.jl") include("utils/checkpointers.jl") include("utils/snapshotter.jl") diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index a59b279..fa8e7d5 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -7,14 +7,14 @@ function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalFor if sincinterp # interpolation coefficients for sources in vx nsrcs = size(shot.srcs.positions, 1) - srccoeij_vx, srccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=0.0) + srccoeij_vx, srccoeval_vx = spread_positions(model.grid, shot.srcs.positions; shift=(model.grid.spacing[1]/2, 0.0), mirror=false) # interpolation coefficients for sources in vz - srccoeij_vz, srccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=model.grid.spacing[2]/2) + srccoeij_vz, srccoeval_vz = spread_positions(model.grid, shot.srcs.positions; shift=(0.0, model.grid.spacing[2]/2), mirror=false) nrecs = size(shot.recs.positions, 1) # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=0.0) + reccoeij_vx, reccoeval_vx = spread_positions(model.grid, shot.recs.positions; shift=(model.grid.spacing[1]/2, 0.0), mirror=false) # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=model.grid.spacing[2]/2) + reccoeij_vz, reccoeval_vz = spread_positions(model.grid, shot.recs.positions; shift=(0.0, model.grid.spacing[2]/2), mirror=false) else src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) @@ -37,14 +37,14 @@ function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTenso if sincinterp nsrcs = size(shot.srcs.positions, 1) # interpolation coefficients for sources in σxx and σzz - srccoeij_xx, srccoeval_xx = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=0.0, zstart=0.0) + srccoeij_xx, srccoeval_xx = spread_positions(model.grid, shot.srcs.positions; shift=(0.0, 0.0), mirror=true) # interpolation coefficients for sources in σxz - srccoeij_xz, srccoeval_xz = spread2D(model.grid.spacing, model.grid.size, shot.srcs.positions, nsrcs; xstart=model.grid.spacing[1]/2, zstart=model.grid.spacing[2]/2) + srccoeij_xz, srccoeval_xz = spread_positions(model.grid, shot.srcs.positions; shift=(model.grid.spacing[1]/2, model.grid.spacing[2]/2), mirror=true) nrecs = size(shot.recs.positions, 1) # interpolation coefficients for receivers in vx - reccoeij_vx, reccoeval_vx = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=model.grid.spacing[1]/2, zstart=0.0) + reccoeij_vx, reccoeval_vx = spread_positions(model.grid, shot.recs.positions; shift=(model.grid.spacing[1]/2, 0.0), mirror=false) # interpolation coefficients for receivers in vz - reccoeij_vz, reccoeval_vz = spread2D(model.grid.spacing, model.grid.size, shot.recs.positions, nrecs; xstart=0.0, zstart=model.grid.spacing[2]/2) + reccoeij_vz, reccoeval_vz = spread_positions(model.grid, shot.recs.positions; shift=(0.0, model.grid.spacing[2]/2), mirror=false) else src_idx_positions = find_nearest_grid_points(model, shot.srcs.positions) rec_idx_positions = find_nearest_grid_points(model, shot.recs.positions) diff --git a/src/utils/utils.jl b/src/utils/utils.jl index 108a461..c4d3a6c 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -65,214 +65,170 @@ Kaiser windowing function. # Parameters - `x`: coordinate of points - - `x0`: coordinate of source or receiver point - - `b`: 'b' coefficient + - `β`: Kaiser shape coefficient - `r`: cut-off radius """ -function kaiser(x::Vector, x0::T, b::T, r::T) where {T} - # Kaiser window function - # r is window half with - # Rule of thumb for finite diff.: - # b=4.14 b=6.31 - # r = 4.0*dx - w = zeros(T, length(x)) - for i in 1:length(x) - xcur = x[i] - x0 - if -r <= xcur <= r - w[i] = besseli(0, b * (sqrt(1 - (xcur / r)^2))) / besseli(0, b) - else - w[i] = 0.0 - end - end - return w -end - -##################################################################### +kaiser(x, r, β) = (-r <= x <= r ? besseli(0, β * sqrt(1 - (x / r)^2)) / besseli(0, β) : 0.0) """ -Compute 1-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. +Band limited delta function by combining Kaiser window and sinc function. # Parameters - - `xstart`: origin coordinate of the grid + - `x`: coordinate of points + - `x0`: coordinate of delta function center + - `r`: cut-off radius in number of grid points + - `β`: Kaiser shape coefficient - `Δx`: grid spacing - - `kind`: :monopole or :dipole, i.e., using sinc or derivative of sinc - - `npts` (optional): half-number of grid points for the window - - `beta` (optional): 'beta' parameter for the Kaiser windowing function """ -function coeffsinc1D(xstart::Real, Δx::Real, xcenter::Real, kind::Symbol, nx::Int; - npts::Int64=4, beta::Union{Nothing, Real}=nothing) - ## Coefficients for sinc interpolation - ## in 1D - ## xstart is the x coordinate of first node in the regular grid - ## - ## Rule of thumb for npts==4 [Hicks 2002, Geophysics]: - ## beta=4.14 for monopoles, - ## beta=4.40 for dipoles - ### - ### Julia: sinc(x) = - ### \sin(\pi x) / (\pi x) if x \neq 0, and 1 if x = 0 - ### - @assert xcenter >= xstart - @assert xcenter <= (nx - 1) * Δx + xstart - - if beta === nothing - if kind == :monopole - beta = 4.14 - elseif kind == :dipole - beta = 4.40 - end - end - - radius = npts * Δx - # Assuming x from grid starts at xstart - xh = (xcenter - xstart) / Δx - ix = floor(Int64, xh + 1) - if mod((xcenter - xstart), Δx) == 0.0 - ixsta = ix - npts - ixend = ix + npts - else - ixsta = ix - npts + 1 - ixend = ix + npts - end - x = [xstart + Δx * (i - 1) for i in ixsta:ixend] - indexes = ixsta:ixend +modd(x, x0, r, β, Δx) = begin + res = 1 / Δx * kaiser(x - x0, r * Δx, β) * sinc((x - x0) / Δx) + return res ≈ 0 ? 0.0 : res +end - if kind == :monopole - # interpolating sinc(x) = sin(pi*x)/(pi*x) see Julia definition - intrpsinc = sinc.((x .- xcenter) ./ Δx) # factor 1/Δx ?? +""" +Band limited delta function with reflected coefficients over the boundary. +This function keeps the property of having integral equal to one even when the sinc function goes over the boundary. +This function should be used to inject / record velocities. - elseif kind == :dipole - # derivative of sinc - # cosc(x) is the derivative of sinc(x) in Julia - intrpsinc = cosc.((x .- xcenter) ./ Δx) +# Parameters - else - error("coeffsinc1d(): Wrong argument 'kind'.") + - `x`: coordinate of points + - `x0`: coordinate of delta function center + - `xbl`: coordinate of left boundary + - `xbr`: coordinate of right boundary + - `r`: cut-off radius in number of grid points + - `β`: Kaiser shape coefficient + - `Δx`: grid spacing +""" +modd_refl(x, x0, xbl, xbr, r, β, Δx) = begin + res = modd(x, x0, r, β, Δx) + if x < xbl || x > xbr + return 0.0 end - # apply Kaiser windowing - kaix = kaiser(x, xcenter, beta, radius) - itpfun = kaix .* intrpsinc - # return also indices of window (as a range) - return itpfun, indexes + res_left = modd(xbl - (x - xbl), x0, r * Δx, β, Δx) + res_right = modd(xbr + (xbr - x), x0, r * Δx, β, Δx) + res_tot = res + res_left + res_right + return res_tot ≈ 0 ? 0.0 : res_tot end -##################################################################### - """ -Compute 2-D coefficients for windowed (Kaiser) sync interpolation of source or receiver position. +Band limited delta function with mirrored coefficients over the boundary. +This delta functions should be used to inject / record pressure or stress when free surface boundary conditions are used. # Parameters - - `xstart`, `zstart`: origin coordinates of the grid - - `Δx`,`Δz` : grid spacing - - `xcenter`, `zcenter`: coordinates of source or receiver point - - `nx`,`nz`: grid size in x and y - - `kind`: vector of symbols :monopole or :dipole, i.e., using sinc or derivative of sinc - - `npts` (optional): half-number of grid points for the window - - `beta` (optional): 'beta' parameter for the Kaiser windowing function + - `x`: coordinate of points + - `x0`: coordinate of delta function center + - `xbl`: coordinate of left boundary + - `xbr`: coordinate of right boundary + - `r`: cut-off radius in number of grid points + - `β`: Kaiser shape coefficient + - `Δx`: grid spacing """ -function coeffsinc2D(xstart::Real, zstart::Real, Δx::Real, Δz::Real, xcenter::Real, zcenter::Real, - nx::Int, nz::Int, kind::Vector{Symbol}; - npts::Int64=4, beta::Union{Nothing, Real}=nothing) - - ## Calculate the 2D array of coefficients - xcoe, xidx = coeffsinc1D(xstart, Δx, xcenter, kind[1], nx; npts=npts, beta=beta) - zcoe, zidx = coeffsinc1D(zstart, Δz, zcenter, kind[2], nz; npts=npts, beta=beta) - - function reflectcoeffsinc(coe, idx, nmax) - # - # "Reflect" coefficients past the edge, i.e., mirror and subtract them - # from the internal ones - # - if idx[1] < 1 - # We are before the edge - nab = count(idx .< 1) - # get the "reflected" coefficients - reflcoe = coe[nab:-1:1] - # Create a new set of indices excluding those above the surface - idx = idx[nab+1:end] - # Hicks 2002 Geophysics - # Subtract coefficients past the edge - coe[nab+1:2*nab] .-= reflcoe - # Create a new set of coefficients excluding those above the surface - coe = coe[nab+1:end] - - elseif idx[end] > nmax - # We are past the edge - nab = count(idx .> nmax) - # get the "reflected" coefficients - reflcoe = coe[end:-1:end-nab+1] - # Create a new set of indices excluding those above the surface - idx = idx[1:end-nab] - # Hicks 2002 Geophysics - # Subtract coefficients past the edge - coe[end-2*nab+1:end-nab] .-= reflcoe - # Create a new set of coefficients excluding those above the surface - coe = coe[1:end-nab] - end - - return coe, idx +modd_mirror(x, x0, xbl, xbr, r, β, Δx) = begin + res = modd(x, x0, r, β, Δx) + if x < xbl || x > xbr + return 0.0 end + res_left = modd(xbl - (x - xbl), x0, r * Δx, β, Δx) + res_right = modd(xbr + (xbr - x), x0, r * Δx, β, Δx) + res_tot = res - res_left - res_right + return res_tot ≈ 0 ? 0.0 : res_tot +end - ## Crop and reflect coefficients if they go beyond model edges [Hicks 2002, Geophysics] - xcoe, xidx = reflectcoeffsinc(xcoe, xidx, nx) - zcoe, zidx = reflectcoeffsinc(zcoe, zidx, nz) +""" +Compute coefficients for a 1D band limited delta function. - # tensor product of coeff. in x and z - xzcoeff = zeros(typeof(xcenter), length(xcoe), length(zcoe)) - for j in eachindex(zcoe) - for i in eachindex(xcoe) - xzcoeff[i, j] = xcoe[i] * zcoe[j] - end - end +# Parameters - return xidx, zidx, xzcoeff -end + - `x0`: coordinate of delta function center + - `dx`: grid spacing + - `nx`: number of grid points + - `r`: cut-off radius in number of grid points + - `β`: Kaiser shape coefficient + - `xstart`: coordinate of the first grid point (from the left) + - `mirror`: controls if the delta function is mirrored over the boundary or not + - `xbl`: coordinate of left boundary + - `xbr`: coordinate of right boundary +""" -function modd_2D_grid(x0::T, y0::T, dx::T, dy::T, nx::Int, ny::Int, r::Int=4, β::Int=10, xstart::T=0, ystart::T=0) where {T} +function coeffsinc1D(x0::T, dx::T, nx::Int, r::Int, β::T, xstart::T, mirror::Bool, xbl::T, xbr::T) where {T} + # Grid points xs = range(xstart; length=nx, step=dx) - ys = range(ystart; length=ny, step=dy) - dd_coeffs = Vector{Tuple{Int, Int, T}}() - - kaiser(x, r, β) = (-r <= x <= r ? besseli(0, β * sqrt(1 - (x / r)^2)) / besseli(0, β) : 0.0) - modd_(x, x0, r, β, Δx) = 1 / Δx * kaiser(x - x0, r, β) * sinc((x - x0) / Δx) - modd(x, x0, r, β, Δx) = begin - res = modd_(x, x0, r * Δx, β, Δx) - return res ≈ 0 ? 0.0 : res - end - modd_2D(x, y, x0, y0, r, β, Δx, Δy) = modd(x, x0, r, β, Δx) * modd(y, y0, r, β, Δy) + # Placeholders for indices and coefficients + idxs, coeffs = Vector{Int}(), Vector{T}() + # Find nearest grid point to the delta function center findnearest(x, xs) = argmin(abs.(x .- xs)) - i0 = findnearest(x0, xs) - j0 = findnearest(y0, ys) - for i in i0-r-1:i0+r+1, j in j0-r-1:j0+r+1 - if i < 1 || i > nx || j < 1 || j > ny + # Compute coefficients + for idx in i0-r-1:i0+r+1 + # Check if the index is within the grid + if idx < 1 || idx > nx continue end - ddij = modd_2D(xs[i], ys[j], x0, y0, r, β, dx, dy) - if ddij != 0.0 - push!(dd_coeffs, (i, j, ddij)) + # Compute coefficient using modified band limited delta function + if mirror + coe = modd_mirror(xs[idx], x0, xbl, xbr, r, β, dx) + else + coe = modd_refl(xs[idx], x0, xbl, xbr, r, β, dx) + end + # Store non-zero coefficients + if !(coe ≈ 0) + push!(idxs, idx) + push!(coeffs, coe) end end - - return dd_coeffs + return idxs, coeffs end -function spread2D(spacing::NTuple{2, T}, size::NTuple{2, Int}, positions::Matrix{T}, npositions; r::Int=4, β::Int=10, xstart::T=0, zstart::T=0) where {T} - coeij = Vector{Matrix{Int}}(undef, npositions) - coeval = Vector{Vector{T}}(undef, npositions) - for p in 1:npositions - x0, y0 = positions[p, 1], positions[p, 2] - dd_coeffs = modd_2D_grid(x0, y0, spacing[1], spacing[2], size[1], size[2], r, β, xstart, zstart) - coeij[p] = zeros(Int, length(dd_coeffs), 2) - coeval[p] = zeros(T, length(dd_coeffs)) - for (idx, (i, j, val)) in enumerate(dd_coeffs) - coeij[p][idx, :] .= (i, j) - coeval[p][idx] = val +""" +Computes coefficients and indices of the grid for arbitrarely placed sources or receivers using band limited delta functions coefficients. + +# Parameters + + - `grid`: grid object + - `positions`: matrix of source or receiver positions + - `shifts`: shift of the source or receiver positions + - `mirror`: controls if the delta function is mirrored over the boundary or not + - `r`: cut-off radius in number of grid points (default = 4) + - `β`: Kaiser shape coefficient (default = 6.31) +""" +function spread_positions( + grid::SeismicWaves.UniformFiniteDifferenceGrid{N, T}, + positions::Matrix{T}; + shift::NTuple{N, T}=ntuple(_ -> 0.0, N), + mirror::Bool=false, + r::Int=4, + β::T=6.31 +) where {N, T} + # Get number of positions to spread + npos = size(positions, 1) + # Spread each position + idxs = Vector{Matrix{Int}}(undef, npos) + coeffs = Vector{Vector{T}}(undef, npos) + for p in 1:npos + # For each dimension + idxs_dims = Vector{Vector{Int}}(undef, N) + coeffs_dims = Vector{Vector{T}}(undef, N) + for n in 1:N + # Compute coefficients in n-th dimension + idxs_nth, coeffs_nth = coeffsinc1D(positions[p, n], grid.spacing[n], grid.size[n], r, β, shift[n], mirror, 0.0, grid.extent[n]) + idxs_dims[n] = idxs_nth + coeffs_dims[n] = coeffs_nth + end + # Compute tensor product of indices and coefficients + totlen = prod(length.(idxs_dims)) + idxs[p] = zeros(Int, totlen, N) + coeffs[p] = zeros(T, totlen) + for (ii, idx_comb) in enumerate(Iterators.product(idxs_dims...)) + idxs[p][ii, :] .= idx_comb + end + for (ii, coeff_comb) in enumerate(Iterators.product(coeffs_dims...)) + coeffs[p][ii] = prod(coeff_comb) end end - return coeij, coeval + return idxs, coeffs end ##################################################################### From d1fec8601127adae3a274a0b66b757576c20a232 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 3 Feb 2025 14:18:07 +0100 Subject: [PATCH 102/111] Merge branch "main" into develop --- .github/workflows/documentation.yml | 36 +++++++++++++++++++++ .github/workflows/test.yml | 49 +++++++++++++++++++++++++++++ .gitlab-ci.yml | 45 -------------------------- README.md | 13 +++----- docs/make.jl | 14 ++++----- 5 files changed, 96 insertions(+), 61 deletions(-) create mode 100644 .github/workflows/documentation.yml create mode 100644 .github/workflows/test.yml delete mode 100644 .gitlab-ci.yml diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 0000000..be23b30 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,36 @@ +name: Build documentation + +on: + push: + branches: + - main # update to match your development branch (master, main, dev, trunk, ...) + - develop + tags: + - 'v*' + pull_request: + branches: + - develop + +jobs: + build_docs: + permissions: + actions: write + contents: write + pull-requests: read + statuses: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + with: + version: '1' + - name: Julia cache + if: ${{ !env.ACT }} + uses: julia-actions/cache@v2 + - name: Install dependencies + run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' + - name: Build docs and deploy + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key + run: julia --project=docs/ docs/make.jl diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..d419c63 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,49 @@ +# Run package tests +name: Package tests + +on: + push: + branches: + - main + - develop + tags: '*' + pull_request: + branches: + - develop + types: + - ready_for_review + - synchronize + +# needed to allow julia-actions/cache to delete old caches that it has created +permissions: + actions: write + contents: read + +jobs: + run_tests: + name: Julia ${{ matrix.julia-version }} - ${{ matrix.os }} - ${{ matrix.arch }} + runs-on: ${{ matrix.os }} + if : github.event.pull_request.draft == false + strategy: + matrix: + julia-version: ['1'] #['lts', '1', 'pre'] + arch: [x64] #[x64, x86] + os: [ubuntu-latest, macOS-latest] #[ubuntu-latest, windows-latest, macOS-latest] + include: + - os: macOS-latest + julia-version: '1' + arch: aarch64 + + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + with: + version: ${{ matrix.julia-version }} + arch: ${{ matrix.arch }} + - name: Julia cache + if: ${{ !env.ACT }} + uses: julia-actions/cache@v2 + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 + # with: + # annotate: true diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 4e149ec..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,45 +0,0 @@ -image: julia:1.9 # image comes from Docker hub - -before_script: - # - export - #- echo $(pwd) - #- echo $(ls ./) - ## - julia --project=@. -e 'ENV["JULIA_PKG_USE_CLI_GIT"]=true; using Pkg; Pkg.add(url="https://gitlab.com/JuliaGeoph/GeoPolygons.jl")' - ## The General registry MUST be added explicitly otherwise only JuliaGeophRegistry will be available. - - julia --project=@. -e 'import Pkg; Pkg.Registry.add("General"); Pkg.Registry.add( Pkg.RegistrySpec(url="https://gitlab.com/JuliaGeoph/JuliaGeophRegistry"))' - - julia --project=@. -e 'import Pkg; Pkg.Registry.status()' - - julia --project=@. -e 'import Pkg; Pkg.build()' - - apt-get -qq update; apt-get -y install git rsync - -default: - stage: test - script: - - julia --project=@. -e "import Pkg; Pkg.test(; coverage = false)" - # - julia --project=test/coverage -e 'import Pkg; Pkg.instantiate()' - # - julia --project=test/coverage test/coverage/coverage-summary.jl - rules: - - if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG ) - -pages: - stage: deploy - script: - - julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - - julia --project=docs --color=yes docs/make.jl - #- echo $(ls ./) - # - git branch -a - ## the following lines needed to have versioned docs from Documenter.jl - - mkdir tmppub ; mv .git tmppub/ - - cd tmppub - - echo $(ls -a) - - git fetch; git checkout gl-pages ; git pull - - echo $(ls ) - - rsync -a --exclude=".git" --exclude=".gitignore" ../tmppub/* ../public/ - # - echo $(ls docs/build/) - ## - mv docs/build public # move to the directory picked up by Gitlab pages - artifacts: - paths: - - public - rules: - - if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH ) && $DOCUMENTER_KEY - - if: ($CI_COMMIT_TAG && $CI_DEFAULT_BRANCH) && $DOCUMENTER_KEY - diff --git a/README.md b/README.md index 6e476a0..16113aa 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,16 @@ # SeismicWaves -[![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://juliageoph.gitlab.io/SeismicWaves.jl/stable) -[![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://juliageoph.gitlab.io/SeismicWaves.jl/dev) +[![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://ginvlab.github.io/SeismicWaves.jl/stable) +[![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://ginvlab.github.io/SeismicWaves.jl/dev) SeismicWaves.jl is a Julia package for acoustic and elastic wave propagation simulations designed to be used in a Full-Waveform Inversion framework. It solves different flavours of the wave equation using the finite difference method. The main features of SeismicWaves.jl are: -- forward wave simulations with multiple pairs of sources and receivers (shots) -- 1D, 2D, and 3D acoustic wave simulations (constant density and variable density) -- 2D P-SV elastic wave similations (isotropic) -- free boundary and C-PML absorbing boundary conditions supported -- gradients of misfit functions with respect to model parameters using the adjoint method (only acoustic simulations supported as of now) - checkpointing of forward simulations for adjoint method - device agnostic backends (CPUs or GPUs) thanks to [`ParallelStencil.jl`](https://github.com/omlins/ParallelStencil.jl) -This package additionally provides some functions to solve inverse problems using the Hamiltonian Monte Carlo (HMC) method, as part of the [`HMCLab`](https://gitlab.com/JuliaGeoph/HMCLab.jl) framework. +This package additionally provides some functions to solve inverse problems using the Hamiltonian Monte Carlo (HMC) method, as part of the [`G⁻¹Lab`](https://ginvlab.github.io) framework. -More information and an extensive list of features can be found in the documentation, which you can either find [online](https://juliageoph.gitlab.io/SeismicWaves.jl/stable) or build locally by running the docs/make.jl file. +More information and an extensive list of features can be found in the documentation, which you can either find [online](https://ginvlab.github.io/SeismicWaves.jl/stable) or build locally by running the docs/make.jl file. Warning: **Documentation is currently minimal** and work in progress! diff --git a/docs/make.jl b/docs/make.jl index 7b3f314..ff6fd1b 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,22 +1,22 @@ using SeismicWaves -using Literate: Literate +import Literate using Documenter println("Converting examples...") Literate.markdown( joinpath(@__DIR__, "src", "examples.jl"), joinpath(@__DIR__, "src"); - credit=false + credit = false ) println("Building documentation...") -makedocs(; repo=Remotes.GitLab("JuliaGeoph", "SeismicWaves.jl"), # "https://gitlab.com/JuliaGeoph/SeismicWaves.jl/blob/{commit}{path}#{line}", +makedocs(; repo=Remotes.GitHub("GinvLab", "SeismicWaves.jl"), sitename="SeismicWaves.jl", modules=[SeismicWaves], - authors="Andrea Zunino, Giacomo Aloisi", + authors="Giacomo Aloisi, Andrea Zunino", format=Documenter.HTML(; prettyurls=get(ENV, "CI", nothing) == "true"), pages=[ "Home" => "index.md", @@ -28,8 +28,8 @@ makedocs(; repo=Remotes.GitLab("JuliaGeoph", "SeismicWaves.jl"), # "https://gitl ) deploydocs(; - repo="gitlab.com/JuliaGeoph/SeismicWaves.jl.git", + repo="github.com/GinvLab/SeismicWaves.jl.git", devbranch="main", - deploy_config=Documenter.GitLab(), - branch="gl-pages" + deploy_config=Documenter.GitHubActions(), + branch="gh-pages" ) From 74806bcdf7383710566826b80e8b99c8ae1d21ed Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 3 Feb 2025 14:24:24 +0100 Subject: [PATCH 103/111] Fix merge --- .../backends/shared/fourth_order_FiniteDifferences1D.jl | 3 --- .../backends/shared/fourth_order_FiniteDifferences2D.jl | 7 ------- .../backends/shared/fourth_order_FiniteDifferences2D.jl | 7 ------- test/test_forward_constant_density.jl | 1 + 4 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl delete mode 100644 src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl delete mode 100644 src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl diff --git a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl deleted file mode 100644 index 3ad648a..0000000 --- a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences1D.jl +++ /dev/null @@ -1,3 +0,0 @@ -macro d_dx_4th(a, i) - return esc(:((-$a[$i+1] + 27.0 * $a[$i] - 27.0 * $a[$i-1] + $a[$i-2]))) -end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl b/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl deleted file mode 100644 index 2dce407..0000000 --- a/src/models/acoustic/backends/shared/fourth_order_FiniteDifferences2D.jl +++ /dev/null @@ -1,7 +0,0 @@ -macro d_dx_4th(a, i, j) - return esc(:((-$a[$i+1, $j] + 27.0 * $a[$i, $j] - 27.0 * $a[$i-1, $j] + $a[$i-2, $j]))) -end - -macro d_dy_4th(a, i, j) - return esc(:((-$a[$i, $j+1] + 27.0 * $a[$i, $j] - 27.0 * $a[$i, $j-1] + $a[$i, $j-2]))) -end diff --git a/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl b/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl deleted file mode 100644 index 2dce407..0000000 --- a/src/models/elastic/backends/shared/fourth_order_FiniteDifferences2D.jl +++ /dev/null @@ -1,7 +0,0 @@ -macro d_dx_4th(a, i, j) - return esc(:((-$a[$i+1, $j] + 27.0 * $a[$i, $j] - 27.0 * $a[$i-1, $j] + $a[$i-2, $j]))) -end - -macro d_dy_4th(a, i, j) - return esc(:((-$a[$i, $j+1] + 27.0 * $a[$i, $j] - 27.0 * $a[$i, $j-1] + $a[$i, $j-2]))) -end diff --git a/test/test_forward_constant_density.jl b/test/test_forward_constant_density.jl index 232cd32..dd3eee0 100644 --- a/test/test_forward_constant_density.jl +++ b/test/test_forward_constant_density.jl @@ -40,6 +40,7 @@ with_logger(ConsoleLogger(stderr, Logging.Warn)) do # test integral of absolute difference over time is less then a constant 1% error relative to the peak analytical solution @test integrate(times, abs.(numerical_trace .- Gc)) <= maximum(abs.(Gc)) * 0.01 * (dt * nt) end + @testset "Test 1D $(parall) single-source multiple-receivers CPML" begin # velocity setup c0 = 1000.0 From 122750f0652865717d9eea6aed111b896de09547 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Mon, 3 Feb 2025 14:26:32 +0100 Subject: [PATCH 104/111] Fix source scaling --- src/models/elastic/ela_models.jl | 4 ++-- src/utils/utils.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/elastic/ela_models.jl b/src/models/elastic/ela_models.jl index fa8e7d5..9ab2406 100644 --- a/src/models/elastic/ela_models.jl +++ b/src/models/elastic/ela_models.jl @@ -30,7 +30,7 @@ function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::ExternalFor reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end - return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, shot.srcs.tf + return srccoeij_vx, srccoeval_vx, srccoeij_vz, srccoeval_vz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, shot.srcs.tf ./ prod(model.grid.spacing) end function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTensorShot{T, 2}; sincinterp=false) where {T} @@ -60,7 +60,7 @@ function possrcrec_scaletf(model::ElasticIsoWaveSimulation{T}, shot::MomentTenso reccoeval_vz = [ones(T, 1) for _ in 1:nrecs] end - return srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, shot.srcs.tf + return srccoeij_xx, srccoeval_xx, srccoeij_xz, srccoeval_xz, reccoeij_vx, reccoeval_vx, reccoeij_vz, reccoeval_vz, shot.srcs.tf ./ prod(model.grid.spacing) end diff --git a/src/utils/utils.jl b/src/utils/utils.jl index c4d3a6c..54a39a2 100644 --- a/src/utils/utils.jl +++ b/src/utils/utils.jl @@ -82,7 +82,7 @@ Band limited delta function by combining Kaiser window and sinc function. - `Δx`: grid spacing """ modd(x, x0, r, β, Δx) = begin - res = 1 / Δx * kaiser(x - x0, r * Δx, β) * sinc((x - x0) / Δx) + res = kaiser(x - x0, r * Δx, β) * sinc((x - x0) / Δx) return res ≈ 0 ? 0.0 : res end From 8c9f8494bde628eca4b22ed83305fcbaaa6631d8 Mon Sep 17 00:00:00 2001 From: GiackAloZ Date: Wed, 19 Feb 2025 11:47:17 +0100 Subject: [PATCH 105/111] Add gradient smoothing for elastic backend --- .../backends/Elastic2D_Iso_CPML_AMDGPU.jl | 1 + .../backends/Elastic2D_Iso_CPML_CUDA.jl | 1 + .../backends/Elastic2D_Iso_CPML_Serial.jl | 2 ++ .../backends/Elastic2D_Iso_CPML_Threads.jl | 1 + .../backends/shared/smooth_gradient_2D.jl | 22 +++++++++++++++++++ src/models/elastic/ela_gradient.jl | 12 ++++++++-- 6 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/models/elastic/backends/shared/smooth_gradient_2D.jl diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl index 6b30bd3..e26c6ce 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl @@ -11,5 +11,6 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") +include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl index 82da12b..f5b87b2 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl @@ -11,5 +11,6 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") +include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index da40f45..ad951a4 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -708,6 +708,8 @@ function correlate_gradients!(grid, vcurr, vold, dt, freetop) ) end +include("shared/smooth_gradient_2D.jl") + ######################################### end # end module ######################################### diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl index 732c94e..7e3b6cc 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl @@ -10,5 +10,6 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") +include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/elastic/backends/shared/smooth_gradient_2D.jl b/src/models/elastic/backends/shared/smooth_gradient_2D.jl new file mode 100644 index 0000000..b739dba --- /dev/null +++ b/src/models/elastic/backends/shared/smooth_gradient_2D.jl @@ -0,0 +1,22 @@ +function smooth_gradient!(grad, possrcs, radius) + nx, ny = size(grad) + nsources = size(possrcs, 1) + for s in 1:nsources + isrc = possrcs[s, 1] + jsrc = possrcs[s, 2] + imin = isrc - radius + imax = isrc + radius + jmin = jsrc - radius + jmax = jsrc + radius + for i in imin:imax + for j in jmin:jmax + if 1 <= i <= nx && 1 <= j <= ny + r = sqrt((i - isrc)^2 + (j - jsrc)^2) + if r < radius + grad[i, j] *= r / radius + end + end + end + end + end +end \ No newline at end of file diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index 434d6c5..f94fcc3 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -167,7 +167,11 @@ function swgradient_1shot!( gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf"].value), 1) .+ back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_jhalf"].value), 2) gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf_jhalf"].value), [1, 2]) - # TODO smooth gradients + # Smooth gradients + nearest_grdpts_src = find_nearest_grid_points(model, shot.srcs.positions) + backend.smooth_gradient!(gradient_ρ, nearest_grdpts_src, model.smooth_radius) + backend.smooth_gradient!(gradient_λ, nearest_grdpts_src, model.smooth_radius) + backend.smooth_gradient!(gradient_μ, nearest_grdpts_src, model.smooth_radius) # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) # Return gradients @@ -336,7 +340,11 @@ function swgradient_1shot!( gradient_ρ .+= back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_ihalf"].value), 1) .+ back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_jhalf"].value), 2) gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf_jhalf"].value), [1, 2]) - # TODO smooth gradients + # Smooth gradients + nearest_grdpts_src = find_nearest_grid_points(model, shot.srcs.positions) + backend.smooth_gradient!(gradient_ρ, nearest_grdpts_src, model.smooth_radius) + backend.smooth_gradient!(gradient_λ, nearest_grdpts_src, model.smooth_radius) + backend.smooth_gradient!(gradient_μ, nearest_grdpts_src, model.smooth_radius) # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) # Return gradients From 9c2b0cd96d2fcb48813f9e1154a643b543265457 Mon Sep 17 00:00:00 2001 From: Andrea Zunino Date: Wed, 26 Feb 2025 13:54:50 +0100 Subject: [PATCH 106/111] add mute_grads.jl --- src/utils/mute_grads.jl | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/utils/mute_grads.jl diff --git a/src/utils/mute_grads.jl b/src/utils/mute_grads.jl new file mode 100644 index 0000000..9ebd555 --- /dev/null +++ b/src/utils/mute_grads.jl @@ -0,0 +1,70 @@ + + +function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFiniteDifferenceGrid{N,T}, + radiuspx::Integer) where {T,N} + + @assert size(inparr) == grid.size + ety = eltype(inparr) + Ndim = ndims(inparr) + rmax::ety = radiuspx*maximum(NTuple(grid.spacing)) + + # This is just for the future, in case an offset of the grid + # coordinates could be specified + #gridinit = @SVector zeros(ety,Ndim) + + ijkmin = MVector{Ndim,Int64}(undef) + ijkmax = MVector{Ndim,Int64}(undef) + for d=1:Ndim + # check that the point is inside the grid + # with offset + # if gridinit[d] <= xyzpt[d] <= grid.extent[d] + # no offset + if zero(ety) <= xyzpt[d] <= grid.extent[d] + # with offset + #xyzres = div(xyzpt-gridinit[d],grid.spacing[d]) + # no offset + xyzres = div(xyzpt[d],grid.spacing[d]) + ijkpt = floor(Int64,xyzres) + 1 # .+1 julia indexing... + # spatial limits for smoothing + ijkmin[d] = ijkpt - radiuspx + ijkmax[d] = ijkpt + radiuspx + else + error("smootharoundpoint(): The point lies outside the grid on dimension $d at position $(xyzpt[d]).") + end + end + + inpcart = [ijkmin[d]:ijkmax[d] for d=1:Ndim] + xyzcur = zeros(Ndim) + caind = CartesianIndices(NTuple{Ndim,UnitRange{Int64}}(inpcart)) + + withinbounds::Bool = true + for caind in caind + idxs = caind.I + + for d=1:Ndim + withinbounds = 1 <= idxs[d] <= grid.size[d] + if !withinbounds + break + end + # with offset + #xyzcur[d] = (idxs[d]-1)*grid.spacing[d] + gridinit[d] + # no offset + xyzcur[d] = (idxs[d]-1)*grid.spacing[d] + end + + if withinbounds + # inverse of geometrical spreading + r = sqrt(sum( (xyzpt .- xyzcur).^2 )) + if r<=rmax + # normalized inverse of geometrical spreading + att = r/rmax + inparr[caind] *= att + end + end + end + + return nothing +end + + + From af32dfc9299651a058c95af4405bc13a9e2d2ed2 Mon Sep 17 00:00:00 2001 From: Andrea Zunino Date: Fri, 28 Feb 2025 12:31:44 +0100 Subject: [PATCH 107/111] Add single function to mute gradients at the source for all backends --- Project.toml | 2 ++ src/SeismicWaves.jl | 2 ++ src/models/acoustic/acou_gradient.jl | 7 ++--- .../backends/Acoustic1D_CD_CPML_AMDGPU.jl | 2 +- .../backends/Acoustic1D_CD_CPML_CUDA.jl | 1 - .../backends/Acoustic1D_CD_CPML_Serial.jl | 2 -- .../backends/Acoustic1D_CD_CPML_Threads.jl | 1 - .../backends/Acoustic1D_VD_CPML_AMDGPU.jl | 1 - .../backends/Acoustic1D_VD_CPML_CUDA.jl | 1 - .../backends/Acoustic1D_VD_CPML_Threads.jl | 1 - .../backends/Acoustic2D_CD_CPML_AMDGPU.jl | 1 - .../backends/Acoustic2D_CD_CPML_CUDA.jl | 1 - .../backends/Acoustic2D_CD_CPML_Serial.jl | 1 - .../backends/Acoustic2D_CD_CPML_Threads.jl | 1 - .../backends/Acoustic2D_VD_CPML_AMDGPU.jl | 1 - .../backends/Acoustic2D_VD_CPML_CUDA.jl | 1 - .../backends/Acoustic2D_VD_CPML_Threads.jl | 1 - .../backends/Acoustic3D_CD_CPML_AMDGPU.jl | 1 - .../backends/Acoustic3D_CD_CPML_CUDA.jl | 1 - .../backends/Acoustic3D_CD_CPML_Serial.jl | 1 - .../backends/Acoustic3D_CD_CPML_Threads.jl | 1 - .../backends/shared/smooth_gradient_1D.jl | 17 ------------ .../backends/shared/smooth_gradient_2D.jl | 22 --------------- .../backends/shared/smooth_gradient_3D.jl | 27 ------------------- .../backends/Elastic2D_Iso_CPML_AMDGPU.jl | 1 - .../backends/Elastic2D_Iso_CPML_CUDA.jl | 1 - .../backends/Elastic2D_Iso_CPML_Serial.jl | 1 - .../backends/Elastic2D_Iso_CPML_Threads.jl | 1 - .../backends/shared/smooth_gradient_2D.jl | 22 --------------- src/models/elastic/ela_gradient.jl | 18 ++++++------- src/utils/{mute_grads.jl => mute_grad.jl} | 26 ++++++++++++++---- 31 files changed, 39 insertions(+), 128 deletions(-) delete mode 100644 src/models/acoustic/backends/shared/smooth_gradient_1D.jl delete mode 100644 src/models/acoustic/backends/shared/smooth_gradient_2D.jl delete mode 100644 src/models/acoustic/backends/shared/smooth_gradient_3D.jl delete mode 100644 src/models/elastic/backends/shared/smooth_gradient_2D.jl rename src/utils/{mute_grads.jl => mute_grad.jl} (74%) diff --git a/Project.toml b/Project.toml index 39fd916..8a7099f 100644 --- a/Project.toml +++ b/Project.toml @@ -11,6 +11,7 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" ParallelStencil = "94395366-693c-11ea-3b26-d9b7aac5d958" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" [weakdeps] AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" @@ -21,6 +22,7 @@ SeismicWaves_AMDGPUBackendExt = "AMDGPU" SeismicWaves_CUDABackendExt = "CUDA" [compat] +StaticArrays = "1.9.12" julia = ">=1.9" [extras] diff --git a/src/SeismicWaves.jl b/src/SeismicWaves.jl index b1f83b4..ba50d8f 100644 --- a/src/SeismicWaves.jl +++ b/src/SeismicWaves.jl @@ -7,6 +7,7 @@ using ParallelStencil using Logging using DocStringExtensions using Interpolations +using StaticArrays # main struct for wave simulation export WaveSimulation @@ -58,6 +59,7 @@ include("utils/checks.jl") include("utils/fields.jl") include("utils/checkpointers.jl") include("utils/snapshotter.jl") +include("utils/mute_grad.jl") # Shots include("shots/sources.jl") diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index 22b2d0b..d5c8a58 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -84,7 +84,7 @@ function swgradient_1shot!( # get gradient gradient = Array(grid.fields["grad_vp"].value) # smooth gradient - backend.smooth_gradient!(gradient, possrcs, model.smooth_radius) + mutearoundmultiplepoints!(gradient,shot.srcs.positions,grid,model.smooth_radius) # rescale gradient gradient .= (convert(T, 2.0) ./ (model.matprop.vp .^ 3)) .* gradient # add regularization if needed @@ -185,8 +185,9 @@ function swgradient_1shot!( gradient_m1 .+= back_interp(model.matprop.interp_method, 1 ./ model.matprop.rho, Array(grid.fields["grad_m1_stag"].value[i]), i) end # Smooth gradients - backend.smooth_gradient!(gradient_m0, possrcs, model.smooth_radius) - backend.smooth_gradient!(gradient_m1, possrcs, model.smooth_radius) + mutearoundmultiplepoints!(gradient_m0,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_m1,shot.srcs.positions,grid,model.smooth_radius) + # compute regularization if needed dχ_dvp, dχ_drho = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) # Rescale gradients with respect to material properties (chain rule) diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl index e49ca7e..684b49b 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_AMDGPU.jl @@ -11,6 +11,6 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic1D_xPU.jl") -include("shared/smooth_gradient_1D.jl") + end diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl index 3fb8694..551b3f2 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_CUDA.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic1D_xPU.jl") -include("shared/smooth_gradient_1D.jl") end diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl index 635b433..0edc01e 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Serial.jl @@ -2,8 +2,6 @@ module Acoustic1D_CD_CPML_Serial using SeismicWaves.FiniteDifferencesMacros -include("shared/smooth_gradient_1D.jl") - # Dummy data module module Data Array = Base.Array diff --git a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl index 9338458..daa1a79 100644 --- a/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_CD_CPML_Threads.jl @@ -10,6 +10,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic1D_xPU.jl") -include("shared/smooth_gradient_1D.jl") end diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl index 3175a12..763b15a 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_AMDGPU.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic1D_VD_xPU.jl") -include("shared/smooth_gradient_1D.jl") end diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl index fce0325..ed1e983 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_CUDA.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic1D_VD_xPU.jl") -include("shared/smooth_gradient_1D.jl") end diff --git a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl index 0cfd641..364f26d 100644 --- a/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic1D_VD_CPML_Threads.jl @@ -10,6 +10,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic1D_VD_xPU.jl") -include("shared/smooth_gradient_1D.jl") end diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl index 55fbbbc..86b4fd3 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_AMDGPU.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic2D_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl index 2a5d400..5ab93bd 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_CUDA.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic2D_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl index ce83f15..748c0b3 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Serial.jl @@ -3,7 +3,6 @@ module Acoustic2D_CD_CPML_Serial using SeismicWaves.FiniteDifferencesMacros -include("shared/smooth_gradient_2D.jl") # Dummy data module module Data diff --git a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl index 952a8cb..50887d3 100644 --- a/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_CD_CPML_Threads.jl @@ -10,6 +10,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic2D_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl index ff4f3de..619017c 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_AMDGPU.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic2D_VD_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl index 9fa3c1f..82d2bc0 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_CUDA.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic2D_VD_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl index eaa1372..43d50ff 100644 --- a/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic2D_VD_CPML_Threads.jl @@ -10,6 +10,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic2D_VD_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl index 90ca7ad..f2dc094 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_AMDGPU.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic3D_xPU.jl") -include("shared/smooth_gradient_3D.jl") end diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl index af44d5b..1d3d2f8 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_CUDA.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic3D_xPU.jl") -include("shared/smooth_gradient_3D.jl") end diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl index 7d9ab1f..475617f 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Serial.jl @@ -3,7 +3,6 @@ module Acoustic3D_CD_CPML_Serial using SeismicWaves.FiniteDifferencesMacros -include("shared/smooth_gradient_3D.jl") # Dummy data module module Data diff --git a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl index 8dadc79..85629cd 100644 --- a/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl +++ b/src/models/acoustic/backends/Acoustic3D_CD_CPML_Threads.jl @@ -10,6 +10,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/correlate_gradient_xPU.jl") include("shared/acoustic3D_xPU.jl") -include("shared/smooth_gradient_3D.jl") end diff --git a/src/models/acoustic/backends/shared/smooth_gradient_1D.jl b/src/models/acoustic/backends/shared/smooth_gradient_1D.jl deleted file mode 100644 index fcc9b89..0000000 --- a/src/models/acoustic/backends/shared/smooth_gradient_1D.jl +++ /dev/null @@ -1,17 +0,0 @@ -function smooth_gradient!(grad, possrcs, radius) - nx = length(grad) - nsources = size(possrcs, 1) - for s in 1:nsources - isrc = possrcs[s, 1] - imin = isrc - radius - imax = isrc + radius - for i in imin:imax - if 1 <= i <= nx - r = abs(i - isrc) - if r < radius - grad[i] *= r / radius - end - end - end - end -end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/smooth_gradient_2D.jl b/src/models/acoustic/backends/shared/smooth_gradient_2D.jl deleted file mode 100644 index b739dba..0000000 --- a/src/models/acoustic/backends/shared/smooth_gradient_2D.jl +++ /dev/null @@ -1,22 +0,0 @@ -function smooth_gradient!(grad, possrcs, radius) - nx, ny = size(grad) - nsources = size(possrcs, 1) - for s in 1:nsources - isrc = possrcs[s, 1] - jsrc = possrcs[s, 2] - imin = isrc - radius - imax = isrc + radius - jmin = jsrc - radius - jmax = jsrc + radius - for i in imin:imax - for j in jmin:jmax - if 1 <= i <= nx && 1 <= j <= ny - r = sqrt((i - isrc)^2 + (j - jsrc)^2) - if r < radius - grad[i, j] *= r / radius - end - end - end - end - end -end \ No newline at end of file diff --git a/src/models/acoustic/backends/shared/smooth_gradient_3D.jl b/src/models/acoustic/backends/shared/smooth_gradient_3D.jl deleted file mode 100644 index 46331cc..0000000 --- a/src/models/acoustic/backends/shared/smooth_gradient_3D.jl +++ /dev/null @@ -1,27 +0,0 @@ -function smooth_gradient!(grad, possrcs, radius) - nx, ny, nz = size(grad) - nsources = size(possrcs, 1) - for s in 1:nsources - isrc = possrcs[s, 1] - jsrc = possrcs[s, 2] - ksrc = possrcs[s, 3] - imin = isrc - radius - imax = isrc + radius - jmin = jsrc - radius - jmax = jsrc + radius - kmin = ksrc - radius - kmax = ksrc + radius - for i in imin:imax - for j in jmin:jmax - for k in kmin:kmax - if 1 <= i <= nx && 1 <= j <= ny && 1 <= k <= nz - r = sqrt((i - isrc)^2 + (j - jsrc)^2 + (k - ksrc)^2) - if r < radius - grad[i, j, k] *= r / radius - end - end - end - end - end - end -end \ No newline at end of file diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl index e26c6ce..6b30bd3 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_AMDGPU.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl index f5b87b2..82da12b 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_CUDA.jl @@ -11,6 +11,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl index ad951a4..8cc71b8 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Serial.jl @@ -708,7 +708,6 @@ function correlate_gradients!(grid, vcurr, vold, dt, freetop) ) end -include("shared/smooth_gradient_2D.jl") ######################################### end # end module diff --git a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl index 7e3b6cc..732c94e 100644 --- a/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl +++ b/src/models/elastic/backends/Elastic2D_Iso_CPML_Threads.jl @@ -10,6 +10,5 @@ using SeismicWaves.FiniteDifferencesMacros include("shared/standard_xPU.jl") include("shared/elastic2D_iso_xPU.jl") include("shared/correlate_gradient_xPU.jl") -include("shared/smooth_gradient_2D.jl") end diff --git a/src/models/elastic/backends/shared/smooth_gradient_2D.jl b/src/models/elastic/backends/shared/smooth_gradient_2D.jl deleted file mode 100644 index b739dba..0000000 --- a/src/models/elastic/backends/shared/smooth_gradient_2D.jl +++ /dev/null @@ -1,22 +0,0 @@ -function smooth_gradient!(grad, possrcs, radius) - nx, ny = size(grad) - nsources = size(possrcs, 1) - for s in 1:nsources - isrc = possrcs[s, 1] - jsrc = possrcs[s, 2] - imin = isrc - radius - imax = isrc + radius - jmin = jsrc - radius - jmax = jsrc + radius - for i in imin:imax - for j in jmin:jmax - if 1 <= i <= nx && 1 <= j <= ny - r = sqrt((i - isrc)^2 + (j - jsrc)^2) - if r < radius - grad[i, j] *= r / radius - end - end - end - end - end -end \ No newline at end of file diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index f94fcc3..69ab003 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -168,10 +168,10 @@ function swgradient_1shot!( back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_jhalf"].value), 2) gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf_jhalf"].value), [1, 2]) # Smooth gradients - nearest_grdpts_src = find_nearest_grid_points(model, shot.srcs.positions) - backend.smooth_gradient!(gradient_ρ, nearest_grdpts_src, model.smooth_radius) - backend.smooth_gradient!(gradient_λ, nearest_grdpts_src, model.smooth_radius) - backend.smooth_gradient!(gradient_μ, nearest_grdpts_src, model.smooth_radius) + mutearoundmultiplepoints!(gradient_ρ,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_λ,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_μ,shot.srcs.positions,grid,model.smooth_radius) + # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) # Return gradients @@ -341,10 +341,10 @@ function swgradient_1shot!( back_interp(model.matprop.interp_method_ρ, model.matprop.ρ, Array(grid.fields["grad_ρ_jhalf"].value), 2) gradient_μ .+= back_interp(model.matprop.interp_method_μ, model.matprop.μ, Array(grid.fields["grad_μ_ihalf_jhalf"].value), [1, 2]) # Smooth gradients - nearest_grdpts_src = find_nearest_grid_points(model, shot.srcs.positions) - backend.smooth_gradient!(gradient_ρ, nearest_grdpts_src, model.smooth_radius) - backend.smooth_gradient!(gradient_λ, nearest_grdpts_src, model.smooth_radius) - backend.smooth_gradient!(gradient_μ, nearest_grdpts_src, model.smooth_radius) + mutearoundmultiplepoints!(gradient_ρ,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_λ,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_μ,shot.srcs.positions,grid,model.smooth_radius) + # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) # Return gradients @@ -353,4 +353,4 @@ function swgradient_1shot!( "lambda" => gradient_λ .+ ∂χ_∂λ, "mu" => gradient_μ .+ ∂χ_∂μ ) -end \ No newline at end of file +end diff --git a/src/utils/mute_grads.jl b/src/utils/mute_grad.jl similarity index 74% rename from src/utils/mute_grads.jl rename to src/utils/mute_grad.jl index 9ebd555..d868879 100644 --- a/src/utils/mute_grads.jl +++ b/src/utils/mute_grad.jl @@ -1,16 +1,26 @@ +function mutearoundmultiplepoints!(inparr::Array{T,N},xyzpts::Matrix{T},grid::UniformFiniteDifferenceGrid{N,T}, + radiuspx::Integer) where {T,N} + for i=1:size(xyzpts,1) + mutearoundpoint!(inparr,xyzpts[i,:],grid,radiuspx) + end + return +end + + + function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFiniteDifferenceGrid{N,T}, radiuspx::Integer) where {T,N} - + @assert size(inparr) == grid.size ety = eltype(inparr) Ndim = ndims(inparr) - rmax::ety = radiuspx*maximum(NTuple(grid.spacing)) + rmax::T = radiuspx*maximum(NTuple(grid.spacing)) # This is just for the future, in case an offset of the grid # coordinates could be specified - #gridinit = @SVector zeros(ety,Ndim) + #gridinit = @SVector zeros(T,Ndim) ijkmin = MVector{Ndim,Int64}(undef) ijkmax = MVector{Ndim,Int64}(undef) @@ -19,9 +29,9 @@ function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFinit # with offset # if gridinit[d] <= xyzpt[d] <= grid.extent[d] # no offset - if zero(ety) <= xyzpt[d] <= grid.extent[d] + if zero(T) <= xyzpt[d] <= grid.extent[d] # with offset - #xyzres = div(xyzpt-gridinit[d],grid.spacing[d]) + # xyzres = div(xyzpt-gridinit[d],grid.spacing[d]) # no offset xyzres = div(xyzpt[d],grid.spacing[d]) ijkpt = floor(Int64,xyzres) + 1 # .+1 julia indexing... @@ -67,4 +77,10 @@ function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFinit end +# nx,ny = 20,20 +# grd = UniformFiniteDifferenceGrid((nx,ny),(1.0,1.0)) +# inparr = ones(20,20) +# xyzpt = [10.0,10.0] +# radiuspx = 5 +# mutearoundpoint!(inparr,xyzpt,grd,radiuspx) From af687dc64e0b7ed046188d3bc7169bbc83bb2820 Mon Sep 17 00:00:00 2001 From: Andrea Zunino Date: Fri, 28 Feb 2025 12:39:45 +0100 Subject: [PATCH 108/111] clean up mute_grad.jl --- src/utils/mute_grad.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/utils/mute_grad.jl b/src/utils/mute_grad.jl index d868879..cec9566 100644 --- a/src/utils/mute_grad.jl +++ b/src/utils/mute_grad.jl @@ -77,10 +77,3 @@ function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFinit end -# nx,ny = 20,20 -# grd = UniformFiniteDifferenceGrid((nx,ny),(1.0,1.0)) -# inparr = ones(20,20) -# xyzpt = [10.0,10.0] -# radiuspx = 5 -# mutearoundpoint!(inparr,xyzpt,grd,radiuspx) - From 361d080198337b0999af83b42ec9a3256631997b Mon Sep 17 00:00:00 2001 From: Andrea Zunino Date: Fri, 28 Feb 2025 15:03:50 +0100 Subject: [PATCH 109/111] Add muting also around receivers --- src/models/acoustic/acou_gradient.jl | 3 +++ src/models/elastic/ela_gradient.jl | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/models/acoustic/acou_gradient.jl b/src/models/acoustic/acou_gradient.jl index d5c8a58..931232d 100644 --- a/src/models/acoustic/acou_gradient.jl +++ b/src/models/acoustic/acou_gradient.jl @@ -85,6 +85,7 @@ function swgradient_1shot!( gradient = Array(grid.fields["grad_vp"].value) # smooth gradient mutearoundmultiplepoints!(gradient,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient,shot.recs.positions,grid,model.smooth_radius) # rescale gradient gradient .= (convert(T, 2.0) ./ (model.matprop.vp .^ 3)) .* gradient # add regularization if needed @@ -187,6 +188,8 @@ function swgradient_1shot!( # Smooth gradients mutearoundmultiplepoints!(gradient_m0,shot.srcs.positions,grid,model.smooth_radius) mutearoundmultiplepoints!(gradient_m1,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_m0,shot.recs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_m1,shot.recs.positions,grid,model.smooth_radius) # compute regularization if needed dχ_dvp, dχ_drho = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0) diff --git a/src/models/elastic/ela_gradient.jl b/src/models/elastic/ela_gradient.jl index 69ab003..b583f26 100644 --- a/src/models/elastic/ela_gradient.jl +++ b/src/models/elastic/ela_gradient.jl @@ -171,7 +171,9 @@ function swgradient_1shot!( mutearoundmultiplepoints!(gradient_ρ,shot.srcs.positions,grid,model.smooth_radius) mutearoundmultiplepoints!(gradient_λ,shot.srcs.positions,grid,model.smooth_radius) mutearoundmultiplepoints!(gradient_μ,shot.srcs.positions,grid,model.smooth_radius) - + mutearoundmultiplepoints!(gradient_ρ,shot.recs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_λ,shot.recs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_μ,shot.recs.positions,grid,model.smooth_radius) # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) # Return gradients @@ -344,6 +346,9 @@ function swgradient_1shot!( mutearoundmultiplepoints!(gradient_ρ,shot.srcs.positions,grid,model.smooth_radius) mutearoundmultiplepoints!(gradient_λ,shot.srcs.positions,grid,model.smooth_radius) mutearoundmultiplepoints!(gradient_μ,shot.srcs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_ρ,shot.recs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_λ,shot.recs.positions,grid,model.smooth_radius) + mutearoundmultiplepoints!(gradient_μ,shot.recs.positions,grid,model.smooth_radius) # Compute regularization if needed ∂χ_∂ρ, ∂χ_∂λ, ∂χ_∂μ = (misfit.regularization !== nothing) ? dχ_dm(misfit.regularization, model.matprop) : (0, 0, 0) From d7f75dbf95f3008771784407a5dd9664d25de32d Mon Sep 17 00:00:00 2001 From: Andrea Zunino Date: Fri, 28 Feb 2025 16:51:45 +0100 Subject: [PATCH 110/111] fix minor things in mute_grad.jl --- src/utils/mute_grad.jl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/utils/mute_grad.jl b/src/utils/mute_grad.jl index cec9566..83474ae 100644 --- a/src/utils/mute_grad.jl +++ b/src/utils/mute_grad.jl @@ -14,17 +14,15 @@ function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFinit radiuspx::Integer) where {T,N} @assert size(inparr) == grid.size - ety = eltype(inparr) - Ndim = ndims(inparr) rmax::T = radiuspx*maximum(NTuple(grid.spacing)) # This is just for the future, in case an offset of the grid # coordinates could be specified - #gridinit = @SVector zeros(T,Ndim) + #gridinit = @SVector zeros(T,N) - ijkmin = MVector{Ndim,Int64}(undef) - ijkmax = MVector{Ndim,Int64}(undef) - for d=1:Ndim + ijkmin = MVector{N,Int64}(undef) + ijkmax = MVector{N,Int64}(undef) + for d=1:N # check that the point is inside the grid # with offset # if gridinit[d] <= xyzpt[d] <= grid.extent[d] @@ -39,19 +37,19 @@ function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFinit ijkmin[d] = ijkpt - radiuspx ijkmax[d] = ijkpt + radiuspx else - error("smootharoundpoint(): The point lies outside the grid on dimension $d at position $(xyzpt[d]).") + error("mutearoundpoint(): The point lies outside the grid on dimension $d at position $(xyzpt[d]).") end end - inpcart = [ijkmin[d]:ijkmax[d] for d=1:Ndim] - xyzcur = zeros(Ndim) - caind = CartesianIndices(NTuple{Ndim,UnitRange{Int64}}(inpcart)) + inpcart = [ijkmin[d]:ijkmax[d] for d=1:N] + xyzcur = zeros(N) + caind = CartesianIndices(NTuple{N,UnitRange{Int64}}(inpcart)) withinbounds::Bool = true for caind in caind idxs = caind.I - for d=1:Ndim + for d=1:N withinbounds = 1 <= idxs[d] <= grid.size[d] if !withinbounds break From db138aa3d97a1e8f10c360c32e242832b91d098d Mon Sep 17 00:00:00 2001 From: Andrea Zunino Date: Fri, 28 Feb 2025 16:56:26 +0100 Subject: [PATCH 111/111] fix typo --- src/utils/mute_grad.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/mute_grad.jl b/src/utils/mute_grad.jl index 83474ae..13b4051 100644 --- a/src/utils/mute_grad.jl +++ b/src/utils/mute_grad.jl @@ -37,7 +37,7 @@ function mutearoundpoint!(inparr::Array{T,N},xyzpt::Vector{T},grid::UniformFinit ijkmin[d] = ijkpt - radiuspx ijkmax[d] = ijkpt + radiuspx else - error("mutearoundpoint(): The point lies outside the grid on dimension $d at position $(xyzpt[d]).") + error("mutearoundpoint!(): The point lies outside the grid on dimension $d at position $(xyzpt[d]).") end end