File: seismic_AppExample.py

package info (click to toggle)
python-escript 5.6-10
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 144,304 kB
  • sloc: python: 592,074; cpp: 136,909; ansic: 18,675; javascript: 9,411; xml: 3,384; sh: 738; makefile: 207
file content (132 lines) | stat: -rw-r--r-- 3,833 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""
simple seismic solver in frequency domain 
with reflectors and PML.
"""

from esys.escript import *
from esys.finley import Rectangle
from esys.downunder.apps import SonicWaveInFrequencyDomain, PMLCondition
from esys.weipa import saveSilo
from esys.escript.pdetools import Locator

import numpy as np

# horizontal and vertical grid spacing in 
dx=10.
dz=10.

# grid size
NEx=400
NEz=180

# element order (1 or 2):
Order=2

# extend of domain:
Width=NEx*dx
Depth=NEz*dz

# position of geophones:
StationOffset = 60*dx # position of first phone from left boundary
StationSpacing = dx # phone spacing
NStations = int((Width-2*StationOffset)//StationSpacing+0.5)+1 # number of stations

# velocity:
Layers=[     30*dx ,   40*dx,  90*dx ] # thickness of layer from the top down 
Vs        =[ 1500.,    2000.,  3000. ] # corresponding velocities
Vbase=3500                             # base velocity

Frequency = 8.   # frequency
Amplitude= 1.     # and amplitude

# thickness of PML zone:
L_PML=40*dx


print("Domain = %g  x %g m"%(Width, Depth))
print("Grid Cells= %d x %d"%(NEx, NEz))
print("Grid Nodes= %d x %d"%(Order*NEx+1, Order*NEz+1))
print("Grid Spacing = %g  x %g m"%(dx, dz))
print("PML zone = %g m"%(L_PML))
print("Number of Stations = %d"%(NStations,))
print("Station spacing = %g m"%(StationSpacing,))
print("Station offset  = %g m"%(StationOffset,))
print("Reflector Layers [m]: ", Layers)
print("Velocities [m/s]: ", Vs)
print("Base velocity : [m/s]", Vbase)
print("Frequency = %g Hz "%Frequency)
print("Amplitude = %g"%Amplitude)


# generate domain:
stationPositions = [ (StationOffset+s*StationSpacing, Depth ) for s in range(NStations)]
stationTags= [ "P%4.4d"%s for s in range(NStations)]
domain=Rectangle(NEx,NEz,l0=Width,l1=Depth, diracPoints=stationPositions, diracTags=stationTags, order=Order, fullOrder=True)
print("Domain has been generated.")

Dim=domain.getDim()
# setup velocity field:
vp=Scalar(Vbase, Function(domain))
X=vp.getX()
Top=sup(domain.getX()[Dim-1])
for l in range(len(Vs)-1, -1, -1 ):
    mask=wherePositive(X[Dim-1]-(Top-Layers[l]))
    vp=vp*(1-mask)+mask*Vs[l]
print("Velocity field generated:",vp)

# check spacing vs, wavelength:
wavelength=inf(vp/(2*np.pi*Frequency))
print("minimum wavelength   = %g"%wavelength)
assert wavelength > max(dx,dz)/Order


# locator to grap amplitudes at geophones:
geophones=Locator(Solution(domain), stationPositions)


# create PML condition:
pml_condition=PMLCondition(sigma0=vp*100/Frequency, Lleft=[L_PML,L_PML], Lright=[L_PML, None], m=4)
print("PMLConditon generated ...")

# sonic wave model
wave=SonicWaveInFrequencyDomain(domain, vp=vp, pml_condition=pml_condition)
wave.setFrequency(Frequency)
print("model created...")
# set source and get wave response: 
source=Scalar(0j, DiracDeltaFunctions(domain))
source.setTaggedValue(stationTags[NStations//2], Amplitude)
u=wave.getWave(source)
print("model solved...")

# get amplitude and phase
amps=abs(u)
phase=phase(u)/np.pi*180.


# save to file:
saveSilo("solution", velocity=vp, amplitude=amps, phase=phase, pmlzone=pml_condition.getPMLMask(domain))
print("solution saved to file ...")

# get the amplitude and phase at geophones:
import matplotlib.pyplot as plt

fig=plt.gcf()
ax1=plt.gca()

geophoneX=[ x[0] for x in geophones.getX()]
color = 'tab:red'
ax1.set_xlabel('offset')
ax1.set_ylabel('amplitude', color=color)
ax1.plot(geophoneX , geophones(amps), color=color)
ax1.tick_params(axis='y', labelcolor=color)

ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis

color = 'tab:blue'
ax2.set_ylabel('phase [deg]', color=color)  # we already handled the x-label with ax1
ax2.plot(geophoneX , geophones(phase), color=color, marker=".")
ax2.tick_params(axis='y', labelcolor=color)

fig.tight_layout()  # otherwise the right y-label is slightly clipped

plt.show()