1 |
jgs |
102 |
# $Id$ |
2 |
|
|
|
3 |
|
|
## @file linearPDEs.py |
4 |
|
|
|
5 |
|
|
""" |
6 |
|
|
@brief Functions and classes for linear PDEs |
7 |
|
|
""" |
8 |
|
|
|
9 |
|
|
import escript |
10 |
|
|
import util |
11 |
|
|
import numarray |
12 |
|
|
|
13 |
|
|
def identifyDomain(domain=None,data={}): |
14 |
|
|
""" |
15 |
|
|
@brief Return the Domain which is equal to the input domain (if not None) |
16 |
|
|
and is the domain of all Data objects in the dictionary data. |
17 |
|
|
An exception is raised if this is not possible |
18 |
|
|
|
19 |
|
|
@param domain |
20 |
|
|
@param data |
21 |
|
|
""" |
22 |
|
|
# get the domain used by any Data object in the list data: |
23 |
|
|
data_domain=None |
24 |
|
|
for d in data.itervalues(): |
25 |
|
|
if isinstance(d,escript.Data): |
26 |
|
|
if not d.isEmpty(): data_domain=d.getDomain() |
27 |
|
|
# check if domain and data_domain are identical? |
28 |
|
|
if domain == None: |
29 |
|
|
if data_domain == None: |
30 |
|
|
raise ValueError,"Undefined PDE domain. Specify a domain or use a Data class object as coefficient" |
31 |
|
|
else: |
32 |
|
|
if data_domain == None: |
33 |
|
|
data_domain=domain |
34 |
|
|
else: |
35 |
|
|
if not data_domain == domain: |
36 |
|
|
raise ValueError,"Domain of coefficients doesnot match specified domain" |
37 |
|
|
# now we check if all Data class object coefficients are defined on data_domain: |
38 |
|
|
for i,d in data.iteritems(): |
39 |
|
|
if isinstance(d,escript.Data): |
40 |
|
|
if not d.isEmpty(): |
41 |
|
|
if not data_domain==d.getDomain(): |
42 |
|
|
raise ValueError,"Illegal domain for coefficient %s."%i |
43 |
|
|
# done: |
44 |
|
|
return data_domain |
45 |
|
|
|
46 |
|
|
def identifyNumEquationsAndSolutions(dim,coef={}): |
47 |
|
|
# get number of equations and number of unknowns: |
48 |
|
|
numEquations=0 |
49 |
|
|
numSolutions=0 |
50 |
|
|
for i in coef.iterkeys(): |
51 |
|
|
if not coef[i].isEmpty(): |
52 |
|
|
res=_PDECoefficientTypes[i].estimateNumEquationsAndNumSolutions(coef[i].getShape(),dim) |
53 |
|
|
if res==None: |
54 |
|
|
raise ValueError,"Illegal shape %s of coefficient %s"%(coef[i].getShape().__str__(),i) |
55 |
|
|
else: |
56 |
|
|
numEquations=max(numEquations,res[0]) |
57 |
|
|
numSolutions=max(numSolutions,res[1]) |
58 |
|
|
return numEquations,numSolutions |
59 |
|
|
|
60 |
|
|
|
61 |
|
|
def _CompTuple2(t1,t2): |
62 |
|
|
""" |
63 |
|
|
@brief |
64 |
|
|
|
65 |
|
|
@param t1 |
66 |
|
|
@param t2 |
67 |
|
|
""" |
68 |
|
|
dif=t1[0]+t1[1]-(t2[0]+t2[1]) |
69 |
|
|
if dif<0: return 1 |
70 |
|
|
elif dif>0: return -1 |
71 |
|
|
else: return 0 |
72 |
|
|
|
73 |
|
|
class PDECoefficientType: |
74 |
|
|
""" |
75 |
|
|
@brief |
76 |
|
|
""" |
77 |
|
|
# identifier for location of Data objects defining coefficients |
78 |
|
|
INTERIOR=0 |
79 |
|
|
BOUNDARY=1 |
80 |
|
|
CONTACT=2 |
81 |
|
|
CONTINUOUS=3 |
82 |
|
|
# identifier in the pattern of coefficients: |
83 |
|
|
# the pattern is a tuple of EQUATION,SOLUTION,DIM where DIM represents the spatial dimension, EQUATION the number of equations and SOLUTION the |
84 |
|
|
# number of unknowns. |
85 |
|
|
EQUATION=3 |
86 |
|
|
SOLUTION=4 |
87 |
|
|
DIM=5 |
88 |
|
|
# indicator for what is altered if the coefficient is altered: |
89 |
|
|
OPERATOR=5 |
90 |
|
|
RIGHTHANDSIDE=6 |
91 |
|
|
BOTH=7 |
92 |
|
|
def __init__(self,where,pattern,altering): |
93 |
|
|
""" |
94 |
|
|
@brief Initialise a PDE Coefficient type |
95 |
|
|
""" |
96 |
|
|
self.what=where |
97 |
|
|
self.pattern=pattern |
98 |
|
|
self.altering=altering |
99 |
|
|
|
100 |
|
|
def getFunctionSpace(self,domain): |
101 |
|
|
""" |
102 |
|
|
@brief defines the FunctionSpace of the coefficient on the domain |
103 |
|
|
|
104 |
|
|
@param domain |
105 |
|
|
""" |
106 |
|
|
if self.what==self.INTERIOR: return escript.Function(domain) |
107 |
|
|
elif self.what==self.BOUNDARY: return escript.FunctionOnBoundary(domain) |
108 |
|
|
elif self.what==self.CONTACT: return escript.FunctionOnContactZero(domain) |
109 |
|
|
elif self.what==self.CONTINUOUS: return escript.ContinuousFunction(domain) |
110 |
|
|
|
111 |
|
|
def isAlteringOperator(self): |
112 |
|
|
""" |
113 |
|
|
@brief return true if the operator of the PDE is changed when the coefficient is changed |
114 |
|
|
""" |
115 |
|
|
if self.altering==self.OPERATOR or self.altering==self.BOTH: |
116 |
|
|
return not None |
117 |
|
|
else: |
118 |
|
|
return None |
119 |
|
|
|
120 |
|
|
def isAlteringRightHandSide(self): |
121 |
|
|
""" |
122 |
|
|
@brief return true if the right hand side of the PDE is changed when the coefficient is changed |
123 |
|
|
""" |
124 |
|
|
if self.altering==self.RIGHTHANDSIDE or self.altering==self.BOTH: |
125 |
|
|
return not None |
126 |
|
|
else: |
127 |
|
|
return None |
128 |
|
|
|
129 |
|
|
def estimateNumEquationsAndNumSolutions(self,shape=(),dim=3): |
130 |
|
|
""" |
131 |
|
|
@brief tries to estimate the number of equations in a given tensor shape for a given spatial dimension dim |
132 |
|
|
|
133 |
|
|
@param shape |
134 |
|
|
@param dim |
135 |
|
|
""" |
136 |
|
|
if len(shape)>0: |
137 |
|
|
num=max(shape)+1 |
138 |
|
|
else: |
139 |
|
|
num=1 |
140 |
|
|
search=[] |
141 |
|
|
for u in range(num): |
142 |
|
|
for e in range(num): |
143 |
|
|
search.append((e,u)) |
144 |
|
|
search.sort(_CompTuple2) |
145 |
|
|
for item in search: |
146 |
|
|
s=self.buildShape(item[0],item[1],dim) |
147 |
|
|
if len(s)==0 and len(shape)==0: |
148 |
|
|
return (1,1) |
149 |
|
|
else: |
150 |
|
|
if s==shape: return item |
151 |
|
|
return None |
152 |
|
|
|
153 |
|
|
def buildShape(self,e=1,u=1,dim=3): |
154 |
|
|
""" |
155 |
|
|
@brief builds the required shape for a given number of equations e, number of unknowns u and spatial dimension dim |
156 |
|
|
|
157 |
|
|
@param e |
158 |
|
|
@param u |
159 |
|
|
@param dim |
160 |
|
|
""" |
161 |
|
|
s=() |
162 |
|
|
for i in self.pattern: |
163 |
|
|
if i==self.EQUATION: |
164 |
|
|
if e>1: s=s+(e,) |
165 |
|
|
elif i==self.SOLUTION: |
166 |
|
|
if u>1: s=s+(u,) |
167 |
|
|
else: |
168 |
|
|
s=s+(dim,) |
169 |
|
|
return s |
170 |
|
|
|
171 |
|
|
_PDECoefficientTypes={ |
172 |
|
|
"A" : PDECoefficientType(PDECoefficientType.INTERIOR,(PDECoefficientType.EQUATION,PDECoefficientType.DIM,PDECoefficientType.SOLUTION,PDECoefficientType.DIM),PDECoefficientType.OPERATOR), |
173 |
|
|
"B" : PDECoefficientType(PDECoefficientType.INTERIOR,(PDECoefficientType.EQUATION,PDECoefficientType.DIM,PDECoefficientType.SOLUTION),PDECoefficientType.OPERATOR), |
174 |
|
|
"C" : PDECoefficientType(PDECoefficientType.INTERIOR,(PDECoefficientType.EQUATION,PDECoefficientType.SOLUTION,PDECoefficientType.DIM),PDECoefficientType.OPERATOR), |
175 |
|
|
"D" : PDECoefficientType(PDECoefficientType.INTERIOR,(PDECoefficientType.EQUATION,PDECoefficientType.SOLUTION),PDECoefficientType.OPERATOR), |
176 |
|
|
"X" : PDECoefficientType(PDECoefficientType.INTERIOR,(PDECoefficientType.EQUATION,PDECoefficientType.DIM),PDECoefficientType.RIGHTHANDSIDE), |
177 |
|
|
"Y" : PDECoefficientType(PDECoefficientType.INTERIOR,(PDECoefficientType.EQUATION,),PDECoefficientType.RIGHTHANDSIDE), |
178 |
|
|
"d" : PDECoefficientType(PDECoefficientType.BOUNDARY,(PDECoefficientType.EQUATION,PDECoefficientType.SOLUTION),PDECoefficientType.OPERATOR), |
179 |
|
|
"y" : PDECoefficientType(PDECoefficientType.BOUNDARY,(PDECoefficientType.EQUATION,),PDECoefficientType.RIGHTHANDSIDE), |
180 |
|
|
"d_contact" : PDECoefficientType(PDECoefficientType.CONTACT,(PDECoefficientType.EQUATION,PDECoefficientType.SOLUTION),PDECoefficientType.OPERATOR), |
181 |
|
|
"y_contact" : PDECoefficientType(PDECoefficientType.CONTACT,(PDECoefficientType.EQUATION,),PDECoefficientType.RIGHTHANDSIDE), |
182 |
|
|
"r" : PDECoefficientType(PDECoefficientType.CONTINUOUS,(PDECoefficientType.EQUATION,),PDECoefficientType.RIGHTHANDSIDE), |
183 |
|
|
"q" : PDECoefficientType(PDECoefficientType.CONTINUOUS,(PDECoefficientType.SOLUTION,),PDECoefficientType.BOTH), |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
class LinearPDE: |
187 |
|
|
""" |
188 |
|
|
@brief Class to define a linear PDE |
189 |
|
|
|
190 |
|
|
class to define a linear PDE of the form |
191 |
|
|
|
192 |
|
|
-(A_{ijkl}u_{k,l})_{,j} -(B_{ijk}u_k)_{,j} + C_{ikl}u_{k,l} +D_{ik}u_k = - (X_{ij})_{,j} + Y_i |
193 |
|
|
|
194 |
|
|
with boundary conditons: |
195 |
|
|
|
196 |
|
|
n_j*(A_{ijkl}u_{k,l}+B_{ijk}u_k)_{,j} + d_{ik}u_k = - n_j*X_{ij} + y_i |
197 |
|
|
|
198 |
|
|
and contact conditions |
199 |
|
|
|
200 |
|
|
n_j*(A_{ijkl}u_{k,l}+B_{ijk}u_k)_{,j} + d_contact_{ik}[u_k] = - n_j*X_{ij} + y_contact_i |
201 |
|
|
|
202 |
|
|
and constraints: |
203 |
|
|
|
204 |
|
|
u_i=r_i where q_i>0 |
205 |
|
|
|
206 |
|
|
""" |
207 |
|
|
DEFAULT_METHOD=util.DEFAULT_METHOD |
208 |
|
|
DIRECT=util.DIRECT |
209 |
|
|
CHOLEVSKY=util.CHOLEVSKY |
210 |
|
|
PCG=util.PCG |
211 |
|
|
CR=util.CR |
212 |
|
|
CGS=util.CGS |
213 |
|
|
BICGSTAB=util.BICGSTAB |
214 |
|
|
SSOR=util.SSOR |
215 |
|
|
GMRES=util.GMRES |
216 |
|
|
PRES20=util.PRES20 |
217 |
|
|
|
218 |
|
|
def __init__(self,**args): |
219 |
|
|
""" |
220 |
|
|
@brief initializes a new linear PDE. |
221 |
|
|
|
222 |
|
|
@param args |
223 |
|
|
""" |
224 |
|
|
|
225 |
|
|
# initialize attributes |
226 |
|
|
self.__debug=None |
227 |
|
|
self.__domain=None |
228 |
|
|
self.__numEquations=0 |
229 |
|
|
self.__numSolutions=0 |
230 |
|
|
self.cleanCoefficients() |
231 |
|
|
|
232 |
|
|
self.__operator=escript.Operator() |
233 |
|
|
self.__operator_isValid=False |
234 |
|
|
self.__righthandside=escript.Data() |
235 |
|
|
self.__righthandside_isValid=False |
236 |
|
|
self.__solution=escript.Data() |
237 |
|
|
self.__solution_isValid=False |
238 |
|
|
|
239 |
|
|
# check the arguments |
240 |
|
|
coef={} |
241 |
|
|
for arg in args.iterkeys(): |
242 |
|
|
if arg=="domain": |
243 |
|
|
self.__domain=args[arg] |
244 |
|
|
elif arg=="numEquations": |
245 |
|
|
self.__numEquations=args[arg] |
246 |
|
|
elif arg=="numSolutions": |
247 |
|
|
self.__numSolutions=args[arg] |
248 |
|
|
elif _PDECoefficientTypes.has_key(arg): |
249 |
|
|
coef[arg]=args[arg] |
250 |
|
|
else: |
251 |
|
|
raise ValueError,"Illegal argument %s"%arg |
252 |
|
|
|
253 |
|
|
# get the domain of the PDE |
254 |
|
|
self.__domain=identifyDomain(self.__domain,coef) |
255 |
|
|
|
256 |
|
|
# set some default values: |
257 |
|
|
self.__homogeneous_constraint=True |
258 |
|
|
self.__row_function_space=escript.Solution(self.__domain) |
259 |
|
|
self.__column_function_space=escript.Solution(self.__domain) |
260 |
|
|
self.__tolerance=1.e-8 |
261 |
|
|
self.__solver_method=util.DEFAULT_METHOD |
262 |
|
|
self.__matrix_type=self.__domain.getSystemMatrixTypeId(util.DEFAULT_METHOD,False) |
263 |
|
|
self.__sym=False |
264 |
|
|
self.__lumping=False |
265 |
|
|
self.__numEquations=0 |
266 |
|
|
self.__numSolutions=0 |
267 |
|
|
# now we can set the ceofficients: |
268 |
|
|
self._setCoefficient(**coef) |
269 |
|
|
|
270 |
|
|
def getCoefficient(self,name): |
271 |
|
|
""" |
272 |
|
|
@brief return the value of the coefficient name |
273 |
|
|
|
274 |
|
|
@param name |
275 |
|
|
""" |
276 |
|
|
return self.__coefficient[name] |
277 |
|
|
|
278 |
|
|
def setValue(self,**coefficients): |
279 |
|
|
""" |
280 |
|
|
@brief sets new values to coefficients |
281 |
|
|
|
282 |
|
|
@param coefficients |
283 |
|
|
""" |
284 |
|
|
self._setCoefficient(**coefficients) |
285 |
|
|
|
286 |
|
|
|
287 |
|
|
def _setCoefficient(self,**coefficients): |
288 |
|
|
""" |
289 |
|
|
@brief sets new values to coefficients |
290 |
|
|
|
291 |
|
|
@param coefficients |
292 |
|
|
""" |
293 |
|
|
|
294 |
|
|
# get the dictionary of the coefficinets been altered: |
295 |
|
|
alteredCoefficients={} |
296 |
|
|
for i,d in coefficients.iteritems(): |
297 |
|
|
if self.hasCoefficient(i): |
298 |
|
|
if d == None: |
299 |
|
|
alteredCoefficients[i]=escript.Data() |
300 |
|
|
elif isinstance(d,escript.Data): |
301 |
|
|
if d.isEmpty(): |
302 |
|
|
alteredCoefficients[i]=escript.Data() |
303 |
|
|
else: |
304 |
|
|
alteredCoefficients[i]=escript.Data(d,self.getFunctionSpaceOfCoefficient(i)) |
305 |
|
|
else: |
306 |
|
|
if self.__numEquations>0 and self.__numSolutions>0: |
307 |
|
|
alteredCoefficients[i]=escript.Data(d,self.getShapeOfCoefficient(i),self.getFunctionSpaceOfCoefficient(i)) |
308 |
|
|
else: |
309 |
|
|
alteredCoefficients[i]=escript.Data(d,self.getFunctionSpaceOfCoefficient(i)) |
310 |
|
|
else: |
311 |
|
|
raise ValueError,"Attempt to set undefined coefficient %s"%i |
312 |
|
|
# if numEquations and numSolutions is undefined we try identify their values based on the coefficients: |
313 |
|
|
if self.__numEquations<1 or self.__numSolutions<1: |
314 |
|
|
numEquations,numSolutions=identifyNumEquationsAndSolutions(self.getDomain().getDim(),alteredCoefficients) |
315 |
|
|
if self.__numEquations<1 and numEquations>0: self.__numEquations=numEquations |
316 |
|
|
if self.__numSolutions<1 and numSolutions>0: self.__numSolutions=numSolutions |
317 |
|
|
if self.debug() and self.__numEquations>0: print "PDE Debug: identified number of equations is ",self.__numEquations |
318 |
|
|
if self.debug() and self.__numSolutions>0: print "PDE Debug: identified number of solutions is ",self.__numSolutions |
319 |
|
|
|
320 |
|
|
# now we check the shape of the coefficient if numEquations and numSolutions are set: |
321 |
|
|
if self.__numEquations>0 and self.__numSolutions>0: |
322 |
|
|
for i in self.__coefficient.iterkeys(): |
323 |
|
|
if alteredCoefficients.has_key(i) and not alteredCoefficients[i].isEmpty(): |
324 |
|
|
if not self.getShapeOfCoefficient(i)==alteredCoefficients[i].getShape(): |
325 |
|
|
raise ValueError,"Expected shape for coefficient %s is %s but actual shape is %s."%(i,self.getShapeOfCoefficient(i),alteredCoefficients[i].getShape()) |
326 |
|
|
else: |
327 |
|
|
if not self.__coefficient[i].isEmpty(): |
328 |
|
|
if not self.getShapeOfCoefficient(i)==self.__coefficient[i].getShape(): |
329 |
|
|
raise ValueError,"Expected shape for coefficient %s is %s but actual shape is %s."%(i,self.getShapeOfCoefficient(i),self.__coefficient[i].getShape()) |
330 |
|
|
# overwrite new values: |
331 |
|
|
for i,d in alteredCoefficients.iteritems(): |
332 |
|
|
if self.debug(): print "PDE Debug: Coefficient %s has been altered."%i |
333 |
|
|
self.__coefficient[i]=d |
334 |
|
|
self.alteredCoefficient(i) |
335 |
|
|
|
336 |
|
|
# reset the HomogeneousConstraintFlag: |
337 |
|
|
self.__setHomogeneousConstraintFlag() |
338 |
|
|
if not "q" in alteredCoefficients and not self.__homogeneous_constraint: self.__rebuildSystem() |
339 |
|
|
|
340 |
|
|
def cleanCoefficients(self): |
341 |
|
|
""" |
342 |
|
|
@brief resets all coefficients to default values. |
343 |
|
|
""" |
344 |
|
|
self.__coefficient={} |
345 |
|
|
for i in _PDECoefficientTypes.iterkeys(): |
346 |
|
|
self.__coefficient[i]=escript.Data() |
347 |
|
|
|
348 |
|
|
def getShapeOfCoefficient(self,name): |
349 |
|
|
""" |
350 |
|
|
@brief return the shape of the coefficient name |
351 |
|
|
|
352 |
|
|
@param name |
353 |
|
|
""" |
354 |
|
|
if self.hasCoefficient(name): |
355 |
|
|
return _PDECoefficientTypes[name].buildShape(self.getNumEquations(),self.getNumSolutions(),self.getDomain().getDim()) |
356 |
|
|
else: |
357 |
|
|
raise ValueError,"Solution coefficient %s requested"%name |
358 |
|
|
|
359 |
|
|
def getFunctionSpaceOfCoefficient(self,name): |
360 |
|
|
""" |
361 |
|
|
@brief return the atoms of the coefficient name |
362 |
|
|
|
363 |
|
|
@param name |
364 |
|
|
""" |
365 |
|
|
if self.hasCoefficient(name): |
366 |
|
|
return _PDECoefficientTypes[name].getFunctionSpace(self.getDomain()) |
367 |
|
|
else: |
368 |
|
|
raise ValueError,"Solution coefficient %s requested"%name |
369 |
|
|
|
370 |
|
|
def alteredCoefficient(self,name): |
371 |
|
|
""" |
372 |
|
|
@brief annonced that coefficient name has been changed |
373 |
|
|
|
374 |
|
|
@param name |
375 |
|
|
""" |
376 |
|
|
if self.hasCoefficient(name): |
377 |
|
|
if _PDECoefficientTypes[name].isAlteringOperator(): self.__rebuildOperator() |
378 |
|
|
if _PDECoefficientTypes[name].isAlteringRightHandSide(): self.__rebuildRightHandSide() |
379 |
|
|
else: |
380 |
|
|
raise ValueError,"Solution coefficient %s requested"%name |
381 |
|
|
|
382 |
|
|
def __setHomogeneousConstraintFlag(self): |
383 |
|
|
""" |
384 |
|
|
@brief checks if the constraints are homogeneous and sets self.__homogeneous_constraint accordingly. |
385 |
|
|
""" |
386 |
|
|
self.__homogeneous_constraint=True |
387 |
|
|
q=self.getCoefficient("q") |
388 |
|
|
r=self.getCoefficient("r") |
389 |
|
|
if not q.isEmpty() and not r.isEmpty(): |
390 |
|
|
print (q*r).Lsup(), 1.e-13*r.Lsup() |
391 |
|
|
if (q*r).Lsup()>=1.e-13*r.Lsup(): self.__homogeneous_constraint=False |
392 |
|
|
if self.debug(): |
393 |
|
|
if self.__homogeneous_constraint: |
394 |
|
|
print "PDE Debug: Constraints are homogeneous." |
395 |
|
|
else: |
396 |
|
|
print "PDE Debug: Constraints are inhomogeneous." |
397 |
|
|
|
398 |
|
|
|
399 |
|
|
def hasCoefficient(self,name): |
400 |
|
|
""" |
401 |
|
|
@brief return true if name is the name of a coefficient |
402 |
|
|
|
403 |
|
|
@param name |
404 |
|
|
""" |
405 |
|
|
return self.__coefficient.has_key(name) |
406 |
|
|
|
407 |
|
|
def getFunctionSpaceForEquation(self): |
408 |
|
|
""" |
409 |
|
|
@brief return true if the test functions should use reduced order |
410 |
|
|
""" |
411 |
|
|
return self.__row_function_space |
412 |
|
|
|
413 |
|
|
def getFunctionSpaceForSolution(self): |
414 |
|
|
""" |
415 |
|
|
@brief return true if the interpolation of the solution should use reduced order |
416 |
|
|
""" |
417 |
|
|
return self.__column_function_space |
418 |
|
|
|
419 |
|
|
# ===== debug ============================================================== |
420 |
|
|
def setDebugOn(self): |
421 |
|
|
""" |
422 |
|
|
@brief |
423 |
|
|
""" |
424 |
|
|
self.__debug=not None |
425 |
|
|
|
426 |
|
|
def setDebugOff(self): |
427 |
|
|
""" |
428 |
|
|
@brief |
429 |
|
|
""" |
430 |
|
|
self.__debug=None |
431 |
|
|
|
432 |
|
|
def debug(self): |
433 |
|
|
""" |
434 |
|
|
@brief returns true if the PDE is in the debug mode |
435 |
|
|
""" |
436 |
|
|
return self.__debug |
437 |
|
|
|
438 |
|
|
#===== Lumping =========================== |
439 |
|
|
def setLumpingOn(self): |
440 |
|
|
""" |
441 |
|
|
@brief indicates to use matrix lumping |
442 |
|
|
""" |
443 |
|
|
if not self.isUsingLumping(): |
444 |
|
|
raise SystemError,"Lumping is not working yet! Talk to the experts" |
445 |
|
|
if self.debug() : print "PDE Debug: lumping is set on" |
446 |
|
|
self.__rebuildOperator() |
447 |
|
|
self.__lumping=True |
448 |
|
|
|
449 |
|
|
def setLumpingOff(self): |
450 |
|
|
""" |
451 |
|
|
@brief switches off matrix lumping |
452 |
|
|
""" |
453 |
|
|
if self.isUsingLumping(): |
454 |
|
|
if self.debug() : print "PDE Debug: lumping is set off" |
455 |
|
|
self.__rebuildOperator() |
456 |
|
|
self.__lumping=False |
457 |
|
|
|
458 |
|
|
def setLumping(self,flag=False): |
459 |
|
|
""" |
460 |
|
|
@brief set the matrix lumping flag to flag |
461 |
|
|
""" |
462 |
|
|
if flag: |
463 |
|
|
self.setLumpingOn() |
464 |
|
|
else: |
465 |
|
|
self.setLumpingOff() |
466 |
|
|
|
467 |
|
|
def isUsingLumping(self): |
468 |
|
|
""" |
469 |
|
|
@brief |
470 |
|
|
""" |
471 |
|
|
return self.__lumping |
472 |
|
|
|
473 |
|
|
#============ method business ========================================================= |
474 |
|
|
def setSolverMethod(self,solver=util.DEFAULT_METHOD): |
475 |
|
|
""" |
476 |
|
|
@brief sets a new solver |
477 |
|
|
""" |
478 |
|
|
if not solver==self.getSolverMethod(): |
479 |
|
|
self.__solver_method=solver |
480 |
|
|
if self.debug() : print "PDE Debug: New solver is %s"%solver |
481 |
|
|
self.__checkMatrixType() |
482 |
|
|
|
483 |
|
|
def getSolverMethod(self): |
484 |
|
|
""" |
485 |
|
|
@brief returns the solver method |
486 |
|
|
""" |
487 |
|
|
return self.__solver_method |
488 |
|
|
|
489 |
|
|
#============ tolerance business ========================================================= |
490 |
|
|
def setTolerance(self,tol=1.e-8): |
491 |
|
|
""" |
492 |
|
|
@brief resets the tolerance to tol. |
493 |
|
|
""" |
494 |
|
|
if not tol>0: |
495 |
|
|
raise ValueException,"Tolerance as to be positive" |
496 |
|
|
if tol<self.getTolerance(): self.__rebuildSolution() |
497 |
|
|
if self.debug() : print "PDE Debug: New tolerance %e",tol |
498 |
|
|
self.__tolerance=tol |
499 |
|
|
return |
500 |
|
|
def getTolerance(self): |
501 |
|
|
""" |
502 |
|
|
@brief returns the tolerance set for the solution |
503 |
|
|
""" |
504 |
|
|
return self.__tolerance |
505 |
|
|
|
506 |
|
|
#===== symmetry flag ========================== |
507 |
|
|
def isSymmetric(self): |
508 |
|
|
""" |
509 |
|
|
@brief returns true is the operator is considered to be symmetric |
510 |
|
|
""" |
511 |
|
|
return self.__sym |
512 |
|
|
|
513 |
|
|
def setSymmetryOn(self): |
514 |
|
|
""" |
515 |
|
|
@brief sets the symmetry flag to true |
516 |
|
|
""" |
517 |
|
|
if not self.isSymmetric(): |
518 |
|
|
if self.debug() : print "PDE Debug: Operator is set to be symmetric" |
519 |
|
|
self.__sym=True |
520 |
|
|
self.__checkMatrixType() |
521 |
|
|
|
522 |
|
|
def setSymmetryOff(self): |
523 |
|
|
""" |
524 |
|
|
@brief sets the symmetry flag to false |
525 |
|
|
""" |
526 |
|
|
if self.isSymmetric(): |
527 |
|
|
if self.debug() : print "PDE Debug: Operator is set to be unsymmetric" |
528 |
|
|
self.__sym=False |
529 |
|
|
self.__checkMatrixType() |
530 |
|
|
|
531 |
|
|
def setSymmetryTo(self,flag=False): |
532 |
|
|
""" |
533 |
|
|
@brief sets the symmetry flag to flag |
534 |
|
|
|
535 |
|
|
@param flag |
536 |
|
|
""" |
537 |
|
|
if flag: |
538 |
|
|
self.setSymmetryOn() |
539 |
|
|
else: |
540 |
|
|
self.setSymmetryOff() |
541 |
|
|
|
542 |
|
|
#===== order reduction ========================== |
543 |
|
|
def setReducedOrderOn(self): |
544 |
|
|
""" |
545 |
|
|
@brief switches to on reduced order |
546 |
|
|
""" |
547 |
|
|
self.setReducedOrderForSolutionOn() |
548 |
|
|
self.setReducedOrderForEquationOn() |
549 |
|
|
|
550 |
|
|
def setReducedOrderOff(self): |
551 |
|
|
""" |
552 |
|
|
@brief switches to full order |
553 |
|
|
""" |
554 |
|
|
self.setReducedOrderForSolutionOff() |
555 |
|
|
self.setReducedOrderForEquationOff() |
556 |
|
|
|
557 |
|
|
def setReducedOrderTo(self,flag=False): |
558 |
|
|
""" |
559 |
|
|
@brief sets order according to flag |
560 |
|
|
|
561 |
|
|
@param flag |
562 |
|
|
""" |
563 |
|
|
self.setReducedOrderForSolutionTo(flag) |
564 |
|
|
self.setReducedOrderForEquationTo(flag) |
565 |
|
|
|
566 |
|
|
|
567 |
|
|
#===== order reduction solution ========================== |
568 |
|
|
def setReducedOrderForSolutionOn(self): |
569 |
|
|
""" |
570 |
|
|
@brief switches to reduced order to interpolate solution |
571 |
|
|
""" |
572 |
|
|
new_fs=escript.ReducedSolution(self.getDomain()) |
573 |
|
|
if self.getFunctionSpaceForSolution()!=new_fs: |
574 |
|
|
if self.debug() : print "PDE Debug: Reduced order is used to interpolate solution." |
575 |
|
|
self.__column_function_space=new_fs |
576 |
|
|
self.__rebuildSystem(deep=True) |
577 |
|
|
|
578 |
|
|
def setReducedOrderForSolutionOff(self): |
579 |
|
|
""" |
580 |
|
|
@brief switches to full order to interpolate solution |
581 |
|
|
""" |
582 |
|
|
new_fs=escript.Solution(self.getDomain()) |
583 |
|
|
if self.getFunctionSpaceForSolution()!=new_fs: |
584 |
|
|
if self.debug() : print "PDE Debug: Full order is used to interpolate solution." |
585 |
|
|
self.__column_function_space=new_fs |
586 |
|
|
self.__rebuildSystem(deep=True) |
587 |
|
|
|
588 |
|
|
def setReducedOrderForSolutionTo(self,flag=False): |
589 |
|
|
""" |
590 |
|
|
@brief sets order for test functions according to flag |
591 |
|
|
|
592 |
|
|
@param flag |
593 |
|
|
""" |
594 |
|
|
if flag: |
595 |
|
|
self.setReducedOrderForSolutionOn() |
596 |
|
|
else: |
597 |
|
|
self.setReducedOrderForSolutionOff() |
598 |
|
|
|
599 |
|
|
#===== order reduction equation ========================== |
600 |
|
|
def setReducedOrderForEquationOn(self): |
601 |
|
|
""" |
602 |
|
|
@brief switches to reduced order for test functions |
603 |
|
|
""" |
604 |
|
|
new_fs=escript.ReducedSolution(self.getDomain()) |
605 |
|
|
if self.getFunctionSpaceForEquation()!=new_fs: |
606 |
|
|
if self.debug() : print "PDE Debug: Reduced order is used for test functions." |
607 |
|
|
self.__row_function_space=new_fs |
608 |
|
|
self.__rebuildSystem(deep=True) |
609 |
|
|
|
610 |
|
|
def setReducedOrderForEquationOff(self): |
611 |
|
|
""" |
612 |
|
|
@brief switches to full order for test functions |
613 |
|
|
""" |
614 |
|
|
new_fs=escript.Solution(self.getDomain()) |
615 |
|
|
if self.getFunctionSpaceForEquation()!=new_fs: |
616 |
|
|
if self.debug() : print "PDE Debug: Full order is used for test functions." |
617 |
|
|
self.__row_function_space=new_fs |
618 |
|
|
self.__rebuildSystem(deep=True) |
619 |
|
|
|
620 |
|
|
def setReducedOrderForEquationTo(self,flag=False): |
621 |
|
|
""" |
622 |
|
|
@brief sets order for test functions according to flag |
623 |
|
|
|
624 |
|
|
@param flag |
625 |
|
|
""" |
626 |
|
|
if flag: |
627 |
|
|
self.setReducedOrderForEquationOn() |
628 |
|
|
else: |
629 |
|
|
self.setReducedOrderForEquationOff() |
630 |
|
|
|
631 |
|
|
|
632 |
|
|
# ==== initialization ===================================================================== |
633 |
|
|
def __makeNewOperator(self): |
634 |
|
|
""" |
635 |
|
|
@brief |
636 |
|
|
""" |
637 |
|
|
return self.getDomain().newOperator( \ |
638 |
|
|
self.getNumEquations(), \ |
639 |
|
|
self.getFunctionSpaceForEquation(), \ |
640 |
|
|
self.getNumSolutions(), \ |
641 |
|
|
self.getFunctionSpaceForSolution(), \ |
642 |
|
|
self.__matrix_type) |
643 |
|
|
|
644 |
|
|
def __makeNewRightHandSide(self): |
645 |
|
|
""" |
646 |
|
|
@brief |
647 |
|
|
""" |
648 |
|
|
return escript.Data(0.,(self.getNumEquations(),),self.getFunctionSpaceForEquation(),True) |
649 |
|
|
|
650 |
|
|
def __makeNewSolution(self): |
651 |
|
|
""" |
652 |
|
|
@brief |
653 |
|
|
""" |
654 |
|
|
return escript.Data(0.,(self.getNumSolutions(),),self.getFunctionSpaceForSolution(),True) |
655 |
|
|
|
656 |
|
|
def __getFreshOperator(self): |
657 |
|
|
""" |
658 |
|
|
@brief |
659 |
|
|
""" |
660 |
|
|
if self.__operator.isEmpty(): |
661 |
|
|
self.__operator=self.__makeNewOperator() |
662 |
|
|
if self.debug() : print "PDE Debug: New operator allocated" |
663 |
|
|
else: |
664 |
|
|
self.__operator.setValue(0.) |
665 |
|
|
if self.debug() : print "PDE Debug: Operator reset to zero" |
666 |
|
|
return self.__operator |
667 |
|
|
|
668 |
|
|
def __getFreshRightHandSide(self): |
669 |
|
|
""" |
670 |
|
|
@brief |
671 |
|
|
""" |
672 |
|
|
if self.__righthandside.isEmpty(): |
673 |
|
|
self.__righthandside=self.__makeNewRightHandSide() |
674 |
|
|
if self.debug() : print "PDE Debug: New right hand side allocated" |
675 |
|
|
else: |
676 |
|
|
print "fix self.__righthandside*=0" |
677 |
|
|
self.__righthandside*=0. |
678 |
|
|
if self.debug() : print "PDE Debug: Right hand side reset to zero" |
679 |
|
|
return self.__righthandside |
680 |
|
|
|
681 |
|
|
# ==== rebuild switches ===================================================================== |
682 |
|
|
def __rebuildSolution(self,deep=False): |
683 |
|
|
""" |
684 |
|
|
@brief indicates the PDE has to be reolved if the solution is requested |
685 |
|
|
""" |
686 |
|
|
if self.__solution_isValid and self.debug() : print "PDE Debug: PDE has to be resolved." |
687 |
|
|
self.__solution_isValid=False |
688 |
|
|
if deep: self.__solution=escript.Data(deep) |
689 |
|
|
|
690 |
|
|
|
691 |
|
|
def __rebuildOperator(self,deep=False): |
692 |
|
|
""" |
693 |
|
|
@brief indicates the operator has to be rebuilt next time it is used |
694 |
|
|
""" |
695 |
|
|
if self.__operator_isValid and self.debug() : print "PDE Debug: Operator has to be rebuilt." |
696 |
|
|
self.__rebuildSolution(deep) |
697 |
|
|
self.__operator_isValid=False |
698 |
|
|
if deep: self.__operator=escript.Operator() |
699 |
|
|
|
700 |
|
|
def __rebuildRightHandSide(self,deep=False): |
701 |
|
|
""" |
702 |
|
|
@brief indicates the right hand side has to be rebuild next time it is used |
703 |
|
|
""" |
704 |
|
|
if self.__righthandside_isValid and self.debug() : print "PDE Debug: Right hand side has to be rebuilt." |
705 |
|
|
self.__rebuildSolution(deep) |
706 |
|
|
self.__righthandside_isValid=False |
707 |
|
|
if not self.__homogeneous_constraint: self.__rebuildOperator() |
708 |
|
|
if deep: self.__righthandside=escript.Data() |
709 |
|
|
|
710 |
|
|
def __rebuildSystem(self,deep=False): |
711 |
|
|
""" |
712 |
|
|
@brief annonced that all coefficient name has been changed |
713 |
|
|
""" |
714 |
|
|
self.__rebuildSolution(deep) |
715 |
|
|
self.__rebuildOperator(deep) |
716 |
|
|
self.__rebuildRightHandSide(deep) |
717 |
|
|
|
718 |
|
|
def __checkMatrixType(self): |
719 |
|
|
""" |
720 |
|
|
@brief reassess the matrix type and, if needed, initiates an operator rebuild |
721 |
|
|
""" |
722 |
|
|
new_matrix_type=self.getDomain().getSystemMatrixTypeId(self.getSolverMethod(),self.isSymmetric()) |
723 |
|
|
if not new_matrix_type==self.__matrix_type: |
724 |
|
|
if self.debug() : print "PDE Debug: Matrix type is now %d."%new_matrix_type |
725 |
|
|
self.__matrix_type=new_matrix_type |
726 |
|
|
self.__rebuildOperator(deep=True) |
727 |
|
|
|
728 |
|
|
#============ assembling ======================================================= |
729 |
|
|
def __copyConstraint(self,u): |
730 |
|
|
""" |
731 |
|
|
@brief copies the constrint condition into u |
732 |
|
|
""" |
733 |
|
|
q=self.getCoefficient("q") |
734 |
|
|
r=self.getCoefficient("r") |
735 |
|
|
if not q.isEmpty(): |
736 |
|
|
if r.isEmpty(): |
737 |
|
|
r2=escript.Data(0,u.getShape(),u.getFunctionSpace()) |
738 |
|
|
else: |
739 |
|
|
r2=escript.Data(r,u.getFunctionSpace()) |
740 |
|
|
u.copyWithMask(r2,escript.Data(q,u.getFunctionSpace())) |
741 |
|
|
|
742 |
|
|
def __applyConstraint(self,rhs_update=True): |
743 |
|
|
""" |
744 |
|
|
@brief applies the constraints defined by q and r to the system |
745 |
|
|
""" |
746 |
|
|
q=self.getCoefficient("q") |
747 |
|
|
r=self.getCoefficient("r") |
748 |
|
|
if not q.isEmpty() and not self.__operator.isEmpty(): |
749 |
|
|
# q is the row and column mask to indicate where constraints are set: |
750 |
|
|
row_q=escript.Data(q,self.getFunctionSpaceForEquation()) |
751 |
|
|
col_q=escript.Data(q,self.getFunctionSpaceForSolution()) |
752 |
|
|
u=self.__makeNewSolution() |
753 |
|
|
if r.isEmpty(): |
754 |
|
|
r_s=self.__makeNewSolution() |
755 |
|
|
else: |
756 |
|
|
r_s=escript.Data(r,self.getFunctionSpaceForSolution()) |
757 |
|
|
u.copyWithMask(r_s,col_q) |
758 |
|
|
if not self.__righthandside.isEmpty() and rhs_update: self.__righthandside-=self.__operator*u |
759 |
|
|
self.__operator.nullifyRowsAndCols(row_q,col_q,1.) |
760 |
|
|
|
761 |
|
|
def getOperator(self): |
762 |
|
|
""" |
763 |
|
|
@brief returns the operator of the PDE |
764 |
|
|
""" |
765 |
|
|
if not self.__operator_isValid: |
766 |
|
|
# some Constraints are applying for a lumpled stifness matrix: |
767 |
|
|
if self.isUsingLumping(): |
768 |
|
|
if self.getFunctionSpaceForEquation()==self.getFunctionSpaceForSolution(): |
769 |
|
|
raise TypeError,"Lumped matrix requires same order for equations and unknowns" |
770 |
|
|
if not self.getCoefficient("A").isEmpty(): |
771 |
|
|
raise Warning,"Lumped matrix does not allow coefficient A" |
772 |
|
|
if not self.getCoefficient("B").isEmpty(): |
773 |
|
|
raise Warning,"Lumped matrix does not allow coefficient B" |
774 |
|
|
if not self.getCoefficient("C").isEmpty(): |
775 |
|
|
raise Warning,"Lumped matrix does not allow coefficient C" |
776 |
|
|
if not self.getCoefficient("D").isEmpty(): |
777 |
|
|
raise Warning,"Lumped matrix does not allow coefficient D" |
778 |
|
|
if self.debug() : print "PDE Debug: New lumped operator is built." |
779 |
|
|
mat=self.__makeNewOperator(self) |
780 |
|
|
else: |
781 |
|
|
if self.debug() : print "PDE Debug: New operator is built." |
782 |
|
|
mat=self.__getFreshOperator() |
783 |
|
|
|
784 |
|
|
self.getDomain().addPDEToSystem(mat,escript.Data(), \ |
785 |
|
|
self.getCoefficient("A"), \ |
786 |
|
|
self.getCoefficient("B"), \ |
787 |
|
|
self.getCoefficient("C"), \ |
788 |
|
|
self.getCoefficient("D"), \ |
789 |
|
|
escript.Data(), \ |
790 |
|
|
escript.Data(), \ |
791 |
|
|
self.getCoefficient("d"), \ |
792 |
|
|
escript.Data(),\ |
793 |
|
|
self.getCoefficient("d_contact"), \ |
794 |
|
|
escript.Data()) |
795 |
|
|
if self.isUsingLumping(): |
796 |
|
|
self.__operator=mat*escript.Data(1,(self.getNumSolutions(),),self.getFunctionSpaceOfSolution(),True) |
797 |
|
|
else: |
798 |
|
|
self.__applyConstraint(rhs_update=False) |
799 |
|
|
self.__operator_isValid=True |
800 |
|
|
return self.__operator |
801 |
|
|
|
802 |
|
|
def getRightHandSide(self,ignoreConstraint=False): |
803 |
|
|
""" |
804 |
|
|
@brief returns the right hand side of the PDE |
805 |
|
|
|
806 |
|
|
@param ignoreConstraint |
807 |
|
|
""" |
808 |
|
|
if not self.__righthandside_isValid: |
809 |
|
|
if self.debug() : print "PDE Debug: New right hand side is built." |
810 |
|
|
self.getDomain().addPDEToRHS(self.__getFreshRightHandSide(), \ |
811 |
|
|
self.getCoefficient("X"), \ |
812 |
|
|
self.getCoefficient("Y"),\ |
813 |
|
|
self.getCoefficient("y"),\ |
814 |
|
|
self.getCoefficient("y_contact")) |
815 |
|
|
self.__righthandside_isValid=True |
816 |
|
|
if ignoreConstraint: self.__copyConstraint(self.__righthandside) |
817 |
|
|
return self.__righthandside |
818 |
|
|
|
819 |
|
|
def getSystem(self): |
820 |
|
|
""" |
821 |
|
|
@brief |
822 |
|
|
""" |
823 |
|
|
if not self.__operator_isValid and not self.__righthandside_isValid: |
824 |
|
|
if self.debug() : print "PDE Debug: New PDE is built." |
825 |
|
|
if self.isUsingLumping(): |
826 |
|
|
self.getRightHandSide(ignoreConstraint=True) |
827 |
|
|
self.getOperator() |
828 |
|
|
else: |
829 |
|
|
self.getDomain().addPDEToSystem(self.__getFreshOperator(),self.__getFreshRightHandSide(), \ |
830 |
|
|
self.getCoefficient("A"), \ |
831 |
|
|
self.getCoefficient("B"), \ |
832 |
|
|
self.getCoefficient("C"), \ |
833 |
|
|
self.getCoefficient("D"), \ |
834 |
|
|
self.getCoefficient("X"), \ |
835 |
|
|
self.getCoefficient("Y"), \ |
836 |
|
|
self.getCoefficient("d"), \ |
837 |
|
|
self.getCoefficient("y"), \ |
838 |
|
|
self.getCoefficient("d_contact"), \ |
839 |
|
|
self.getCoefficient("y_contact")) |
840 |
|
|
self.__operator_isValid=True |
841 |
|
|
self.__righthandside_isValid=True |
842 |
|
|
self.__applyConstraint() |
843 |
|
|
self.__copyConstraint(self.__righthandside) |
844 |
|
|
elif not self.__operator_isValid: |
845 |
|
|
self.getOperator() |
846 |
|
|
elif not self.__righthandside_isValid: |
847 |
|
|
self.getRightHandSide() |
848 |
|
|
return (self.__operator,self.__righthandside) |
849 |
|
|
|
850 |
|
|
def solve(self,**options): |
851 |
|
|
""" |
852 |
|
|
@brief solve the PDE |
853 |
|
|
|
854 |
|
|
@param options |
855 |
|
|
""" |
856 |
|
|
mat,f=self.getSystem() |
857 |
|
|
if self.isUsingLumping(): |
858 |
|
|
out=f/mat |
859 |
|
|
self.__copyConstraint(out) |
860 |
|
|
else: |
861 |
|
|
options[util.TOLERANCE_KEY]=self.getTolerance() |
862 |
|
|
options[util.METHOD_KEY]=self.getSolverMethod() |
863 |
|
|
options[util.SYMMETRY_KEY]=self.isSymmetric() |
864 |
|
|
if self.debug() : print "PDE Debug: solver options: ",options |
865 |
|
|
out=mat.solve(f,options) |
866 |
|
|
return out |
867 |
|
|
|
868 |
|
|
def getSolution(self,**options): |
869 |
|
|
""" |
870 |
|
|
@brief returns the solution of the PDE |
871 |
|
|
|
872 |
|
|
@param options |
873 |
|
|
""" |
874 |
|
|
if not self.__solution_isValid: |
875 |
|
|
if self.debug() : print "PDE Debug: PDE is resolved." |
876 |
|
|
self.__solution=self.solve(**options) |
877 |
|
|
self.__solution_isValid=True |
878 |
|
|
return self.__solution |
879 |
|
|
#============ some serivice functions ===================================================== |
880 |
|
|
def getDomain(self): |
881 |
|
|
""" |
882 |
|
|
@brief returns the domain of the PDE |
883 |
|
|
""" |
884 |
|
|
return self.__domain |
885 |
|
|
|
886 |
|
|
def getNumEquations(self): |
887 |
|
|
""" |
888 |
|
|
@brief returns the number of equations |
889 |
|
|
""" |
890 |
|
|
if self.__numEquations>0: |
891 |
|
|
return self.__numEquations |
892 |
|
|
else: |
893 |
|
|
raise ValueError,"Number of equations is undefined. Please specify argument numEquations." |
894 |
|
|
|
895 |
|
|
def getNumSolutions(self): |
896 |
|
|
""" |
897 |
|
|
@brief returns the number of unknowns |
898 |
|
|
""" |
899 |
|
|
if self.__numSolutions>0: |
900 |
|
|
return self.__numSolutions |
901 |
|
|
else: |
902 |
|
|
raise ValueError,"Number of solution is undefined. Please specify argument numSolutions." |
903 |
|
|
|
904 |
|
|
|
905 |
|
|
def checkSymmetry(self): |
906 |
|
|
""" |
907 |
|
|
@brief returns if the Operator is symmetric. This is a very expensive operation!!! The symmetry flag is not altered. |
908 |
|
|
""" |
909 |
|
|
raise SystemError,"checkSymmetry is not implemented yet" |
910 |
|
|
|
911 |
|
|
return None |
912 |
|
|
|
913 |
|
|
def getFlux(self,u): |
914 |
|
|
""" |
915 |
|
|
@brief returns the flux J_ij for a given u |
916 |
|
|
|
917 |
|
|
J_ij=A_{ijkl}u_{k,l}+B_{ijk}u_k-X_{ij} |
918 |
|
|
|
919 |
|
|
@param u argument of the operator |
920 |
|
|
|
921 |
|
|
""" |
922 |
|
|
raise SystemError,"getFlux is not implemented yet" |
923 |
|
|
return None |
924 |
|
|
|
925 |
|
|
def applyOperator(self,u): |
926 |
|
|
""" |
927 |
|
|
@brief applies the operator of the PDE to a given solution u in weak from |
928 |
|
|
|
929 |
|
|
@param u argument of the operator |
930 |
|
|
|
931 |
|
|
""" |
932 |
|
|
return self.getOperator()*escript.Data(u,self.getFunctionSpaceForSolution()) |
933 |
|
|
|
934 |
|
|
def getResidual(self,u): |
935 |
|
|
""" |
936 |
|
|
@brief return the residual of u in the weak from |
937 |
|
|
|
938 |
|
|
@param u |
939 |
|
|
""" |
940 |
|
|
return self.applyOperator(u)-self.getRightHandSide() |
941 |
|
|
|
942 |
|
|
class Poisson(LinearPDE): |
943 |
|
|
""" |
944 |
|
|
@brief Class to define a Poisson equstion problem: |
945 |
|
|
|
946 |
|
|
class to define a linear PDE of the form |
947 |
|
|
|
948 |
|
|
-u_{,jj} = f |
949 |
|
|
|
950 |
|
|
with boundary conditons: |
951 |
|
|
|
952 |
|
|
n_j*u_{,j} = 0 |
953 |
|
|
|
954 |
|
|
and constraints: |
955 |
|
|
|
956 |
|
|
u=0 where q>0 |
957 |
|
|
|
958 |
|
|
""" |
959 |
|
|
|
960 |
|
|
def __init__(self,domain=None,f=escript.Data(),q=escript.Data()): |
961 |
|
|
LinearPDE.__init__(self,domain=identifyDomain(domain,{"f":f, "q":q})) |
962 |
|
|
self._setCoefficient(A=numarray.identity(self.getDomain().getDim())) |
963 |
|
|
self.setSymmetryOn() |
964 |
|
|
self.setValue(f,q) |
965 |
|
|
|
966 |
|
|
def setValue(self,f=escript.Data(),q=escript.Data()): |
967 |
|
|
self._setCoefficient(Y=f,q=q) |
968 |
|
|
|
969 |
|
|
|
970 |
|
|
# $Log$ |
971 |
|
|
# Revision 1.2 2004/12/15 07:08:27 jgs |
972 |
|
|
# *** empty log message *** |
973 |
|
|
# |
974 |
|
|
# Revision 1.1.2.2 2004/12/14 03:55:01 jgs |
975 |
|
|
# *** empty log message *** |
976 |
|
|
# |
977 |
|
|
# Revision 1.1.2.1 2004/12/12 22:53:47 gross |
978 |
|
|
# linearPDE has been renamed LinearPDE |
979 |
|
|
# |
980 |
|
|
# Revision 1.1.1.1.2.7 2004/12/07 10:13:08 gross |
981 |
|
|
# GMRES added |
982 |
|
|
# |
983 |
|
|
# Revision 1.1.1.1.2.6 2004/12/07 03:19:50 gross |
984 |
|
|
# options for GMRES and PRES20 added |
985 |
|
|
# |
986 |
|
|
# Revision 1.1.1.1.2.5 2004/12/01 06:25:15 gross |
987 |
|
|
# some small changes |
988 |
|
|
# |
989 |
|
|
# Revision 1.1.1.1.2.4 2004/11/24 01:50:21 gross |
990 |
|
|
# Finley solves 4M unknowns now |
991 |
|
|
# |
992 |
|
|
# Revision 1.1.1.1.2.3 2004/11/15 06:05:26 gross |
993 |
|
|
# poisson solver added |
994 |
|
|
# |
995 |
|
|
# Revision 1.1.1.1.2.2 2004/11/12 06:58:15 gross |
996 |
|
|
# a lot of changes to get the linearPDE class running: most important change is that there is no matrix format exposed to the user anymore. the format is chosen by the Domain according to the solver and symmetry |
997 |
|
|
# |
998 |
|
|
# Revision 1.1.1.1.2.1 2004/10/28 22:59:22 gross |
999 |
|
|
# finley's RecTest.py is running now: problem in SystemMatrixAdapater fixed |
1000 |
|
|
# |
1001 |
|
|
# Revision 1.1.1.1 2004/10/26 06:53:56 jgs |
1002 |
|
|
# initial import of project esys2 |
1003 |
|
|
# |
1004 |
|
|
# Revision 1.3.2.3 2004/10/26 06:43:48 jgs |
1005 |
|
|
# committing Lutz's and Paul's changes to brach jgs |
1006 |
|
|
# |
1007 |
|
|
# Revision 1.3.4.1 2004/10/20 05:32:51 cochrane |
1008 |
|
|
# Added incomplete Doxygen comments to files, or merely put the docstrings that already exist into Doxygen form. |
1009 |
|
|
# |
1010 |
|
|
# Revision 1.3 2004/09/23 00:53:23 jgs |
1011 |
|
|
# minor fixes |
1012 |
|
|
# |
1013 |
|
|
# Revision 1.1 2004/08/28 12:58:06 gross |
1014 |
|
|
# SimpleSolve is not running yet: problem with == of functionsspace |
1015 |
|
|
# |
1016 |
|
|
# |