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 |
jgs |
104 |
def __init__(self,domain,numEquations=0,numSolutions=0): |
219 |
jgs |
102 |
""" |
220 |
|
|
@brief initializes a new linear PDE. |
221 |
|
|
|
222 |
|
|
@param args |
223 |
|
|
""" |
224 |
|
|
|
225 |
|
|
# initialize attributes |
226 |
|
|
self.__debug=None |
227 |
jgs |
104 |
self.__domain=domain |
228 |
|
|
self.__numEquations=numEquations |
229 |
|
|
self.__numSolutions=numSolutions |
230 |
jgs |
102 |
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 |
|
|
# set some default values: |
240 |
|
|
self.__homogeneous_constraint=True |
241 |
|
|
self.__row_function_space=escript.Solution(self.__domain) |
242 |
|
|
self.__column_function_space=escript.Solution(self.__domain) |
243 |
|
|
self.__tolerance=1.e-8 |
244 |
|
|
self.__solver_method=util.DEFAULT_METHOD |
245 |
|
|
self.__matrix_type=self.__domain.getSystemMatrixTypeId(util.DEFAULT_METHOD,False) |
246 |
|
|
self.__sym=False |
247 |
|
|
self.__lumping=False |
248 |
|
|
|
249 |
|
|
def getCoefficient(self,name): |
250 |
|
|
""" |
251 |
|
|
@brief return the value of the coefficient name |
252 |
|
|
|
253 |
|
|
@param name |
254 |
|
|
""" |
255 |
|
|
return self.__coefficient[name] |
256 |
|
|
|
257 |
|
|
def setValue(self,**coefficients): |
258 |
|
|
""" |
259 |
|
|
@brief sets new values to coefficients |
260 |
|
|
|
261 |
|
|
@param coefficients |
262 |
|
|
""" |
263 |
jgs |
104 |
self._setValue(**coefficients) |
264 |
jgs |
102 |
|
265 |
|
|
|
266 |
jgs |
104 |
def _setValue(self,**coefficients): |
267 |
jgs |
102 |
""" |
268 |
|
|
@brief sets new values to coefficients |
269 |
|
|
|
270 |
|
|
@param coefficients |
271 |
|
|
""" |
272 |
|
|
|
273 |
|
|
# get the dictionary of the coefficinets been altered: |
274 |
|
|
alteredCoefficients={} |
275 |
|
|
for i,d in coefficients.iteritems(): |
276 |
|
|
if self.hasCoefficient(i): |
277 |
|
|
if d == None: |
278 |
|
|
alteredCoefficients[i]=escript.Data() |
279 |
|
|
elif isinstance(d,escript.Data): |
280 |
|
|
if d.isEmpty(): |
281 |
|
|
alteredCoefficients[i]=escript.Data() |
282 |
|
|
else: |
283 |
|
|
alteredCoefficients[i]=escript.Data(d,self.getFunctionSpaceOfCoefficient(i)) |
284 |
|
|
else: |
285 |
jgs |
104 |
alteredCoefficients[i]=escript.Data(d,self.getFunctionSpaceOfCoefficient(i)) |
286 |
jgs |
102 |
else: |
287 |
|
|
raise ValueError,"Attempt to set undefined coefficient %s"%i |
288 |
|
|
# if numEquations and numSolutions is undefined we try identify their values based on the coefficients: |
289 |
|
|
if self.__numEquations<1 or self.__numSolutions<1: |
290 |
|
|
numEquations,numSolutions=identifyNumEquationsAndSolutions(self.getDomain().getDim(),alteredCoefficients) |
291 |
|
|
if self.__numEquations<1 and numEquations>0: self.__numEquations=numEquations |
292 |
|
|
if self.__numSolutions<1 and numSolutions>0: self.__numSolutions=numSolutions |
293 |
|
|
if self.debug() and self.__numEquations>0: print "PDE Debug: identified number of equations is ",self.__numEquations |
294 |
|
|
if self.debug() and self.__numSolutions>0: print "PDE Debug: identified number of solutions is ",self.__numSolutions |
295 |
|
|
|
296 |
|
|
# now we check the shape of the coefficient if numEquations and numSolutions are set: |
297 |
|
|
if self.__numEquations>0 and self.__numSolutions>0: |
298 |
|
|
for i in self.__coefficient.iterkeys(): |
299 |
|
|
if alteredCoefficients.has_key(i) and not alteredCoefficients[i].isEmpty(): |
300 |
|
|
if not self.getShapeOfCoefficient(i)==alteredCoefficients[i].getShape(): |
301 |
|
|
raise ValueError,"Expected shape for coefficient %s is %s but actual shape is %s."%(i,self.getShapeOfCoefficient(i),alteredCoefficients[i].getShape()) |
302 |
|
|
else: |
303 |
|
|
if not self.__coefficient[i].isEmpty(): |
304 |
|
|
if not self.getShapeOfCoefficient(i)==self.__coefficient[i].getShape(): |
305 |
|
|
raise ValueError,"Expected shape for coefficient %s is %s but actual shape is %s."%(i,self.getShapeOfCoefficient(i),self.__coefficient[i].getShape()) |
306 |
|
|
# overwrite new values: |
307 |
|
|
for i,d in alteredCoefficients.iteritems(): |
308 |
|
|
if self.debug(): print "PDE Debug: Coefficient %s has been altered."%i |
309 |
|
|
self.__coefficient[i]=d |
310 |
|
|
self.alteredCoefficient(i) |
311 |
|
|
|
312 |
|
|
# reset the HomogeneousConstraintFlag: |
313 |
|
|
self.__setHomogeneousConstraintFlag() |
314 |
|
|
if not "q" in alteredCoefficients and not self.__homogeneous_constraint: self.__rebuildSystem() |
315 |
|
|
|
316 |
|
|
def cleanCoefficients(self): |
317 |
|
|
""" |
318 |
|
|
@brief resets all coefficients to default values. |
319 |
|
|
""" |
320 |
|
|
self.__coefficient={} |
321 |
|
|
for i in _PDECoefficientTypes.iterkeys(): |
322 |
|
|
self.__coefficient[i]=escript.Data() |
323 |
|
|
|
324 |
|
|
def getShapeOfCoefficient(self,name): |
325 |
|
|
""" |
326 |
|
|
@brief return the shape of the coefficient name |
327 |
|
|
|
328 |
|
|
@param name |
329 |
|
|
""" |
330 |
|
|
if self.hasCoefficient(name): |
331 |
|
|
return _PDECoefficientTypes[name].buildShape(self.getNumEquations(),self.getNumSolutions(),self.getDomain().getDim()) |
332 |
|
|
else: |
333 |
|
|
raise ValueError,"Solution coefficient %s requested"%name |
334 |
|
|
|
335 |
|
|
def getFunctionSpaceOfCoefficient(self,name): |
336 |
|
|
""" |
337 |
|
|
@brief return the atoms of the coefficient name |
338 |
|
|
|
339 |
|
|
@param name |
340 |
|
|
""" |
341 |
|
|
if self.hasCoefficient(name): |
342 |
|
|
return _PDECoefficientTypes[name].getFunctionSpace(self.getDomain()) |
343 |
|
|
else: |
344 |
|
|
raise ValueError,"Solution coefficient %s requested"%name |
345 |
|
|
|
346 |
|
|
def alteredCoefficient(self,name): |
347 |
|
|
""" |
348 |
|
|
@brief annonced that coefficient name has been changed |
349 |
|
|
|
350 |
|
|
@param name |
351 |
|
|
""" |
352 |
|
|
if self.hasCoefficient(name): |
353 |
|
|
if _PDECoefficientTypes[name].isAlteringOperator(): self.__rebuildOperator() |
354 |
|
|
if _PDECoefficientTypes[name].isAlteringRightHandSide(): self.__rebuildRightHandSide() |
355 |
|
|
else: |
356 |
|
|
raise ValueError,"Solution coefficient %s requested"%name |
357 |
|
|
|
358 |
|
|
def __setHomogeneousConstraintFlag(self): |
359 |
|
|
""" |
360 |
|
|
@brief checks if the constraints are homogeneous and sets self.__homogeneous_constraint accordingly. |
361 |
|
|
""" |
362 |
|
|
self.__homogeneous_constraint=True |
363 |
|
|
q=self.getCoefficient("q") |
364 |
|
|
r=self.getCoefficient("r") |
365 |
|
|
if not q.isEmpty() and not r.isEmpty(): |
366 |
|
|
print (q*r).Lsup(), 1.e-13*r.Lsup() |
367 |
|
|
if (q*r).Lsup()>=1.e-13*r.Lsup(): self.__homogeneous_constraint=False |
368 |
|
|
if self.debug(): |
369 |
|
|
if self.__homogeneous_constraint: |
370 |
|
|
print "PDE Debug: Constraints are homogeneous." |
371 |
|
|
else: |
372 |
|
|
print "PDE Debug: Constraints are inhomogeneous." |
373 |
|
|
|
374 |
|
|
|
375 |
|
|
def hasCoefficient(self,name): |
376 |
|
|
""" |
377 |
|
|
@brief return true if name is the name of a coefficient |
378 |
|
|
|
379 |
|
|
@param name |
380 |
|
|
""" |
381 |
|
|
return self.__coefficient.has_key(name) |
382 |
|
|
|
383 |
|
|
def getFunctionSpaceForEquation(self): |
384 |
|
|
""" |
385 |
|
|
@brief return true if the test functions should use reduced order |
386 |
|
|
""" |
387 |
|
|
return self.__row_function_space |
388 |
|
|
|
389 |
|
|
def getFunctionSpaceForSolution(self): |
390 |
|
|
""" |
391 |
|
|
@brief return true if the interpolation of the solution should use reduced order |
392 |
|
|
""" |
393 |
|
|
return self.__column_function_space |
394 |
|
|
|
395 |
|
|
# ===== debug ============================================================== |
396 |
|
|
def setDebugOn(self): |
397 |
|
|
""" |
398 |
|
|
@brief |
399 |
|
|
""" |
400 |
|
|
self.__debug=not None |
401 |
|
|
|
402 |
|
|
def setDebugOff(self): |
403 |
|
|
""" |
404 |
|
|
@brief |
405 |
|
|
""" |
406 |
|
|
self.__debug=None |
407 |
|
|
|
408 |
|
|
def debug(self): |
409 |
|
|
""" |
410 |
|
|
@brief returns true if the PDE is in the debug mode |
411 |
|
|
""" |
412 |
|
|
return self.__debug |
413 |
|
|
|
414 |
|
|
#===== Lumping =========================== |
415 |
|
|
def setLumpingOn(self): |
416 |
|
|
""" |
417 |
|
|
@brief indicates to use matrix lumping |
418 |
|
|
""" |
419 |
|
|
if not self.isUsingLumping(): |
420 |
|
|
raise SystemError,"Lumping is not working yet! Talk to the experts" |
421 |
|
|
if self.debug() : print "PDE Debug: lumping is set on" |
422 |
|
|
self.__rebuildOperator() |
423 |
|
|
self.__lumping=True |
424 |
|
|
|
425 |
|
|
def setLumpingOff(self): |
426 |
|
|
""" |
427 |
|
|
@brief switches off matrix lumping |
428 |
|
|
""" |
429 |
|
|
if self.isUsingLumping(): |
430 |
|
|
if self.debug() : print "PDE Debug: lumping is set off" |
431 |
|
|
self.__rebuildOperator() |
432 |
|
|
self.__lumping=False |
433 |
|
|
|
434 |
|
|
def setLumping(self,flag=False): |
435 |
|
|
""" |
436 |
|
|
@brief set the matrix lumping flag to flag |
437 |
|
|
""" |
438 |
|
|
if flag: |
439 |
|
|
self.setLumpingOn() |
440 |
|
|
else: |
441 |
|
|
self.setLumpingOff() |
442 |
|
|
|
443 |
|
|
def isUsingLumping(self): |
444 |
|
|
""" |
445 |
|
|
@brief |
446 |
|
|
""" |
447 |
|
|
return self.__lumping |
448 |
|
|
|
449 |
|
|
#============ method business ========================================================= |
450 |
|
|
def setSolverMethod(self,solver=util.DEFAULT_METHOD): |
451 |
|
|
""" |
452 |
|
|
@brief sets a new solver |
453 |
|
|
""" |
454 |
|
|
if not solver==self.getSolverMethod(): |
455 |
|
|
self.__solver_method=solver |
456 |
|
|
if self.debug() : print "PDE Debug: New solver is %s"%solver |
457 |
|
|
self.__checkMatrixType() |
458 |
|
|
|
459 |
|
|
def getSolverMethod(self): |
460 |
|
|
""" |
461 |
|
|
@brief returns the solver method |
462 |
|
|
""" |
463 |
|
|
return self.__solver_method |
464 |
|
|
|
465 |
|
|
#============ tolerance business ========================================================= |
466 |
|
|
def setTolerance(self,tol=1.e-8): |
467 |
|
|
""" |
468 |
|
|
@brief resets the tolerance to tol. |
469 |
|
|
""" |
470 |
|
|
if not tol>0: |
471 |
|
|
raise ValueException,"Tolerance as to be positive" |
472 |
|
|
if tol<self.getTolerance(): self.__rebuildSolution() |
473 |
|
|
if self.debug() : print "PDE Debug: New tolerance %e",tol |
474 |
|
|
self.__tolerance=tol |
475 |
|
|
return |
476 |
|
|
def getTolerance(self): |
477 |
|
|
""" |
478 |
|
|
@brief returns the tolerance set for the solution |
479 |
|
|
""" |
480 |
|
|
return self.__tolerance |
481 |
|
|
|
482 |
|
|
#===== symmetry flag ========================== |
483 |
|
|
def isSymmetric(self): |
484 |
|
|
""" |
485 |
|
|
@brief returns true is the operator is considered to be symmetric |
486 |
|
|
""" |
487 |
|
|
return self.__sym |
488 |
|
|
|
489 |
|
|
def setSymmetryOn(self): |
490 |
|
|
""" |
491 |
|
|
@brief sets the symmetry flag to true |
492 |
|
|
""" |
493 |
|
|
if not self.isSymmetric(): |
494 |
|
|
if self.debug() : print "PDE Debug: Operator is set to be symmetric" |
495 |
|
|
self.__sym=True |
496 |
|
|
self.__checkMatrixType() |
497 |
|
|
|
498 |
|
|
def setSymmetryOff(self): |
499 |
|
|
""" |
500 |
|
|
@brief sets the symmetry flag to false |
501 |
|
|
""" |
502 |
|
|
if self.isSymmetric(): |
503 |
|
|
if self.debug() : print "PDE Debug: Operator is set to be unsymmetric" |
504 |
|
|
self.__sym=False |
505 |
|
|
self.__checkMatrixType() |
506 |
|
|
|
507 |
|
|
def setSymmetryTo(self,flag=False): |
508 |
|
|
""" |
509 |
|
|
@brief sets the symmetry flag to flag |
510 |
|
|
|
511 |
|
|
@param flag |
512 |
|
|
""" |
513 |
|
|
if flag: |
514 |
|
|
self.setSymmetryOn() |
515 |
|
|
else: |
516 |
|
|
self.setSymmetryOff() |
517 |
|
|
|
518 |
|
|
#===== order reduction ========================== |
519 |
|
|
def setReducedOrderOn(self): |
520 |
|
|
""" |
521 |
|
|
@brief switches to on reduced order |
522 |
|
|
""" |
523 |
|
|
self.setReducedOrderForSolutionOn() |
524 |
|
|
self.setReducedOrderForEquationOn() |
525 |
|
|
|
526 |
|
|
def setReducedOrderOff(self): |
527 |
|
|
""" |
528 |
|
|
@brief switches to full order |
529 |
|
|
""" |
530 |
|
|
self.setReducedOrderForSolutionOff() |
531 |
|
|
self.setReducedOrderForEquationOff() |
532 |
|
|
|
533 |
|
|
def setReducedOrderTo(self,flag=False): |
534 |
|
|
""" |
535 |
|
|
@brief sets order according to flag |
536 |
|
|
|
537 |
|
|
@param flag |
538 |
|
|
""" |
539 |
|
|
self.setReducedOrderForSolutionTo(flag) |
540 |
|
|
self.setReducedOrderForEquationTo(flag) |
541 |
|
|
|
542 |
|
|
|
543 |
|
|
#===== order reduction solution ========================== |
544 |
|
|
def setReducedOrderForSolutionOn(self): |
545 |
|
|
""" |
546 |
|
|
@brief switches to reduced order to interpolate solution |
547 |
|
|
""" |
548 |
|
|
new_fs=escript.ReducedSolution(self.getDomain()) |
549 |
|
|
if self.getFunctionSpaceForSolution()!=new_fs: |
550 |
|
|
if self.debug() : print "PDE Debug: Reduced order is used to interpolate solution." |
551 |
|
|
self.__column_function_space=new_fs |
552 |
|
|
self.__rebuildSystem(deep=True) |
553 |
|
|
|
554 |
|
|
def setReducedOrderForSolutionOff(self): |
555 |
|
|
""" |
556 |
|
|
@brief switches to full order to interpolate solution |
557 |
|
|
""" |
558 |
|
|
new_fs=escript.Solution(self.getDomain()) |
559 |
|
|
if self.getFunctionSpaceForSolution()!=new_fs: |
560 |
|
|
if self.debug() : print "PDE Debug: Full order is used to interpolate solution." |
561 |
|
|
self.__column_function_space=new_fs |
562 |
|
|
self.__rebuildSystem(deep=True) |
563 |
|
|
|
564 |
|
|
def setReducedOrderForSolutionTo(self,flag=False): |
565 |
|
|
""" |
566 |
|
|
@brief sets order for test functions according to flag |
567 |
|
|
|
568 |
|
|
@param flag |
569 |
|
|
""" |
570 |
|
|
if flag: |
571 |
|
|
self.setReducedOrderForSolutionOn() |
572 |
|
|
else: |
573 |
|
|
self.setReducedOrderForSolutionOff() |
574 |
|
|
|
575 |
|
|
#===== order reduction equation ========================== |
576 |
|
|
def setReducedOrderForEquationOn(self): |
577 |
|
|
""" |
578 |
|
|
@brief switches to reduced order for test functions |
579 |
|
|
""" |
580 |
|
|
new_fs=escript.ReducedSolution(self.getDomain()) |
581 |
|
|
if self.getFunctionSpaceForEquation()!=new_fs: |
582 |
|
|
if self.debug() : print "PDE Debug: Reduced order is used for test functions." |
583 |
|
|
self.__row_function_space=new_fs |
584 |
|
|
self.__rebuildSystem(deep=True) |
585 |
|
|
|
586 |
|
|
def setReducedOrderForEquationOff(self): |
587 |
|
|
""" |
588 |
|
|
@brief switches to full order for test functions |
589 |
|
|
""" |
590 |
|
|
new_fs=escript.Solution(self.getDomain()) |
591 |
|
|
if self.getFunctionSpaceForEquation()!=new_fs: |
592 |
|
|
if self.debug() : print "PDE Debug: Full order is used for test functions." |
593 |
|
|
self.__row_function_space=new_fs |
594 |
|
|
self.__rebuildSystem(deep=True) |
595 |
|
|
|
596 |
|
|
def setReducedOrderForEquationTo(self,flag=False): |
597 |
|
|
""" |
598 |
|
|
@brief sets order for test functions according to flag |
599 |
|
|
|
600 |
|
|
@param flag |
601 |
|
|
""" |
602 |
|
|
if flag: |
603 |
|
|
self.setReducedOrderForEquationOn() |
604 |
|
|
else: |
605 |
|
|
self.setReducedOrderForEquationOff() |
606 |
|
|
|
607 |
|
|
|
608 |
|
|
# ==== initialization ===================================================================== |
609 |
|
|
def __makeNewOperator(self): |
610 |
|
|
""" |
611 |
|
|
@brief |
612 |
|
|
""" |
613 |
|
|
return self.getDomain().newOperator( \ |
614 |
|
|
self.getNumEquations(), \ |
615 |
|
|
self.getFunctionSpaceForEquation(), \ |
616 |
|
|
self.getNumSolutions(), \ |
617 |
|
|
self.getFunctionSpaceForSolution(), \ |
618 |
|
|
self.__matrix_type) |
619 |
|
|
|
620 |
|
|
def __makeNewRightHandSide(self): |
621 |
|
|
""" |
622 |
|
|
@brief |
623 |
|
|
""" |
624 |
|
|
return escript.Data(0.,(self.getNumEquations(),),self.getFunctionSpaceForEquation(),True) |
625 |
|
|
|
626 |
|
|
def __makeNewSolution(self): |
627 |
|
|
""" |
628 |
|
|
@brief |
629 |
|
|
""" |
630 |
|
|
return escript.Data(0.,(self.getNumSolutions(),),self.getFunctionSpaceForSolution(),True) |
631 |
|
|
|
632 |
|
|
def __getFreshOperator(self): |
633 |
|
|
""" |
634 |
|
|
@brief |
635 |
|
|
""" |
636 |
|
|
if self.__operator.isEmpty(): |
637 |
|
|
self.__operator=self.__makeNewOperator() |
638 |
|
|
if self.debug() : print "PDE Debug: New operator allocated" |
639 |
|
|
else: |
640 |
|
|
self.__operator.setValue(0.) |
641 |
|
|
if self.debug() : print "PDE Debug: Operator reset to zero" |
642 |
|
|
return self.__operator |
643 |
|
|
|
644 |
|
|
def __getFreshRightHandSide(self): |
645 |
|
|
""" |
646 |
|
|
@brief |
647 |
|
|
""" |
648 |
|
|
if self.__righthandside.isEmpty(): |
649 |
|
|
self.__righthandside=self.__makeNewRightHandSide() |
650 |
|
|
if self.debug() : print "PDE Debug: New right hand side allocated" |
651 |
|
|
else: |
652 |
|
|
print "fix self.__righthandside*=0" |
653 |
|
|
self.__righthandside*=0. |
654 |
|
|
if self.debug() : print "PDE Debug: Right hand side reset to zero" |
655 |
|
|
return self.__righthandside |
656 |
|
|
|
657 |
|
|
# ==== rebuild switches ===================================================================== |
658 |
|
|
def __rebuildSolution(self,deep=False): |
659 |
|
|
""" |
660 |
|
|
@brief indicates the PDE has to be reolved if the solution is requested |
661 |
|
|
""" |
662 |
|
|
if self.__solution_isValid and self.debug() : print "PDE Debug: PDE has to be resolved." |
663 |
|
|
self.__solution_isValid=False |
664 |
|
|
if deep: self.__solution=escript.Data(deep) |
665 |
|
|
|
666 |
|
|
|
667 |
|
|
def __rebuildOperator(self,deep=False): |
668 |
|
|
""" |
669 |
|
|
@brief indicates the operator has to be rebuilt next time it is used |
670 |
|
|
""" |
671 |
|
|
if self.__operator_isValid and self.debug() : print "PDE Debug: Operator has to be rebuilt." |
672 |
|
|
self.__rebuildSolution(deep) |
673 |
|
|
self.__operator_isValid=False |
674 |
|
|
if deep: self.__operator=escript.Operator() |
675 |
|
|
|
676 |
|
|
def __rebuildRightHandSide(self,deep=False): |
677 |
|
|
""" |
678 |
|
|
@brief indicates the right hand side has to be rebuild next time it is used |
679 |
|
|
""" |
680 |
|
|
if self.__righthandside_isValid and self.debug() : print "PDE Debug: Right hand side has to be rebuilt." |
681 |
|
|
self.__rebuildSolution(deep) |
682 |
|
|
self.__righthandside_isValid=False |
683 |
|
|
if not self.__homogeneous_constraint: self.__rebuildOperator() |
684 |
|
|
if deep: self.__righthandside=escript.Data() |
685 |
|
|
|
686 |
|
|
def __rebuildSystem(self,deep=False): |
687 |
|
|
""" |
688 |
|
|
@brief annonced that all coefficient name has been changed |
689 |
|
|
""" |
690 |
|
|
self.__rebuildSolution(deep) |
691 |
|
|
self.__rebuildOperator(deep) |
692 |
|
|
self.__rebuildRightHandSide(deep) |
693 |
|
|
|
694 |
|
|
def __checkMatrixType(self): |
695 |
|
|
""" |
696 |
|
|
@brief reassess the matrix type and, if needed, initiates an operator rebuild |
697 |
|
|
""" |
698 |
|
|
new_matrix_type=self.getDomain().getSystemMatrixTypeId(self.getSolverMethod(),self.isSymmetric()) |
699 |
|
|
if not new_matrix_type==self.__matrix_type: |
700 |
|
|
if self.debug() : print "PDE Debug: Matrix type is now %d."%new_matrix_type |
701 |
|
|
self.__matrix_type=new_matrix_type |
702 |
|
|
self.__rebuildOperator(deep=True) |
703 |
|
|
|
704 |
|
|
#============ assembling ======================================================= |
705 |
|
|
def __copyConstraint(self,u): |
706 |
|
|
""" |
707 |
|
|
@brief copies the constrint condition into u |
708 |
|
|
""" |
709 |
|
|
q=self.getCoefficient("q") |
710 |
|
|
r=self.getCoefficient("r") |
711 |
|
|
if not q.isEmpty(): |
712 |
|
|
if r.isEmpty(): |
713 |
|
|
r2=escript.Data(0,u.getShape(),u.getFunctionSpace()) |
714 |
|
|
else: |
715 |
|
|
r2=escript.Data(r,u.getFunctionSpace()) |
716 |
|
|
u.copyWithMask(r2,escript.Data(q,u.getFunctionSpace())) |
717 |
|
|
|
718 |
|
|
def __applyConstraint(self,rhs_update=True): |
719 |
|
|
""" |
720 |
|
|
@brief applies the constraints defined by q and r to the system |
721 |
|
|
""" |
722 |
|
|
q=self.getCoefficient("q") |
723 |
|
|
r=self.getCoefficient("r") |
724 |
|
|
if not q.isEmpty() and not self.__operator.isEmpty(): |
725 |
|
|
# q is the row and column mask to indicate where constraints are set: |
726 |
|
|
row_q=escript.Data(q,self.getFunctionSpaceForEquation()) |
727 |
|
|
col_q=escript.Data(q,self.getFunctionSpaceForSolution()) |
728 |
|
|
u=self.__makeNewSolution() |
729 |
|
|
if r.isEmpty(): |
730 |
|
|
r_s=self.__makeNewSolution() |
731 |
|
|
else: |
732 |
|
|
r_s=escript.Data(r,self.getFunctionSpaceForSolution()) |
733 |
|
|
u.copyWithMask(r_s,col_q) |
734 |
|
|
if not self.__righthandside.isEmpty() and rhs_update: self.__righthandside-=self.__operator*u |
735 |
|
|
self.__operator.nullifyRowsAndCols(row_q,col_q,1.) |
736 |
|
|
|
737 |
|
|
def getOperator(self): |
738 |
|
|
""" |
739 |
|
|
@brief returns the operator of the PDE |
740 |
|
|
""" |
741 |
|
|
if not self.__operator_isValid: |
742 |
|
|
# some Constraints are applying for a lumpled stifness matrix: |
743 |
|
|
if self.isUsingLumping(): |
744 |
|
|
if self.getFunctionSpaceForEquation()==self.getFunctionSpaceForSolution(): |
745 |
|
|
raise TypeError,"Lumped matrix requires same order for equations and unknowns" |
746 |
|
|
if not self.getCoefficient("A").isEmpty(): |
747 |
|
|
raise Warning,"Lumped matrix does not allow coefficient A" |
748 |
|
|
if not self.getCoefficient("B").isEmpty(): |
749 |
|
|
raise Warning,"Lumped matrix does not allow coefficient B" |
750 |
|
|
if not self.getCoefficient("C").isEmpty(): |
751 |
|
|
raise Warning,"Lumped matrix does not allow coefficient C" |
752 |
|
|
if not self.getCoefficient("D").isEmpty(): |
753 |
|
|
raise Warning,"Lumped matrix does not allow coefficient D" |
754 |
|
|
if self.debug() : print "PDE Debug: New lumped operator is built." |
755 |
|
|
mat=self.__makeNewOperator(self) |
756 |
|
|
else: |
757 |
|
|
if self.debug() : print "PDE Debug: New operator is built." |
758 |
|
|
mat=self.__getFreshOperator() |
759 |
|
|
|
760 |
|
|
self.getDomain().addPDEToSystem(mat,escript.Data(), \ |
761 |
|
|
self.getCoefficient("A"), \ |
762 |
|
|
self.getCoefficient("B"), \ |
763 |
|
|
self.getCoefficient("C"), \ |
764 |
|
|
self.getCoefficient("D"), \ |
765 |
|
|
escript.Data(), \ |
766 |
|
|
escript.Data(), \ |
767 |
|
|
self.getCoefficient("d"), \ |
768 |
|
|
escript.Data(),\ |
769 |
|
|
self.getCoefficient("d_contact"), \ |
770 |
|
|
escript.Data()) |
771 |
|
|
if self.isUsingLumping(): |
772 |
|
|
self.__operator=mat*escript.Data(1,(self.getNumSolutions(),),self.getFunctionSpaceOfSolution(),True) |
773 |
|
|
else: |
774 |
|
|
self.__applyConstraint(rhs_update=False) |
775 |
|
|
self.__operator_isValid=True |
776 |
|
|
return self.__operator |
777 |
|
|
|
778 |
|
|
def getRightHandSide(self,ignoreConstraint=False): |
779 |
|
|
""" |
780 |
|
|
@brief returns the right hand side of the PDE |
781 |
|
|
|
782 |
|
|
@param ignoreConstraint |
783 |
|
|
""" |
784 |
|
|
if not self.__righthandside_isValid: |
785 |
|
|
if self.debug() : print "PDE Debug: New right hand side is built." |
786 |
|
|
self.getDomain().addPDEToRHS(self.__getFreshRightHandSide(), \ |
787 |
|
|
self.getCoefficient("X"), \ |
788 |
|
|
self.getCoefficient("Y"),\ |
789 |
|
|
self.getCoefficient("y"),\ |
790 |
|
|
self.getCoefficient("y_contact")) |
791 |
|
|
self.__righthandside_isValid=True |
792 |
|
|
if ignoreConstraint: self.__copyConstraint(self.__righthandside) |
793 |
|
|
return self.__righthandside |
794 |
|
|
|
795 |
|
|
def getSystem(self): |
796 |
|
|
""" |
797 |
|
|
@brief |
798 |
|
|
""" |
799 |
|
|
if not self.__operator_isValid and not self.__righthandside_isValid: |
800 |
|
|
if self.debug() : print "PDE Debug: New PDE is built." |
801 |
|
|
if self.isUsingLumping(): |
802 |
|
|
self.getRightHandSide(ignoreConstraint=True) |
803 |
|
|
self.getOperator() |
804 |
|
|
else: |
805 |
|
|
self.getDomain().addPDEToSystem(self.__getFreshOperator(),self.__getFreshRightHandSide(), \ |
806 |
|
|
self.getCoefficient("A"), \ |
807 |
|
|
self.getCoefficient("B"), \ |
808 |
|
|
self.getCoefficient("C"), \ |
809 |
|
|
self.getCoefficient("D"), \ |
810 |
|
|
self.getCoefficient("X"), \ |
811 |
|
|
self.getCoefficient("Y"), \ |
812 |
|
|
self.getCoefficient("d"), \ |
813 |
|
|
self.getCoefficient("y"), \ |
814 |
|
|
self.getCoefficient("d_contact"), \ |
815 |
|
|
self.getCoefficient("y_contact")) |
816 |
|
|
self.__operator_isValid=True |
817 |
|
|
self.__righthandside_isValid=True |
818 |
|
|
self.__applyConstraint() |
819 |
|
|
self.__copyConstraint(self.__righthandside) |
820 |
|
|
elif not self.__operator_isValid: |
821 |
|
|
self.getOperator() |
822 |
|
|
elif not self.__righthandside_isValid: |
823 |
|
|
self.getRightHandSide() |
824 |
|
|
return (self.__operator,self.__righthandside) |
825 |
|
|
|
826 |
|
|
def solve(self,**options): |
827 |
|
|
""" |
828 |
|
|
@brief solve the PDE |
829 |
|
|
|
830 |
|
|
@param options |
831 |
|
|
""" |
832 |
|
|
mat,f=self.getSystem() |
833 |
|
|
if self.isUsingLumping(): |
834 |
|
|
out=f/mat |
835 |
|
|
self.__copyConstraint(out) |
836 |
|
|
else: |
837 |
|
|
options[util.TOLERANCE_KEY]=self.getTolerance() |
838 |
|
|
options[util.METHOD_KEY]=self.getSolverMethod() |
839 |
|
|
options[util.SYMMETRY_KEY]=self.isSymmetric() |
840 |
|
|
if self.debug() : print "PDE Debug: solver options: ",options |
841 |
|
|
out=mat.solve(f,options) |
842 |
|
|
return out |
843 |
|
|
|
844 |
|
|
def getSolution(self,**options): |
845 |
|
|
""" |
846 |
|
|
@brief returns the solution of the PDE |
847 |
|
|
|
848 |
|
|
@param options |
849 |
|
|
""" |
850 |
|
|
if not self.__solution_isValid: |
851 |
|
|
if self.debug() : print "PDE Debug: PDE is resolved." |
852 |
|
|
self.__solution=self.solve(**options) |
853 |
|
|
self.__solution_isValid=True |
854 |
|
|
return self.__solution |
855 |
|
|
#============ some serivice functions ===================================================== |
856 |
|
|
def getDomain(self): |
857 |
|
|
""" |
858 |
|
|
@brief returns the domain of the PDE |
859 |
|
|
""" |
860 |
|
|
return self.__domain |
861 |
|
|
|
862 |
jgs |
104 |
def getDim(self): |
863 |
|
|
""" |
864 |
|
|
@brief returns the spatial dimension of the PDE |
865 |
|
|
""" |
866 |
|
|
return self.getDomain().getDim() |
867 |
|
|
|
868 |
jgs |
102 |
def getNumEquations(self): |
869 |
|
|
""" |
870 |
|
|
@brief returns the number of equations |
871 |
|
|
""" |
872 |
|
|
if self.__numEquations>0: |
873 |
|
|
return self.__numEquations |
874 |
|
|
else: |
875 |
|
|
raise ValueError,"Number of equations is undefined. Please specify argument numEquations." |
876 |
|
|
|
877 |
|
|
def getNumSolutions(self): |
878 |
|
|
""" |
879 |
|
|
@brief returns the number of unknowns |
880 |
|
|
""" |
881 |
|
|
if self.__numSolutions>0: |
882 |
|
|
return self.__numSolutions |
883 |
|
|
else: |
884 |
|
|
raise ValueError,"Number of solution is undefined. Please specify argument numSolutions." |
885 |
|
|
|
886 |
|
|
|
887 |
|
|
def checkSymmetry(self): |
888 |
|
|
""" |
889 |
|
|
@brief returns if the Operator is symmetric. This is a very expensive operation!!! The symmetry flag is not altered. |
890 |
|
|
""" |
891 |
|
|
raise SystemError,"checkSymmetry is not implemented yet" |
892 |
|
|
|
893 |
|
|
return None |
894 |
|
|
|
895 |
|
|
def getFlux(self,u): |
896 |
|
|
""" |
897 |
|
|
@brief returns the flux J_ij for a given u |
898 |
|
|
|
899 |
|
|
J_ij=A_{ijkl}u_{k,l}+B_{ijk}u_k-X_{ij} |
900 |
|
|
|
901 |
|
|
@param u argument of the operator |
902 |
|
|
|
903 |
|
|
""" |
904 |
|
|
raise SystemError,"getFlux is not implemented yet" |
905 |
|
|
return None |
906 |
|
|
|
907 |
|
|
def applyOperator(self,u): |
908 |
|
|
""" |
909 |
|
|
@brief applies the operator of the PDE to a given solution u in weak from |
910 |
|
|
|
911 |
|
|
@param u argument of the operator |
912 |
|
|
|
913 |
|
|
""" |
914 |
|
|
return self.getOperator()*escript.Data(u,self.getFunctionSpaceForSolution()) |
915 |
|
|
|
916 |
|
|
def getResidual(self,u): |
917 |
|
|
""" |
918 |
|
|
@brief return the residual of u in the weak from |
919 |
|
|
|
920 |
|
|
@param u |
921 |
|
|
""" |
922 |
|
|
return self.applyOperator(u)-self.getRightHandSide() |
923 |
|
|
|
924 |
|
|
class Poisson(LinearPDE): |
925 |
|
|
""" |
926 |
|
|
@brief Class to define a Poisson equstion problem: |
927 |
|
|
|
928 |
|
|
class to define a linear PDE of the form |
929 |
|
|
|
930 |
|
|
-u_{,jj} = f |
931 |
|
|
|
932 |
|
|
with boundary conditons: |
933 |
|
|
|
934 |
|
|
n_j*u_{,j} = 0 |
935 |
|
|
|
936 |
|
|
and constraints: |
937 |
|
|
|
938 |
|
|
u=0 where q>0 |
939 |
|
|
|
940 |
|
|
""" |
941 |
|
|
|
942 |
|
|
def __init__(self,domain=None,f=escript.Data(),q=escript.Data()): |
943 |
|
|
LinearPDE.__init__(self,domain=identifyDomain(domain,{"f":f, "q":q})) |
944 |
jgs |
104 |
self._setValue(A=numarray.identity(self.getDomain().getDim())) |
945 |
jgs |
102 |
self.setSymmetryOn() |
946 |
|
|
self.setValue(f,q) |
947 |
|
|
|
948 |
|
|
def setValue(self,f=escript.Data(),q=escript.Data()): |
949 |
jgs |
104 |
self._setValue(Y=f,q=q) |
950 |
jgs |
102 |
|
951 |
|
|
|
952 |
|
|
# $Log$ |
953 |
jgs |
104 |
# Revision 1.3 2004/12/17 07:43:10 jgs |
954 |
jgs |
102 |
# *** empty log message *** |
955 |
|
|
# |
956 |
jgs |
104 |
# Revision 1.1.2.3 2004/12/16 00:12:34 gross |
957 |
|
|
# __init__ of LinearPDE does not accept any coefficients anymore |
958 |
|
|
# |
959 |
jgs |
102 |
# Revision 1.1.2.2 2004/12/14 03:55:01 jgs |
960 |
|
|
# *** empty log message *** |
961 |
|
|
# |
962 |
|
|
# Revision 1.1.2.1 2004/12/12 22:53:47 gross |
963 |
|
|
# linearPDE has been renamed LinearPDE |
964 |
|
|
# |
965 |
|
|
# Revision 1.1.1.1.2.7 2004/12/07 10:13:08 gross |
966 |
|
|
# GMRES added |
967 |
|
|
# |
968 |
|
|
# Revision 1.1.1.1.2.6 2004/12/07 03:19:50 gross |
969 |
|
|
# options for GMRES and PRES20 added |
970 |
|
|
# |
971 |
|
|
# Revision 1.1.1.1.2.5 2004/12/01 06:25:15 gross |
972 |
|
|
# some small changes |
973 |
|
|
# |
974 |
|
|
# Revision 1.1.1.1.2.4 2004/11/24 01:50:21 gross |
975 |
|
|
# Finley solves 4M unknowns now |
976 |
|
|
# |
977 |
|
|
# Revision 1.1.1.1.2.3 2004/11/15 06:05:26 gross |
978 |
|
|
# poisson solver added |
979 |
|
|
# |
980 |
|
|
# Revision 1.1.1.1.2.2 2004/11/12 06:58:15 gross |
981 |
|
|
# 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 |
982 |
|
|
# |
983 |
|
|
# Revision 1.1.1.1.2.1 2004/10/28 22:59:22 gross |
984 |
|
|
# finley's RecTest.py is running now: problem in SystemMatrixAdapater fixed |
985 |
|
|
# |
986 |
|
|
# Revision 1.1.1.1 2004/10/26 06:53:56 jgs |
987 |
|
|
# initial import of project esys2 |
988 |
|
|
# |
989 |
|
|
# Revision 1.3.2.3 2004/10/26 06:43:48 jgs |
990 |
|
|
# committing Lutz's and Paul's changes to brach jgs |
991 |
|
|
# |
992 |
|
|
# Revision 1.3.4.1 2004/10/20 05:32:51 cochrane |
993 |
|
|
# Added incomplete Doxygen comments to files, or merely put the docstrings that already exist into Doxygen form. |
994 |
|
|
# |
995 |
|
|
# Revision 1.3 2004/09/23 00:53:23 jgs |
996 |
|
|
# minor fixes |
997 |
|
|
# |
998 |
|
|
# Revision 1.1 2004/08/28 12:58:06 gross |
999 |
|
|
# SimpleSolve is not running yet: problem with == of functionsspace |
1000 |
|
|
# |
1001 |
|
|
# |