# Diff of /branches/symbolic_from_3470/escript/py_src/linearPDEs.py

revision 2469 by jfenwick, Wed Jun 3 03:29:07 2009 UTC revision 2470 by gross, Thu Jun 11 08:32:32 2009 UTC
# Line 44  import numpy Line 44  import numpy
44  __author__="Lutz Gross, l.gross@uq.edu.au"  __author__="Lutz Gross, l.gross@uq.edu.au"
45
46
47    class SolverOptions(object):
48        """
49        this class defines the solver options for a linear or non-linear solver.
50
51        The option also supports the handling of diagnostic informations.
52
53        Typical usage is
54
55        opts=SolverOptions()
56        print opts
57        opts.resetDiagnostics()
58        u=solver(opts)
59        print "number of iteration steps: =",opts.getDiagnostics("num_iter")
60
61
62        @cvar DEFAULT: The default method used to solve the system of linear equations
63        @cvar DIRECT: The direct solver based on LDU factorization
64        @cvar CHOLEVSKY: The direct solver based on LDLt factorization (can only be applied for symmetric PDEs)
65        @cvar PCG: The preconditioned conjugate gradient method (can only be applied for symmetric PDEs)
66        @cvar CR: The conjugate residual method
67        @cvar CGS: The conjugate gradient square method
68        @cvar BICGSTAB: The stabilized Bi-Conjugate Gradient method
69        @cvar TFQMR: Transport Free Quasi Minimal Residual method
70        @cvar MINRES: Minimum residual method
71        @cvar SSOR: The symmetric over-relaxation method
72        @cvar ILU0: The incomplete LU factorization preconditioner with no fill-in
73        @cvar ILUT: The incomplete LU factorization preconditioner with fill-in
74        @cvar JACOBI: The Jacobi preconditioner
75        @cvar GMRES: The Gram-Schmidt minimum residual method
76        @cvar PRES20: Special GMRES with restart after 20 steps and truncation after 5 residuals
77        @cvar LUMPING: Matrix lumping
78        @cvar NO_REORDERING: No matrix reordering allowed
79        @cvar MINIMUM_FILL_IN: Reorder matrix to reduce fill-in during factorization
80        @cvar NESTED_DISSECTION: Reorder matrix to improve load balancing during factorization
81        @cvar PASO: PASO solver package
82        @cvar SCSL: SGI SCSL solver library
83        @cvar MKL: Intel's MKL solver library
84        @cvar UMFPACK: The UMFPACK library
85        @cvar TRILINOS: The TRILINOS parallel solver class library from Sandia National Labs
86        @cvar ITERATIVE: The default iterative solver
87        @cvar AMG: Algebraic Multi Grid
88        @cvar REC_ILU: recursive ILU0
89        @cvar RILU: relaxed ILU0
90        @cvar GAUSS_SEIDEL: Gauss-Seidel solver
91        @cvar DEFAULT_REORDERING: the reordering method recommended by the solver
92        @cvar SUPER_LU: the Super_LU solver package
93        @cvar PASTIX: the Pastix direct solver_package
94        @cvar YAIR_SHAPIRA_COARSENING: AMG coarsening method by Yair-Shapira
95        @cvar RUGE_STUEBEN_COARSENING: AMG coarsening method by Ruge and Stueben
96        @cvar AGGREGATION_COARSENING: AMG coarsening using (symmetric) aggregation
97        @cvar NO_PRECONDITIONER: no preconditioner is applied.
98        """
99        DEFAULT= 0
100        DIRECT= 1
101        CHOLEVSKY= 2
102        PCG= 3
103        CR= 4
104        CGS= 5
105        BICGSTAB= 6
106        SSOR= 7
107        ILU0= 8
108        ILUT= 9
109        JACOBI= 10
110        GMRES= 11
111        PRES20= 12
112        LUMPING= 13
113        NO_REORDERING= 17
114        MINIMUM_FILL_IN= 18
115        NESTED_DISSECTION= 19
116        MKL= 15
117        UMFPACK= 16
118        ITERATIVE= 20
119        PASO= 21
120        AMG= 22
121        REC_ILU = 23
122        TRILINOS = 24
123        NONLINEAR_GMRES = 25
124        TFQMR = 26
125        MINRES = 27
126        GAUSS_SEIDEL=28
127        RILU=29
128        DEFAULT_REORDERING=30
129        SUPER_LU=31
130        PASTIX=32
131        YAIR_SHAPIRA_COARSENING=33
132        RUGE_STUEBEN_COARSENING=34
133        AGGREGATION_COARSENING=35
134        NO_PRECONDITIONER=36
135        def __init__(self):
136            self.setLevelMax()
137            self.setCoarseningThreshold()
138            self.setNumSweeps()
139            self.setNumPreSweeps()
140            self.setNumPostSweeps()
141            self.setTolerance()
142            self.setAbsoluteTolerance()
143            self.setInnerTolerance()
144            self.setDropTolerance()
145            self.setDropStorage()
146            self.setIterMax()
147            self.setInnerIterMax()
148            self.setTruncation()
149            self.setRestart()
150            self.setSymmetry()
151            self.setVerbosity()
153            self.setAcceptanceConvergenceFailure()
154            self.setReordering()
155            self.setPackage()
156            self.setSolverMethod()
157            self.setPreconditioner()
158            self.setCoarsening()
159            self.setRelaxationFactor()
160            self.resetDiagnostics(all=True)
161
162        def __str__(self):
163            return self.getSummary()
164        def getSummary(self):
165            """
166            Returns a string reporting the current settings
167            """
168            out="Solver Package: %s"%(self.getName(self.getPackage()))
169            out+="\nVerbosity = %s"%self.isVerbose()
170            out+="\nAccept failed convergence = %s"%self.acceptConvergenceFailure()
171            out+="\nRelative tolerance = %e"%self.getTolerance()
172            out+="\nAbsolute tolerance = %e"%self.getAbsoluteTolerance()
173            out+="\nSymmetric problem = %s"%self.isSymmetric()
174            out+="\nMaximum number of iteration steps = %s"%self.getIterMax()
175            if self.getPackage() == self.PASO:
176                out+="\nSolver method = %s"%self.getName(self.getSolverMethod())
177                if self.getSolverMethod() == self.GMRES:
178                    out+="\nTruncation  = %s"%self.getTruncation()
179                    out+="\nRestart  = %s"%self.getRestart()
180                if self.getSolverMethod() == self.AMG:
181                    out+="\nNumber of pre / post sweeps = %s / %s, %s"%(self.getNumPreSweeps(), self.getNumPostSweeps(), self.getNumSweeps())
182                    out+="\nMaximum number of levels = %s"%self.LevelMax()
183                    out+="\nCoarsening threshold = %e"%self.getCoarseningThreshold()
184                    out+="\Coarsening method = %s"%self.getName(self.getCoarsening())
185                out+="\nPreconditioner = %s"%self.getName(self.getPreconditioner())
186                if self.getPreconditioner() == self.AMG:
187                    out+="\nMaximum number of levels = %s"%self.LevelMax()
188                    out+="\nCoarsening method = %s"%self.getName(self.getCoarsening())
189                    out+="\nCoarsening threshold = %e"%self.getCoarseningThreshold()
190                    out+="\nNumber of pre / post sweeps = %s / %s, %s"%(self.getNumPreSweeps(), self.getNumPostSweeps(), self.getNumSweeps())
191                if self.getPreconditioner() == self.GAUSS_SEIDEL:
192                    out+="\nNumber of sweeps = %s"%self.getNumSweeps()
193                if self.getPreconditioner() == self.ILUT:
194                    out+="\nDrop tolerance = %e"%self.getDropTolerance()
195                    out+="\nStorage increase = %e"%self.getDropStorage()
196                if self.getPreconditioner() == self.RILU:
197                    out+="\nRelaxation factor = %e"%self.getRelaxationFactor()
198            return out
199
200        def getName(self,key):
201            """
202            returns the name of a given key
203
204            @param key: a valid key
205            """
206            if key == self.DEFAULT: return "DEFAULT"
207            if key == self.DIRECT: return "DIRECT"
208            if key == self.CHOLEVSKY: return "CHOLEVSKY"
209            if key == self.PCG: return "PCG"
210            if key == self.CR: return "CR"
211            if key == self.CGS: return "CGS"
212            if key == self.BICGSTAB: return "BICGSTAB"
213            if key == self.SSOR: return "SSOR"
214            if key == self.ILU0: return "ILU0:"
215            if key == self.ILUT: return "ILUT"
216            if key == self.JACOBI: return "JACOBI"
217            if key == self.GMRES: return "GMRES"
218            if key == self.PRES20: return "PRES20"
219            if key == self.LUMPING: return "LUMPING"
220            if key == self.NO_REORDERING: return "NO_REORDERING"
221            if key == self.MINIMUM_FILL_IN: return "MINIMUM_FILL_IN"
222            if key == self.NESTED_DISSECTION: return "NESTED_DISSECTION"
223            if key == self.MKL: return "MKL"
224            if key == self.UMFPACK: return "UMFPACK"
225            if key == self.ITERATIVE: return "ITERATIVE"
226            if key == self.PASO: return "PASO"
227            if key == self.AMG: return "AMG"
228            if key == self.REC_ILU: return "REC_ILU"
229            if key == self.TRILINOS: return "TRILINOS"
230            if key == self.NONLINEAR_GMRES: return "NONLINEAR_GMRES"
231            if key == self.TFQMR: return "TFQMR"
232            if key == self.MINRES: return "MINRES"
233            if key == self.GAUSS_SEIDEL: return "GAUSS_SEIDEL"
234            if key == self.RILU: return "RILU"
235            if key == self.DEFAULT_REORDERING: return "DEFAULT_REORDERING"
236            if key == self.SUPER_LU: return "SUPER_LU"
237            if key == self.PASTIX: return "PASTIX"
238            if key == self.YAIR_SHAPIRA_COARSENING: return "YAIR_SHAPIRA_COARSENING"
239            if key == self.RUGE_STUEBEN_COARSENING: return "RUGE_STUEBEN_COARSENING"
240            if key == self.AGGREGATION_COARSENING: return "AGGREGATION_COARSENING"
241            if key == self.NO_PRECONDITIONER: return "NO_PRECONDITIONER"
242
243        def resetDiagnostics(self,all=False):
244            """
245            resets the diagnostics
246
247            @param all: if C{all} is C{True} all diagnostics including accumulative counters are reset.
248            @type all: C{bool}
249            """
250            self.__num_iter=None
251            self.__num_level=None
252            self.__num_inner_iter=None
253            self.__time=None
254            self.__set_up_time=None
255            self.__residual_norm=None
256            self.__converged=None
257            if all:
258                self.__cum_num_inner_iter=0
259                self.__cum_num_iter=0
260                self.__cum_time=0
261                self.__cum_set_up_time=0
262
263        def _updateDiagnostics(self, name, value):
264            """
266
267            @param name: name of  diagnostic information
268            @type name: C{str} in the list "num_iter", "num_level", "num_inner_iter", "time", "set_up_time", "residual_norm", "converged".
269            @param vale: new value of the diagnostic information
270            @note: this function is used by a solver to report diagnostics informations.
271            """
272            if name == "num_iter":
273                self.__num_iter=int(value)
274                self.__cum_num_iter+=self.__num_iter
275            if name == "num_level":
276                self.__num_iter=int(value)
277            if name == "num_inner_iter":
278                self.__num_inner_iter=int(value)
279                self.__cum_num_inner_iter+=self.__num_inner_iter
280            if name == "time":
281                self.__time=float(value)
282                self.__cum_time+=self.__time
283            if name == "set_up_time":
284                self.__set_up_time=float(value)
285                self.__cum_set_up_time+=self.__set_up_time
286            if name == "residual_norm":
287                self.__residual_norm=float(value)
288            if name == "converged":
289                self.__converged = (value == True)
290        def getDiagnostics(self, name):
291            """
292            Returns the diagnostic information C{name}
293
294            @param name: name of diagnostic information where
295            - "num_iter": the number of iteration steps
296            - "cum_num_iter": the cumulative number of iteration steps
297            - "num_level": the number of level in multi level solver
298            - "num_inner_iter": the number of inner iteration steps
299            - "cum_num_inner_iter": the cumulative number of inner iteration steps
300            - "time": execution time
301            - "cum_time": cumulative execution time
302            - "set_up_time": time to set up of the solver, typically this includes factorization and reordering
303            - "cum_set_up_time": cumulative time to set up of the solver
304            - "residual_norm": norm of the final residual
305            - "converged": return self.__converged
306            @type name: C{str} in the list "num_iter", "num_level", "num_inner_iter", "time", "set_up_time", "residual_norm", "converged".
307            @return: requested value. C{None} is returned if the value is undefined.
308            @note: If the solver has thrown an exception diagnostic values have an undefined status.
309            """
310            if name == "num_iter": return self.__num_iter
311            elif name == "cum_num_iter": return self.__cum_num_iter
312            elif name == "num_level": return self.__num_level
313            elif name == "num_inner_iter": return self.__num_inner_iter
314            elif name == "cum_num_inner_iter": return self.__cum_num_inner_iter
315            elif name == "time": return self.__time
316            elif name == "cum_time": return self.__cum_time
317            elif name == "set_up_time": return self.__set_up_time
318            elif name == "cum_set_up_time": return self.__cum_set_up_time
319            elif name == "residual_norm": return self.__residual_norm
320            elif name == "converged": return self.__converged
321            else:
322                raise ValueError,"unknown diagnostic item %s"%name
323        def hasConverged(self):
324            """
325            Returns C{True} if the last solver call has been finalized successfully.
326            @note: if an exception has been thrown by the solver the status of this flag is undefined.
327            """
328            return self.getDiagnostics("converged")
329        def setCoarsening(self,method=0):
330            """
331            Sets the key of the coarsening method to be applied in AMG.
332
333            @param method: selects the coarsening method .
334            @type method: in L{SolverOptions.DEFAULT}, L{SolverOptions.YAIR_SHAPIRA_COARSENING},
335            L{SolverOptions.RUGE_STUEBEN_COARSENING}, L{SolverOptions.AGGREGATION_COARSENING}
336            """
337            if not method in [self.DEFAULT, self.YAIR_SHAPIRA_COARSENING, self.RUGE_STUEBEN_COARSENING, self.AGGREGATION_COARSENING]:
338                 raise ValueError,"unknown coarsening method %s"%method
339            self.__coarsening=method
340        def getCoarsening(self):
341            """
342            Returns the key of the coarsening algorithm to be applied AMG.
343
344            @rtype: in the list L{SolverOptions.DEFAULT}, L{SolverOptions.YAIR_SHAPIRA_COARSENING},
345            L{SolverOptions.RUGE_STUEBEN_COARSENING}, L{SolverOptions.AGGREGATION_COARSENING}
346            """
347            return self.__coarsening
348        def setPreconditioner(self, preconditioner=10):
349            """
350            Sets the preconditioner to be used.
351
352            @param preconditioner: key of the preconditioner to be used.
353            @type preconditioner: in L{SolverOptions.SSOR}, L{SolverOptions.ILU0}, L{SolverOptions.ILUT}, L{SolverOptions.JACOBI},
354                                        L{SolverOptions.AMG}, L{SolverOptions.REC_ILU}, L{SolverOptions.GAUSS_SEIDEL}, L{SolverOptions.RILU},
355                                        L{SolverOptions.NO_PRECONDITIONER}
356            @note: Not all packages support all preconditioner. It can be assumed that a package makes a reasonable choice if it encounters
357            an unknown preconditioner.
358            """
359            if not preconditioner in [ SolverOptions.SSOR, SolverOptions.ILU0, SolverOptions.ILUT, SolverOptions.JACOBI,
360                                        SolverOptions.AMG, SolverOptions.REC_ILU, SolverOptions.GAUSS_SEIDEL, SolverOptions.RILU,
361                                        SolverOptions.NO_PRECONDITIONER] :
362                 raise ValueError,"unknown preconditioner %s"%preconditioner
363            self.__preconditioner=preconditioner
364        def getPreconditioner(self):
365            """
366            Returns key of the preconditioner to be used.
367
368            @rtype: in the list L{SolverOptions.SSOR}, L{SolverOptions.ILU0}, L{SolverOptions.ILUT}, L{SolverOptions.JACOBI},
369                                        L{SolverOptions.AMG}, L{SolverOptions.REC_ILU}, L{SolverOptions.GAUSS_SEIDEL}, L{SolverOptions.RILU},
370                                        L{SolverOptions.NO_PRECONDITIONER}
371            """
372            return self.__preconditioner
373        def setSolverMethod(self, method=0):
374            """
375            Sets the solver method to be used. Use C{method}=C{SolverOptions.DIRECT} to indicate that a direct rather than an iterative
376            solver should be used and Use C{method}=C{SolverOptions.ITERATIVE} to indicate that an iterative rather than a direct
377            solver should be used.
378
379            @param method: key of the solver method to be used.
380            @type method: in L{SolverOptions.DEFAULT}, L{SolverOptions.DIRECT}, L{SolverOptions.CHOLEVSKY}, L{SolverOptions.PCG},
381                            L{SolverOptions.CR}, L{SolverOptions.CGS}, L{SolverOptions.BICGSTAB}, L{SolverOptions.SSOR},
382                            L{SolverOptions.GMRES}, L{SolverOptions.PRES20}, L{SolverOptions.LUMPING}, L{SolverOptions.ITERATIVE},
383                            L{SolverOptions.AMG}, L{SolverOptions.NONLINEAR_GMRES}, L{SolverOptions.TFQMR}, L{SolverOptions.MINRES},
384                            L{SolverOptions.GAUSS_SEIDEL}
385            @note: Not all packages support all solvers. It can be assumed that a package makes a reasonable choice if it encounters
386            an unknown solver method.
387            """
388            if not method in [ SolverOptions.DEFAULT, SolverOptions.DIRECT, SolverOptions.CHOLEVSKY, SolverOptions.PCG,
389                               SolverOptions.CR, SolverOptions.CGS, SolverOptions.BICGSTAB, SolverOptions.SSOR,
390                               SolverOptions.GMRES, SolverOptions.PRES20, SolverOptions.LUMPING, SolverOptions.ITERATIVE, SolverOptions.AMG,
391                               SolverOptions.NONLINEAR_GMRES, SolverOptions.TFQMR, SolverOptions.MINRES, SolverOptions.GAUSS_SEIDEL]:
392                 raise ValueError,"unknown solver method %s"%method
393            self.__method=method
394        def getSolverMethod(self):
395            """
396            Returns key of the solver method to be used.
397
398            @rtype: in the list L{SolverOptions.DEFAULT}, L{SolverOptions.DIRECT}, L{SolverOptions.CHOLEVSKY}, L{SolverOptions.PCG},
399                            L{SolverOptions.CR}, L{SolverOptions.CGS}, L{SolverOptions.BICGSTAB}, L{SolverOptions.SSOR},
400                            L{SolverOptions.GMRES}, L{SolverOptions.PRES20}, L{SolverOptions.LUMPING}, L{SolverOptions.ITERATIVE},
401                            L{SolverOptions.AMG}, L{SolverOptions.NONLINEAR_GMRES}, L{SolverOptions.TFQMR}, L{SolverOptions.MINRES},
402                            L{SolverOptions.GAUSS_SEIDEL}
403            """
404            return self.__method
405
406        def setPackage(self, package=0):
407            """
408            Sets the solver package to be used as a solver.
409
410            @param package: key of the solver package to be used.
411            @type package: in L{SolverOptions.DEFAULT}, L{SolverOptions.PASO}, L{SolverOptions.SUPER_LU}, L{SolverOptions.PASTIX}, L{SolverOptions.MKL}, L{SolverOptions.UMFPACK}, L{SolverOptions.TRILINOS}
412            @note: Not all packages are support on all implementation. An exception may be thrown on some platforms if a particular is requested.
413            """
414            if not package in [SolverOptions.DEFAULT, SolverOptions.PASO, SolverOptions.SUPER_LU, SolverOptions.PASTIX, SolverOptions.MKL, SolverOptions.UMFPACK, SolverOptions.TRILINOS]:
415                 raise ValueError,"unknown solver package %s"%package
416            self.__package=package
417        def getPackage(self):
418            """
419            Returns the solver package key
420
421            @rtype: in the list L{SolverOptions.DEFAULT}, L{SolverOptions.PASO}, L{SolverOptions.SUPER_LU}, L{SolverOptions.PASTIX}, L{SolverOptions.MKL}, L{SolverOptions.UMFPACK}, L{SolverOptions.TRILINOS}
422            """
423            return self.__package
424        def setReordering(self,ordering=30):
425            """
426            Sets the key of the reordering method to be applied if supported by the solver. Some direct solvers support reordering
427            to optimize compute time and storage use during elimination.
428
429            @param ordering: selects the reordering strategy.
430            @type ordering: in L{SolverOptions.NO_REORDERING}, L{SolverOptions.NO_REORDERING},
431            L{SolverOptions.NO_REORDERING}, L{SolverOptions.DEFAULT_REORDERING}
432            """
433            if not ordering in [self.NO_REORDERING, self.MINIMUM_FILL_IN, self.NESTED_DISSECTION, self.DEFAULT_REORDERING]:
434                 raise ValueError,"unknown reordering strategy %s"%ordering
435            self.__reordering=ordering
436        def getReordering(self):
437            """
438            Returns the key of the reordering method to be applied if supported by the solver.
439
440            @rtype: in the list L{SolverOptions.NO_REORDERING}, L{SolverOptions.NO_REORDERING},
441            L{SolverOptions.NO_REORDERING}, L{SolverOptions.DEFAULT_REORDERING}
442            """
443            return self.__reordering
444        def setRestart(self,restart=None):
445            """
446            Sets the number of iterations steps after which GMRES is performing a restart.
447
448            @param restart: number of iteration steps after which to perform a restart. If equal to C{None} no
449                            restart is performed.
450            @type restart: C{int} or C{None}
451            """
452            if restart == None:
453                self.__restart=restart
454            else:
455                restart=int(restart)
456                if restart<1:
457                    raise ValueError,"restart must be positive."
458                self.__restart=restart
459        def getRestart(self):
460            """
461            Returns the number of iterations steps after which GMRES is performing a restart.
462            If C{None} is returned no restart is performed.
463
464            @rtype: C{int} or C{None}
465            """
466            if self.__restart < 0:
467                return None
468            else:
469                return self.__restart
470        def setTruncation(self,truncation=20):
471            """
472            Sets the number of residuals in GMRES to be stored for orthogonalization.  The more residuals are stored
473            the faster GMRES converged but
474
475            @param truncation: truncation
476            @type truncation: C{int}
477            """
478            truncation=int(truncation)
479            if truncation<1:
480               raise ValueError,"truncation must be positive."
481            self.__truncation=truncation
482        def getTruncation(self):
483            """
484            Returns the number of residuals in GMRES to be stored for orthogonalization
485
486            @rtype: C{int}
487            """
488            return self.__truncation
489        def setInnerIterMax(self,iter_max=10):
490            """
491            Sets the maximum number of iteration steps for the inner iteration.
492
493            @param iter_max: maximum number of inner iterations
494            @type iter_max: C{int}
495            """
496            iter_max=int(iter_max)
497            if iter_max<1:
498               raise ValueError,"maximum number of inner iteration must be positive."
499            self.__inner_iter_max=iter_max
500        def getInnerIterMax(self):
501            """
502            Returns maximum number of inner iteration steps
503
504            @rtype: C{int}
505            """
506            return self.__inner_iter_max
507        def setIterMax(self,iter_max=10000):
508            """
509            Sets the maximum number of iteration steps
510
511            @param iter_max: maximum number of iteration steps
512            @type iter_max: C{int}
513            """
514            iter_max=int(iter_max)
515            if iter_max<1:
516               raise ValueError,"maximum number of iteration steps must be positive."
517            self.__iter_max=iter_max
518        def getIterMax(self):
519            """
520            Returns maximum number of iteration steps
521
522            @rtype: C{int}
523            """
524            return self.__iter_max
525        def setLevelMax(self,level_max=10):
526            """
527            Sets the maximum number of coarsening levels to be used in an algebraic multi level solver or preconditioner
528
529            @param level_max: maximum number of levels
530            @type level_max: C{int}
531            """
532            level_max=int(level_max)
533            if level_max<0:
534               raise ValueError,"maximum number of coarsening levels must be non-negative."
535            self.__level_max=level_max
536        def getLevelMax(self):
537            """
538            Returns the maximum number of coarsening levels to be used in an algebraic multi level solver or preconditioner
539
540            @rtype: C{int}
541            """
542            return self.__level_max
543        def setCoarseningThreshold(self,theta=0.05):
544            """
545            Sets the threshold for coarsening in the algebraic multi level solver or preconditioner
546
547            @param theta: threshold for coarsening
548            @type theta: positive C{float}
549            """
550            theta=float(theta)
551            if theta<0 or theta>1:
552               raise ValueError,"threshold must be non-negative and less or equal 1."
553            self.__coarsening_threshold=theta
554        def getCoarseningThreshold(self):
555            """
556            Returns the threshold for coarsening in the algebraic multi level solver or preconditioner
557
558            @rtype: C{float}
559            """
560            return self.__coarsening_threshold
561        def setNumSweeps(self,sweeps=2):
562            """
563            Sets the number of sweeps in a Jacobi or Gauss-Seidel/SOR preconditioner.
564
565            @param sweeps: number of sweeps
566            @type theta: positive C{int}
567            """
568            sweeps=int(sweeps)
569            if sweeps<1:
570               raise ValueError,"number of sweeps must be positive."
571            self.__sweeps=sweeps
572        def getNumSweeps(self):
573            """
574            Returns the number of sweeps in a Jacobi or Gauss-Seidel/SOR preconditioner.
575
576            @rtype: C{int}
577            """
578            return self.__sweeps
579        def setNumPreSweeps(self,sweeps=2):
580            """
581            Sets the number of sweeps in the pre-smoothing step of a multi level solver or preconditioner
582
583            @param sweeps: number of sweeps
584            @type theta: positive C{int}
585            """
586            sweeps=int(sweeps)
587            if sweeps<1:
588               raise ValueError,"number of sweeps must be positive."
589            self.__pre_sweeps=sweeps
590        def getNumPreSweeps(self):
591            """
592            Returns he number of sweeps in the pre-smoothing step of a multi level solver or preconditioner
593
594            @rtype: C{int}
595            """
596            return self.__pre_sweeps
597        def setNumPostSweeps(self,sweeps=2):
598            """
599            Sets the number of sweeps in the post-smoothing step of a multi level solver or preconditioner
600
601            @param sweeps: number of sweeps
602            @type theta: positive C{int}
603            """
604            sweeps=int(sweeps)
605            if sweeps<1:
606               raise ValueError,"number of sweeps must be positive."
607            self.__post_sweeps=sweeps
608        def getNumPostSweeps(self):
609            """
610            Returns he number of sweeps in the post-smoothing step of a multi level solver or preconditioner
611
612            @rtype: C{int}
613            """
614            return self.__post_sweeps
615
616        def setTolerance(self,rtol=1.e-8):
617            """
618            Sets the relative tolerance for the solver
619
620            @param rtol: relative tolerance
621            @type rtol: non-negative C{float}
622            """
623            rtol=float(rtol)
624            if rtol<0 or rtol>1:
625               raise ValueError,"tolerance must be non-negative and less or equal 1."
626            self.__tolerance=rtol
627        def getTolerance(self):
628            """
629            Returns the relative tolerance for the solver
630
631            @rtype: C{float}
632            """
633            return self.__tolerance
634        def setAbsoluteTolerance(self,atol=0.):
635            """
636            Sets the absolute tolerance for the solver
637
638            @param atol:  absolute tolerance
639            @type atol: non-negative C{float}
640            """
641            atol=float(atol)
642            if atol<0:
643               raise ValueError,"tolerance must be non-negative."
644            self.__absolute_tolerance=atol
645        def getAbsoluteTolerance(self):
646            """
647            Returns the absolute tolerance for the solver
648
649            @rtype: C{float}
650            """
651            return self.__absolute_tolerance
652
653        def setInnerTolerance(self,rtol=0.9):
654            """
655             Sets the relative tolerance for an inner iteration scheme for instance
656            on the coarsest level in a multi-level scheme.
657
658            @param rtol: inner relative tolerance
659            @type rtol: positive C{float}
660            """
661            rtol=float(rtol)
662            if rtol<=0 or rtol>1:
663                raise ValueError,"tolerance must be positive and less or equal 1."
664            self.__inner_tolerance=rtol
665        def getInnerTolerance(self):
666            """
667            Returns the relative tolerance for an inner iteration scheme
668
669            @rtype: C{float}
670            """
671            return self.__inner_tolerance
672        def setDropTolerance(self,drop_tol=0.01):
673            """
674            Sets the relative drop tolerance in ILUT
675
676            @param drop_tol: drop tolerance
677            @type drop_tol: positive C{float}
678            """
679            drop_tol=float(drop_tol)
680            if drop_tol<=0 or drop_tol>1:
681                raise ValueError,"drop tolerance must be positive and less or equal 1."
682            self.__drop_tolerance=drop_tol
683        def getDropTolerance(self):
684            """
685            Returns the relative drop tolerance in ILUT
686
687            @rtype: C{float}
688            """
689            return self.__drop_tolerance
690        def setDropStorage(self,storage=2.):
691            """
692            Sets the maximum allowed increase in storage for ILUT. C{storage}=2 would mean that
693            a doubling of the storage needed for the coefficient matrix is allowed in the ILUT factorization.
694
695            @param storage: allowed storage increase
696            @type storage: C{float}
697            """
698            storage=float(storage)
699            if storage<1:
700                raise ValueError,"allowed storage increase must be greater or equal to 1."
701            self.__drop_storage=storage
702        def getDropStorage(self):
703
704            """
705            Returns the maximum allowed increase in storage for ILUT
706
707            @rtype: C{float}
708            """
709            return self.__drop_storage
710        def setRelaxationFactor(self,factor=0.3):
711            """
712            Sets the relaxation factor used to add dropped elements in RILU to the main diagonal.
713
714            @param factor: relaxation factor
715            @type factor: C{float}
716            @note: RILU with a relaxation factor 0 is identical to ILU0
717            """
718            factor=float(factor)
719            if factor<0:
720                raise ValueError,"relaxation factor must be non-negative."
721            self.__relaxation=factor
722        def getRelaxationFactor(self):
723
724            """
725            Returns the relaxation factor used to add dropped elements in RILU to the main diagonal.
726
727            @rtype: C{float}
728            """
729            return self.__relaxation
730        def isSymmetric(self):
731            """
732            Checks if symmetry of the  coefficient matrix is indicated.
733
734            @return: True if a symmetric PDE is indicated, False otherwise
735            @rtype: C{bool}
736            """
737            return self.__symmetric
738        def setSymmetryOn(self):
739            """
740            Sets the symmetry flag to indicate that the coefficient matrix is symmetric.
741            """
742            self.__symmetric=True
743        def setSymmetryOff(self):
744            """
745            Clears the symmetry flag for the coefficient matrix.
746            """
747            self.__symmetric=False
748        def setSymmetry(self,flag=False):
749            """
750            Sets the symmetry flag for the coefficient matrix to C{flag}.
751
752            @param flag: If True, the symmetry flag is set otherwise reset.
753            @type flag: C{bool}
754            """
755            if flag:
756                self.setSymmetryOn()
757            else:
758                self.setSymmetryOff()
759        def isVerbose(self):
760            """
761            Returns C{True} if the solver is expected to be verbose.
762
763            @return: True if verbosity of switched on.
764            @rtype: C{bool}
765            """
766            return self.__verbose
767
768        def setVerbosityOn(self):
769            """
770            Switches the verbosity of the solver on.
771            """
772            self.__verbose=True
773        def setVerbosityOff(self):
774            """
775            Switches the verbosity of the solver off.
776            """
777            self.__verbose=False
778        def setVerbosity(self,verbose=True):
779            """
780            Sets the verbosity flag for the solver to C{flag}.
781
782            @param flag: If C{True}, the verbosity of the solver is switched on.
783            @type flag: C{bool}
784            """
785            if verbose:
786                self.setVerbosityOn()
787            else:
788                self.setVerbosityOff()
789
792            """
793            Returns C{True} if the tolerance of the inner solver is selected automatically.
794            Otherwise the inner tolerance set by L{setInnerTolerance} is used.
795
796            @return: C{True} if inner tolerance adaption is chosen.
797            @rtype: C{bool}
798            """
800
802            """
803            Switches the automatic selection of inner tolerance on
804            """
807            """
808            Switches the automatic selection of inner tolerance off.
809            """
812            """
813            Sets a flag to indicate automatic selection of the inner tolerance.
814
815            @param adapt: If C{True}, the inner tolerance is selected automatically.
817            """
820            else:
822
823        def acceptConvergenceFailure(self):
824            """
825            Returns C{True} if a failure to meet the stopping criteria within the
826            given number of iteration steps is not raising in exception. This is useful
827            if a solver is used in a non-linear context where the non-linear solver can
828            continue even if the returned the solution does not necessarily meet the
829            stopping criteria. One can use the L{hasConverged} method to check if the
830            last call to the solver was successful.
831
832            @return: C{True} if a failure to achieve convergence is accepted.
833            @rtype: C{bool}
834            """
835            return self.__accept_convergence_failure
836
837        def setAcceptanceConvergenceFailureOn(self):
838            """
839            Switches the acceptance of a failure of convergence on
840            """
841            self.__accept_convergence_failure=True
842        def setAcceptanceConvergenceFailureOff(self):
843            """
844            Switches the acceptance of a failure of convergence off.
845            """
846            self.__accept_convergence_failure=False
847        def setAcceptanceConvergenceFailure(self,accept=False):
848            """
849            Sets a flag to indicate the acceptance of a failure of convergence.
850
851            @param accept: If C{True}, any failure to achieve convergence is accepted.
852            @type accept: C{bool}
853            """
854            if accept:
855                self.setAcceptanceConvergenceFailureOn()
856            else:
857                self.setAcceptanceConvergenceFailureOff()
858
859  class IllegalCoefficient(ValueError):  class IllegalCoefficient(ValueError):
860     """     """
861     Exception that is raised if an illegal coefficient of the general or     Exception that is raised if an illegal coefficient of the general or
# Line 379  class PDECoef(object): Line 1191  class PDECoef(object):
1191                  s=s+(dim,)                  s=s+(dim,)
1192         return s         return s
1193
1194    #====================================================================================================================
1195
1196  class LinearProblem(object):  class LinearProblem(object):
1197     """     """
1198     This is the base class to define a general linear PDE-type problem for     This is the base class to define a general linear PDE-type problem for

Legend:
 Removed from v.2469 changed lines Added in v.2470