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 |
""" |
23 |
Author: Antony Hallam antony.hallam@uqconnect.edu.au |
24 |
""" |
25 |
|
26 |
############################################################FILE HEADER |
27 |
# example08c.py |
28 |
# Create either a 2D syncline or anticline model using pycad meshing |
29 |
# tools. Wave equation solution. |
30 |
|
31 |
#######################################################EXTERNAL MODULES |
32 |
import matplotlib |
33 |
matplotlib.use('agg') #It's just here for automated testing |
34 |
from esys.pycad import * #domain constructor |
35 |
from esys.pycad.gmsh import Design #Finite Element meshing package |
36 |
from esys.finley import MakeDomain #Converter for escript |
37 |
import os #file path tool |
38 |
from math import * # math package |
39 |
from esys.escript import * |
40 |
from esys.escript.unitsSI import * |
41 |
from esys.escript.linearPDEs import LinearPDE |
42 |
from esys.escript.pdetools import Projector |
43 |
from cblib import toRegGrid, subsample |
44 |
import pylab as pl #Plotting package |
45 |
import numpy as np |
46 |
|
47 |
########################################################MPI WORLD CHECK |
48 |
if getMPISizeWorld() > 1: |
49 |
import sys |
50 |
print "This example will not run in an MPI world." |
51 |
sys.exit(0) |
52 |
|
53 |
#################################################ESTABLISHING VARIABLES |
54 |
#set modal to 1 for a syncline or -1 for an anticline structural |
55 |
#configuration |
56 |
modal=-1 |
57 |
|
58 |
# the folder to put our outputs in, leave blank "" for script path - |
59 |
# note this folder path must exist to work |
60 |
save_path= os.path.join("data","example08c") |
61 |
mkDir(save_path) |
62 |
|
63 |
################################################ESTABLISHING PARAMETERS |
64 |
#Model Parameters |
65 |
width=1000.0*m #width of model |
66 |
depth=1000.0*m #depth of model |
67 |
dx=5 |
68 |
xstep=dx # calculate the size of delta x |
69 |
ystep=dx # calculate the size of delta y |
70 |
|
71 |
sspl=51 #number of discrete points in spline |
72 |
dsp=width/(sspl-1) #dx of spline steps for width |
73 |
dep_sp=500.0*m #avg depth of spline |
74 |
h_sp=250.*m #heigh of spline |
75 |
orit=-1.0 #orientation of spline 1.0=>up -1.0=>down |
76 |
|
77 |
vel2=1800.; vel1=3000. |
78 |
rho2=2300.; rho1=3100. #density |
79 |
mu2=(vel2**2.)*rho2/8.; mu1=(vel1**2.)*rho1/8. #bulk modulus |
80 |
lam2=mu2*6.; lam1=mu1*6. #lames constant |
81 |
|
82 |
|
83 |
# Time related variables. |
84 |
tend=0.5 # end time |
85 |
h=0.0001 # time step |
86 |
# data recording times |
87 |
rtime=0.0 # first time to record |
88 |
rtime_inc=tend/50.0 # time increment to record |
89 |
# will introduce a spherical source at middle left of bottom face |
90 |
xc=[width/2,0] |
91 |
#Check to make sure number of time steps is not too large. |
92 |
print "Time step size= ",h, "Expected number of outputs= ",tend/h |
93 |
|
94 |
U0=0.1 # amplitude of point source |
95 |
ls=500 # length of the source |
96 |
source=np.zeros(ls,'float') # source array |
97 |
decay1=np.zeros(ls,'float') # decay curve one |
98 |
decay2=np.zeros(ls,'float') # decay curve two |
99 |
time=np.zeros(ls,'float') # time values |
100 |
g=np.log(0.01)/ls |
101 |
|
102 |
dfeq=50 #Dominant Frequency |
103 |
a = 2.0 * (np.pi * dfeq)**2.0 |
104 |
t0 = 5.0 / (2.0 * np.pi * dfeq) |
105 |
srclength = 5. * t0 |
106 |
ls = int(srclength/h) |
107 |
print 'source length',ls |
108 |
source=np.zeros(ls,'float') # source array |
109 |
ampmax=0 |
110 |
for it in range(0,ls): |
111 |
t = it*h |
112 |
tt = t-t0 |
113 |
dum1 = np.exp(-a * tt * tt) |
114 |
source[it] = -2. * a * tt * dum1 |
115 |
if (abs(source[it]) > ampmax): |
116 |
ampmax = abs(source[it]) |
117 |
time[t]=t*h |
118 |
|
119 |
####################################################DOMAIN CONSTRUCTION |
120 |
# Domain Corners |
121 |
p0=Point(0.0, 0.0, 0.0) |
122 |
p1=Point(0.0, depth, 0.0) |
123 |
p2=Point(width, depth, 0.0) |
124 |
p3=Point(width, 0.0, 0.0) |
125 |
|
126 |
# Generate Material Boundary |
127 |
x=[ Point(i*dsp\ |
128 |
,dep_sp+modal*orit*h_sp*cos(pi*i*dsp/dep_sp+pi))\ |
129 |
for i in range(0,sspl)\ |
130 |
] |
131 |
mysp = Spline(*tuple(x)) |
132 |
# Start and end of material boundary. |
133 |
x1=mysp.getStartPoint() |
134 |
x2=mysp.getEndPoint() |
135 |
|
136 |
# Create TOP BLOCK |
137 |
# lines |
138 |
tbl1=Line(p0,x1) |
139 |
tbl2=mysp |
140 |
tbl3=Line(x2,p3) |
141 |
l30=Line(p3, p0) |
142 |
# curve |
143 |
tblockloop = CurveLoop(tbl1,tbl2,tbl3,l30) |
144 |
# surface |
145 |
tblock = PlaneSurface(tblockloop) |
146 |
# Create BOTTOM BLOCK |
147 |
# lines |
148 |
bbl1=Line(x1,p1) |
149 |
bbl3=Line(p2,x2) |
150 |
bbl4=-mysp |
151 |
l12=Line(p1, p2) |
152 |
# curve |
153 |
bblockloop = CurveLoop(bbl1,l12,bbl3,bbl4) |
154 |
|
155 |
# surface |
156 |
bblock = PlaneSurface(bblockloop) |
157 |
|
158 |
#clockwise check as splines must be set as polygons in the point order |
159 |
#they were created. Otherwise get a line across plot. |
160 |
bblockloop2=CurveLoop(mysp,Line(x2,p2),Line(p2,p1),Line(p1,x1)) |
161 |
|
162 |
################################################CREATE MESH FOR ESCRIPT |
163 |
# Create a Design which can make the mesh |
164 |
d=Design(dim=2, element_size=dx, order=2) |
165 |
# Add the subdomains and flux boundaries. |
166 |
d.addItems(PropertySet("top",tblock),PropertySet("bottom",bblock),\ |
167 |
PropertySet("linetop",l30)) |
168 |
# Create the geometry, mesh and Escript domain |
169 |
d.setScriptFileName(os.path.join(save_path,"example08c.geo")) |
170 |
d.setMeshFileName(os.path.join(save_path,"example08c.msh")) |
171 |
domain=MakeDomain(d, optimizeLabeling=True) |
172 |
x=domain.getX() |
173 |
print "Domain has been generated ..." |
174 |
|
175 |
lam=Scalar(0,Function(domain)) |
176 |
lam.setTaggedValue("top",lam1) |
177 |
lam.setTaggedValue("bottom",lam2) |
178 |
mu=Scalar(0,Function(domain)) |
179 |
mu.setTaggedValue("top",mu1) |
180 |
mu.setTaggedValue("bottom",mu2) |
181 |
rho=Scalar(0,Function(domain)) |
182 |
rho.setTaggedValue("top",rho1) |
183 |
rho.setTaggedValue("bottom",rho2) |
184 |
|
185 |
##########################################################ESTABLISH PDE |
186 |
mypde=LinearPDE(domain) # create pde |
187 |
mypde.setSymmetryOn() # turn symmetry on |
188 |
# turn lumping on for more efficient solving |
189 |
#mypde.getSolverOptions().setSolverMethod(mypde.getSolverOptions().LUMPING) |
190 |
kmat = kronecker(domain) # create the kronecker delta function of the domain |
191 |
mypde.setValue(D=rho*kmat) #set the general form value D |
192 |
|
193 |
##########################################################ESTABLISH ABC |
194 |
# Define where the boundary decay will be applied. |
195 |
bn=20. |
196 |
bleft=xstep*bn; bright=width-(xstep*bn); bbot=depth-(ystep*bn) |
197 |
# btop=ystep*bn # don't apply to force boundary!!! |
198 |
|
199 |
# locate these points in the domain |
200 |
left=x[0]-bleft; right=x[0]-bright; bottom=x[1]-bbot |
201 |
|
202 |
tgamma=0.85 # decay value for exponential function |
203 |
def calc_gamma(G,npts): |
204 |
func=np.sqrt(abs(-1.*np.log(G)/(npts**2.))) |
205 |
return func |
206 |
|
207 |
gleft = calc_gamma(tgamma,bleft) |
208 |
gright = calc_gamma(tgamma,bleft) |
209 |
gbottom= calc_gamma(tgamma,ystep*bn) |
210 |
|
211 |
print 'gamma', gleft,gright,gbottom |
212 |
|
213 |
# calculate decay functions |
214 |
def abc_bfunc(gamma,loc,x,G): |
215 |
func=exp(-1.*(gamma*abs(loc-x))**2.) |
216 |
return func |
217 |
|
218 |
fleft=abc_bfunc(gleft,bleft,x[0],tgamma) |
219 |
fright=abc_bfunc(gright,bright,x[0],tgamma) |
220 |
fbottom=abc_bfunc(gbottom,bbot,x[1],tgamma) |
221 |
# apply these functions only where relevant |
222 |
abcleft=fleft*whereNegative(left) |
223 |
abcright=fright*wherePositive(right) |
224 |
abcbottom=fbottom*wherePositive(bottom) |
225 |
# make sure the inside of the abc is value 1 |
226 |
abcleft=abcleft+whereZero(abcleft) |
227 |
abcright=abcright+whereZero(abcright) |
228 |
abcbottom=abcbottom+whereZero(abcbottom) |
229 |
# multiply the conditions together to get a smooth result |
230 |
abc=abcleft*abcright*abcbottom |
231 |
|
232 |
############################################FIRST TIME STEPS AND SOURCE |
233 |
# define small radius around point xc |
234 |
src_length = 40; print "src_length = ",src_length |
235 |
# set initial values for first two time steps with source terms |
236 |
xb=FunctionOnBoundary(domain).getX() |
237 |
y=source[0]*(cos(length(x-xc)*3.1415/src_length)+1)*whereNegative(length(xb-src_length)) |
238 |
src_dir=numpy.array([0.,1.]) # defines direction of point source as down |
239 |
y=y*src_dir |
240 |
mypde.setValue(y=y) #set the source as a function on the boundary |
241 |
# initial value of displacement at point source is constant (U0=0.01) |
242 |
# for first two time steps |
243 |
u=[0.0,0.0]*wherePositive(x) |
244 |
u_m1=u |
245 |
|
246 |
####################################################ITERATION VARIABLES |
247 |
n=0 # iteration counter |
248 |
t=0 # time counter |
249 |
##############################################################ITERATION |
250 |
while t<tend: |
251 |
# get current stress |
252 |
g=grad(u); stress=lam*trace(g)*kmat+mu*(g+transpose(g)) |
253 |
mypde.setValue(X=-stress*abc) # set PDE values |
254 |
accel = mypde.getSolution() #get PDE solution for accelleration |
255 |
u_p1=(2.*u-u_m1)+h*h*accel #calculate displacement |
256 |
u_p1=u_p1*abc # apply boundary conditions |
257 |
u_m1=u; u=u_p1 # shift values by 1 |
258 |
# save current displacement, acceleration and pressure |
259 |
if (t >= rtime): |
260 |
saveVTK(os.path.join(save_path,"ex08c.%05d.vtu"%n),\ |
261 |
vector_displacement=u,displacement=length(u),\ |
262 |
vector_acceleration=accel,acceleration=length(accel),\ |
263 |
tensor=stress) |
264 |
rtime=rtime+rtime_inc #increment data save time |
265 |
# increment loop values |
266 |
t=t+h; n=n+1 |
267 |
if (n < ls): |
268 |
y=source[n]*(cos(length(x-xc)*3.1415/src_length)+1)*whereNegative(length(x-xc)-src_length) |
269 |
y=y*src_dir; mypde.setValue(y=y) #set the source as a function on the boundary |
270 |
print n,"-th time step t ",t |