1 |
|
2 |
######################################################## |
3 |
# |
4 |
# Copyright (c) 2009-2010 by University of Queensland |
5 |
# Earth Systems Science Computational Center (ESSCC) |
6 |
# http://www.uq.edu.au/esscc |
7 |
# |
8 |
# Primary Business: Queensland, Australia |
9 |
# Licensed under the Open Software License version 3.0 |
10 |
# http://www.opensource.org/licenses/osl-3.0.php |
11 |
# |
12 |
######################################################## |
13 |
|
14 |
__copyright__="""Copyright (c) 2009-2010 by University of Queensland |
15 |
Earth Systems Science Computational Center (ESSCC) |
16 |
http://www.uq.edu.au/esscc |
17 |
Primary Business: Queensland, Australia""" |
18 |
__license__="""Licensed under the Open Software License version 3.0 |
19 |
http://www.opensource.org/licenses/osl-3.0.php""" |
20 |
__url__="https://launchpad.net/escript-finley" |
21 |
|
22 |
############################################################FILE HEADER |
23 |
# example08b.py |
24 |
# Antony Hallam |
25 |
# Seismic Wave Equation Simulation using acceleration solution. |
26 |
# Extend the solution in example 08a to use absorbing boundary |
27 |
# conditions. |
28 |
|
29 |
#######################################################EXTERNAL MODULES |
30 |
from esys.escript import * |
31 |
from esys.finley import Rectangle |
32 |
import os |
33 |
# smoothing operator |
34 |
from esys.escript.pdetools import Projector, Locator |
35 |
from esys.escript.unitsSI import * |
36 |
import numpy as np |
37 |
import pylab as pl |
38 |
import matplotlib.cm as cm |
39 |
from esys.escript.linearPDEs import LinearPDE |
40 |
|
41 |
########################################################MPI WORLD CHECK |
42 |
if getMPISizeWorld() > 1: |
43 |
import sys |
44 |
print "This example will not run in an MPI world." |
45 |
sys.exit(0) |
46 |
|
47 |
#################################################ESTABLISHING VARIABLES |
48 |
# where to save output data |
49 |
savepath = "data/example08b" |
50 |
mkDir(savepath) |
51 |
#Geometric and material property related variables. |
52 |
mx = 1000. # model lenght |
53 |
my = 1000. # model width |
54 |
ndx = 500 # steps in x direction |
55 |
ndy = 500 # steps in y direction |
56 |
xstep=mx/ndx # calculate the size of delta x |
57 |
ystep=abs(my/ndy) # calculate the size of delta y |
58 |
lam=3.462e9 #lames constant |
59 |
mu=3.462e9 #bulk modulus |
60 |
rho=1154. #density |
61 |
# Time related variables. |
62 |
tend=0.5 # end time |
63 |
h=0.0005 # time step |
64 |
# data recording times |
65 |
rtime=0.0 # first time to record |
66 |
rtime_inc=tend/50.0 # time increment to record |
67 |
#Check to make sure number of time steps is not too large. |
68 |
print "Time step size= ",h, "Expected number of outputs= ",tend/h |
69 |
|
70 |
U0=0.1 # amplitude of point source |
71 |
ls=500 # length of the source |
72 |
source=np.zeros(ls,'float') # source array |
73 |
decay1=np.zeros(ls,'float') # decay curve one |
74 |
decay2=np.zeros(ls,'float') # decay curve two |
75 |
time=np.zeros(ls,'float') # time values |
76 |
g=np.log(0.01)/ls |
77 |
|
78 |
dfeq=50 #Dominant Frequency |
79 |
a = 2.0 * (np.pi * dfeq)**2.0 |
80 |
t0 = 5.0 / (2.0 * np.pi * dfeq) |
81 |
srclength = 5. * t0 |
82 |
ls = int(srclength/h) |
83 |
print 'source length',ls |
84 |
source=np.zeros(ls,'float') # source array |
85 |
ampmax=0 |
86 |
for it in range(0,ls): |
87 |
t = it*h |
88 |
tt = t-t0 |
89 |
dum1 = np.exp(-a * tt * tt) |
90 |
source[it] = -2. * a * tt * dum1 |
91 |
# source[it] = exp(-a * tt * tt) !gaussian |
92 |
if (abs(source[it]) > ampmax): |
93 |
ampmax = abs(source[it]) |
94 |
#source[t]=np.exp(g*t)*U0*np.sin(2.*np.pi*t/(0.75*ls))*(np.exp(-.1*g*t)-1) |
95 |
#decay1[t]=np.exp(g*t) |
96 |
#decay2[t]=(np.exp(-.1*g*t)-1) |
97 |
time[t]=t*h |
98 |
#tdecay=decay1*decay2*U0 |
99 |
#decay1=decay1*U0; decay2=decay2*U0 |
100 |
pl.clf(); |
101 |
pl.plot(source) |
102 |
#pl.plot(time,decay1);pl.plot(time,decay2); |
103 |
#pl.plot(time,tdecay) |
104 |
pl.savefig(os.path.join(savepath,'source.png')) |
105 |
|
106 |
# will introduce a spherical source at middle left of bottom face |
107 |
xc=[mx/2,0] |
108 |
|
109 |
####################################################DOMAIN CONSTRUCTION |
110 |
domain=Rectangle(l0=mx,l1=my,n0=ndx, n1=ndy,order=2) # create the domain |
111 |
x=domain.getX() # get the locations of the nodes in the domani |
112 |
|
113 |
##########################################################ESTABLISH PDE |
114 |
mypde=LinearPDE(domain) # create pde |
115 |
mypde.setSymmetryOn() # turn symmetry on |
116 |
# turn lumping on for more efficient solving |
117 |
mypde.getSolverOptions().setSolverMethod(mypde.getSolverOptions().LUMPING) |
118 |
kmat = kronecker(domain) # create the kronecker delta function of the domain |
119 |
mypde.setValue(D=kmat*rho) #set the general form value D |
120 |
|
121 |
##########################################################ESTABLISH ABC |
122 |
# Define where the boundary decay will be applied. |
123 |
bn=50. |
124 |
bleft=xstep*bn; bright=mx-(xstep*bn); bbot=my-(ystep*bn) |
125 |
# btop=ystep*bn # don't apply to force boundary!!! |
126 |
|
127 |
# locate these points in the domain |
128 |
left=x[0]-bleft; right=x[0]-bright; bottom=x[1]-bbot |
129 |
|
130 |
tgamma=0.85 # decay value for exponential function |
131 |
def calc_gamma(G,npts): |
132 |
func=np.sqrt(abs(-1.*np.log(G)/(npts**2.))) |
133 |
return func |
134 |
|
135 |
gleft = calc_gamma(tgamma,bleft) |
136 |
gright = calc_gamma(tgamma,bleft) |
137 |
gbottom= calc_gamma(tgamma,ystep*bn) |
138 |
|
139 |
print 'gamma', gleft,gright,gbottom |
140 |
|
141 |
# calculate decay functions |
142 |
def abc_bfunc(gamma,loc,x,G): |
143 |
func=exp(-1.*(gamma*abs(loc-x))**2.) |
144 |
return func |
145 |
|
146 |
fleft=abc_bfunc(gleft,bleft,x[0],tgamma) |
147 |
fright=abc_bfunc(gright,bright,x[0],tgamma) |
148 |
fbottom=abc_bfunc(gbottom,bbot,x[1],tgamma) |
149 |
# apply these functions only where relevant |
150 |
abcleft=fleft*whereNegative(left) |
151 |
abcright=fright*wherePositive(right) |
152 |
abcbottom=fbottom*wherePositive(bottom) |
153 |
# make sure the inside of the abc is value 1 |
154 |
abcleft=abcleft+whereZero(abcleft) |
155 |
abcright=abcright+whereZero(abcright) |
156 |
abcbottom=abcbottom+whereZero(abcbottom) |
157 |
# multiply the conditions together to get a smooth result |
158 |
abc=abcleft*abcright*abcbottom |
159 |
|
160 |
#visualise the boundary function |
161 |
#abcT=abc.toListOfTuples() |
162 |
#abcT=np.reshape(abcT,(ndx+1,ndy+1)) |
163 |
#pl.clf(); pl.imshow(abcT); pl.colorbar(); |
164 |
#pl.savefig(os.path.join(savepath,"abc.png")) |
165 |
|
166 |
|
167 |
############################################FIRST TIME STEPS AND SOURCE |
168 |
# define small radius around point xc |
169 |
src_length = 40; print "src_length = ",src_length |
170 |
# set initial values for first two time steps with source terms |
171 |
y=source[0]*(cos(length(x-xc)*3.1415/src_length)+1)*whereNegative(length(x-xc)-src_length) |
172 |
src_dir=numpy.array([0.,-1.]) # defines direction of point source as down |
173 |
y=y*src_dir |
174 |
mypde.setValue(y=y) #set the source as a function on the boundary |
175 |
# initial value of displacement at point source is constant (U0=0.01) |
176 |
# for first two time steps |
177 |
u=[0.0,0.0]*whereNegative(x) |
178 |
u_m1=u |
179 |
|
180 |
####################################################ITERATION VARIABLES |
181 |
n=0 # iteration counter |
182 |
t=0 # time counter |
183 |
##############################################################ITERATION |
184 |
while t<tend: |
185 |
# get current stress |
186 |
g=grad(u); stress=lam*trace(g)*kmat+mu*(g+transpose(g))*abc |
187 |
mypde.setValue(X=-stress) # set PDE values |
188 |
accel = mypde.getSolution() #get PDE solution for accelleration |
189 |
u_p1=(2.*u-u_m1)+h*h*accel #calculate displacement |
190 |
u_p1=u_p1*abc # apply boundary conditions |
191 |
u_m1=u; u=u_p1 # shift values by 1 |
192 |
# save current displacement, acceleration and pressure |
193 |
if (t >= rtime): |
194 |
saveVTK(os.path.join(savepath,"ex08b.%05d.vtu"%n),displacement=length(u),\ |
195 |
acceleration=length(accel),tensor=stress) |
196 |
rtime=rtime+rtime_inc #increment data save time |
197 |
# increment loop values |
198 |
t=t+h; n=n+1 |
199 |
if (n < ls): |
200 |
y=source[n]*(cos(length(x-xc)*3.1415/src_length)+1)*whereNegative(length(x-xc)-src_length) |
201 |
y=y*src_dir; mypde.setValue(y=y) #set the source as a function on the boundary |
202 |
print n,"-th time step t ",t |