1 |
# |
2 |
# $Id$ |
3 |
# |
4 |
####################################################### |
5 |
# |
6 |
# Copyright 2003-2007 by ACceSS MNRF |
7 |
# Copyright 2007 by University of Queensland |
8 |
# |
9 |
# http://esscc.uq.edu.au |
10 |
# Primary Business: Queensland, Australia |
11 |
# Licensed under the Open Software License version 3.0 |
12 |
# http://www.opensource.org/licenses/osl-3.0.php |
13 |
# |
14 |
####################################################### |
15 |
# |
16 |
|
17 |
__copyright__=""" Copyright (c) 2006 by ACcESS MNRF |
18 |
http://www.access.edu.au |
19 |
Primary Business: Queensland, Australia""" |
20 |
__license__="""Licensed under the Open Software License version 3.0 |
21 |
http://www.opensource.org/licenses/osl-3.0.php""" |
22 |
|
23 |
from esys.escript import * |
24 |
from esys.escript.modelframe import Model,IterationDivergenceError |
25 |
from esys.escript.linearPDEs import LinearPDE |
26 |
|
27 |
class Mechanics(Model): |
28 |
""" |
29 |
base class for mechanics models in updated lagrangean framework |
30 |
|
31 |
@ivar domain: domain (in) |
32 |
@ivar internal_force: =Data() |
33 |
@ivar external_force: =Data() |
34 |
@ivar prescribed_velocity: =Data() |
35 |
@ivar location_prescribed_velocity: =Data() |
36 |
@ivar temperature: = None |
37 |
@ivar expansion_coefficient: = 0. |
38 |
@ivar bulk_modulus: =1. |
39 |
@ivar shear_modulus: =1. |
40 |
@ivar rel_tol: =1.e-3 |
41 |
@ivar abs_tol: =1.e-15 |
42 |
@ivar max_iter: =10 |
43 |
@ivar displacement: =None |
44 |
@ivar stress: =None |
45 |
""" |
46 |
SAFTY_FACTOR_ITERATION=1./100. |
47 |
def __init__(self,**kwargs): |
48 |
""" |
49 |
set up the model |
50 |
|
51 |
@param debug: debug flag |
52 |
@type debug: C{bool} |
53 |
""" |
54 |
super(Mechanics, self).__init__(self,**kwargs) |
55 |
self.declareParameter(domain=None, \ |
56 |
displacement=None, \ |
57 |
stress=None, \ |
58 |
velocity=None, \ |
59 |
internal_force=None, \ |
60 |
external_force=None, \ |
61 |
prescribed_velocity=None, \ |
62 |
location_prescribed_velocity=None, \ |
63 |
temperature = None, \ |
64 |
expansion_coefficient = 0., \ |
65 |
bulk_modulus=2., \ |
66 |
shear_modulus=1., \ |
67 |
rel_tol=1.e-3,abs_tol=1.e-15,max_iter=10) |
68 |
self.__iter=0 |
69 |
|
70 |
def doInitialization(self): |
71 |
""" |
72 |
initialize model |
73 |
""" |
74 |
if not self.displacement: self.displacement=Vector(0.,ContinuousFunction(self.domain)) |
75 |
if not self.velocity: self.velocity=Vector(0.,ContinuousFunction(self.domain)) |
76 |
if not self.stress: self.stress=Tensor(0.,ContinuousFunction(self.domain)) |
77 |
if not self.internal_force: self.internal_force = Data() |
78 |
if not self.external_force: self.external_force = Data() |
79 |
if not self.prescribed_velocity: self.prescribed_velocity = Data() |
80 |
if not self.location_prescribed_velocity: self.location_prescribed_velocity =Data() |
81 |
# save the old values: |
82 |
self.__stress_safe=self.stress |
83 |
self.__temperature_safe=self.temperature |
84 |
self.__displacement_safe=self.displacement |
85 |
self.__velocity_safe=self.velocity |
86 |
self.__velocity_old=None |
87 |
self.__old_dt=None |
88 |
self.__very_old_dt=None |
89 |
# get node cooridnates and apply initial displacement |
90 |
self.__x=self.domain.getX() |
91 |
self.domain.setX(self.__x+self.displacement) |
92 |
# open PDE: |
93 |
self.__pde=LinearPDE(self.domain) |
94 |
self.__pde.setSolverMethod(self.__pde.DIRECT) |
95 |
# self.__pde.setSymmetryOn() |
96 |
|
97 |
def doStepPreprocessing(self,dt): |
98 |
""" |
99 |
step up pressure iteration |
100 |
|
101 |
if run within a time dependend problem extrapolation of pressure from previous time steps is used to |
102 |
get an initial guess (that needs some work!!!!!!!) |
103 |
""" |
104 |
# reset iteration counters: |
105 |
self.__iter=0 |
106 |
self.__diff=self.UNDEF_DT |
107 |
# set initial guesses for the iteration: |
108 |
self.displacement=self.__displacement_safe |
109 |
self.stress=self.__stress_safe |
110 |
self.velocity=self.__velocity_safe |
111 |
# update geometry |
112 |
self.domain.setX(self.__x+self.displacement) |
113 |
|
114 |
def doStep(self,dt): |
115 |
""" |
116 |
""" |
117 |
self.__iter+=1 |
118 |
k3=kronecker(self.domain) |
119 |
# set new thermal stress increment |
120 |
if self.temperature == None: |
121 |
self.deps_th=0. |
122 |
else: |
123 |
self.deps_th=self.expansion_coefficient*(self.temperature-self.__temperature_safe) |
124 |
# set PDE coefficients: |
125 |
self.__pde.setValue(A=self.S) |
126 |
self.__pde.setValue(X=-self.stress-self.bulk_modulus*self.deps_th*k3) |
127 |
if self.internal_force: self.__pde.setValue(Y=self.internal_force) |
128 |
if self.external_force: self.__pde.setValue(y=self.external_force) |
129 |
self.__pde.setValue(q=self.location_prescribed_velocity, \ |
130 |
r=Data()) |
131 |
if not self.prescribed_velocity.isEmpty() and self.__iter==1: |
132 |
self.__pde.setValue(r=dt*self.prescribed_velocity) |
133 |
# solve the PDE: |
134 |
self.__pde.setTolerance(self.rel_tol**2) |
135 |
self.du=self.__pde.getSolution(verbose=self.debug) |
136 |
# update geometry |
137 |
self.displacement=self.displacement+self.du |
138 |
self.domain.setX(self.__x+self.displacement) |
139 |
self.velocity=(self.displacement-self.__displacement_safe)/dt |
140 |
|
141 |
if self.debug: |
142 |
for i in range(self.domain.getDim()): |
143 |
self.trace("du %d range %e:%e"%(i,inf(self.du[i]),sup(self.du[i]))) |
144 |
for i in range(self.domain.getDim()): |
145 |
self.trace("displacement %d range %e:%e"%(i,inf(self.displacement[i]),sup(self.displacement[i]))) |
146 |
for i in range(self.domain.getDim()): |
147 |
self.trace("velocity %d range %e:%e"%(i,inf(self.velocity[i]),sup(self.velocity[i]))) |
148 |
self.__stress_last=self.stress |
149 |
|
150 |
def terminateIteration(self): |
151 |
"""iteration is terminateIterationd if relative pressure change is less then rel_tol""" |
152 |
if self.__iter>self.max_iter: |
153 |
raise IterationDivergenceError,"Maximum number of iterations steps reached" |
154 |
if self.__iter==0: |
155 |
self.__diff=self.UNDEF_DT |
156 |
else: |
157 |
self.__diff,diff_safe=Lsup(self.stress-self.__stress_last),self.__diff |
158 |
s_sup=Lsup(self.stress) |
159 |
self.trace("stress max and increment :%e, %e"%(s_sup,self.__diff)) |
160 |
if self.__iter>2 and diff_safe<self.__diff: |
161 |
raise IterationDivergenceError,"no improvement in stress iteration" |
162 |
return self.__diff<=self.rel_tol*self.SAFTY_FACTOR_ITERATION*s_sup+self.abs_tol |
163 |
|
164 |
def doStepPostprocessing(self,dt): |
165 |
""" |
166 |
accept all the values: |
167 |
""" |
168 |
self.__displacement_safe=self.displacement |
169 |
self.__temperature_safe=self.temperature |
170 |
self.__stress_safe=self.stress |
171 |
self.__velocity_safe=self.velocity |
172 |
|
173 |
def getSafeTimeStepSize(self,dt): |
174 |
""" |
175 |
returns new step size |
176 |
""" |
177 |
a=sup(length(self.velocity)/self.domain.getSize()) |
178 |
if a>0: |
179 |
return 1./a |
180 |
else: |
181 |
return self.UNDEF_DT |
182 |
|
183 |
|
184 |
|
185 |
class DruckerPrager(Mechanics): |
186 |
""" |
187 |
|
188 |
""" |
189 |
|
190 |
def __init__(self,**kwargs): |
191 |
""" |
192 |
set up model |
193 |
""" |
194 |
super(DruckerPrager, self).__init__(**kwargs) |
195 |
self.declareParameter(plastic_stress=0., |
196 |
hardening=0., |
197 |
friction_parameter=0., |
198 |
dilatancy_parameter=0., |
199 |
shear_length=1.e15) |
200 |
def doInitialization(self): |
201 |
""" |
202 |
""" |
203 |
super(DruckerPrager, self).doInitialization() |
204 |
self.__plastic_stress_safe=self.plastic_stress |
205 |
self.__shear_length_safe=self.shear_length |
206 |
self.__hardening_safe=self.hardening |
207 |
self.__chi_safe=0 |
208 |
self.__tau_safe=0 |
209 |
|
210 |
def doStepPreprocessing(self,dt): |
211 |
""" |
212 |
""" |
213 |
super(DruckerPrager, self).doStepPreprocessing(dt) |
214 |
# set initial guess for iteration: |
215 |
self.shear_length=self.__shear_length_safe |
216 |
self.plastic_stress=self.__plastic_stress_safe |
217 |
self.hardening=self.__hardening_safe |
218 |
self.__chi=self.__chi_safe |
219 |
self.__tau=self.__tau_safe |
220 |
|
221 |
def doStep(self,dt): |
222 |
# set new tangential operator: |
223 |
self.setTangentialTensor() |
224 |
# do the update step: |
225 |
super(DruckerPrager, self).doStep(dt) |
226 |
# update stresses: |
227 |
self.setStress() |
228 |
|
229 |
def doStepPostprocessing(self,dt): |
230 |
super(DruckerPrager, self).doStepPostprocessing(dt) |
231 |
self.__plastic_stress_safe=self.plastic_stress |
232 |
self.__shear_length_safe=self.shear_length |
233 |
self.__hardening_safe=self.hardening |
234 |
self.__chi_safe=self.__chi |
235 |
self.__tau_safe=self.__tau |
236 |
|
237 |
def setStress(self): |
238 |
d=self.domain.getDim() |
239 |
G=self.shear_modulus |
240 |
K=self.bulk_modulus |
241 |
alpha=self.friction_parameter |
242 |
beta=self.dilatancy_parameter |
243 |
h=self.hardening |
244 |
k3=kronecker(self.domain) |
245 |
# elastic trial stress: |
246 |
g=grad(self.du) |
247 |
D=symmetric(g) |
248 |
W=nonsymmetric(g) |
249 |
s_e=self.stress+K*self.deps_th*k3+ \ |
250 |
2*G*D+(K-2./3*G)*trace(D)*k3 \ |
251 |
+2*symmetric(matrix_mult(W,self.stress)) |
252 |
p_e=-1./d*trace(s_e) |
253 |
s_e_dev=s_e+p_e*k3 |
254 |
tau_e=sqrt(1./2*inner(s_e_dev,s_e_dev)) |
255 |
# yield conditon for elastic trial stress: |
256 |
F=tau_e-alpha*p_e-self.shear_length |
257 |
self.__chi=whereNonNegative(F+(self.rel_tol*(self.SAFTY_FACTOR_ITERATION)**2)*self.shear_length) |
258 |
# plastic stress increment: |
259 |
l=self.__chi*F/(h+G+beta*K) |
260 |
self.__tau=tau_e-G*l |
261 |
self.stress=self.__tau/(tau_e+self.abs_tol*whereZero(tau_e,self.abs_tol))*s_e_dev-(p_e+l*beta*K)*k3 |
262 |
self.plastic_stress=self.plastic_stress+l |
263 |
# update hardening |
264 |
self.hardening=(self.shear_length-self.__shear_length_safe)/(l+self.abs_tol*whereZero(l)) |
265 |
|
266 |
def setTangentialTensor(self): |
267 |
d=self.domain.getDim() |
268 |
G=self.shear_modulus |
269 |
K=self.bulk_modulus |
270 |
alpha=self.friction_parameter |
271 |
beta=self.dilatancy_parameter |
272 |
tau_Y=self.shear_length |
273 |
chi=self.__chi |
274 |
tau=self.__tau |
275 |
h=self.hardening |
276 |
k3=kronecker(Function(self.domain)) |
277 |
|
278 |
sXk3=outer(self.stress,k3) |
279 |
k3Xk3=outer(k3,k3) |
280 |
s_dev=self.stress-trace(self.stress)*(k3/d) |
281 |
tmp=G*s_dev/(tau+self.abs_tol*whereZero(tau,self.abs_tol)) |
282 |
|
283 |
self.S=G*(swap_axes(k3Xk3,0,3)+swap_axes(k3Xk3,1,3)) \ |
284 |
+ (K-2./3*G)*k3Xk3 \ |
285 |
+ (sXk3-swap_axes(swap_axes(sXk3,1,2),2,3)) \ |
286 |
+ 1./2*(swap_axes(swap_axes(sXk3,0,2),2,3) \ |
287 |
-swap_axes(swap_axes(sXk3,0,3),2,3) \ |
288 |
-swap_axes(sXk3,1,2) \ |
289 |
+swap_axes(sXk3,1,3) ) \ |
290 |
- outer(chi/(h+G+alpha*beta*K)*(tmp+beta*K*k3),tmp+alpha*K*k3) |