/[escript]/trunk/escript/py_src/modelframe.py
ViewVC logotype

Diff of /trunk/escript/py_src/modelframe.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/esys2/escript/py_src/modelframe.py revision 121 by jgs, Fri May 6 04:26:16 2005 UTC trunk/escript/py_src/modelframe.py revision 266 by elspeth, Wed Nov 30 00:21:51 2005 UTC
# Line 1  Line 1 
1  # $Id$  # $Id$
 from types import StringType  
2    
3  class Link:  from types import StringType,IntType,FloatType,BooleanType,ListType,DictType
4    """ """  from sys import stdout
5    def __init__(self,object,attribute=None):  import itertools
6       self.__object=object  # import modellib  temporarily removed!!!
7       self.setAttributeName(attribute)  
8    # import the 'set' module if it's not defined (python2.3/2.4 difference)
9    def setAttributeName(self,name):  try:
10       if not name==None:      set
11          if not hasattr(self.__object,name):  except NameError:
12             raise AttributeError("Link: object %s has no attribute %s."%(self.__object,name))      from sets import Set as set
13       self.__attribute=name  
14    from xml.dom import minidom
15    def hasAttributeName(self):  
16        if self.__attribute==None:  def dataNode(document, tagName, data):
17           return False      """
18        else:      C{dataNode}s are the building blocks of the xml documents constructed in
19           return True      this module.  
20        
21    def __str__(self):      @param document: the current xml document
22        if self.hasAttributeName():      @param tagName: the associated xml tag
23            return "reference to %s of %s"%(self.__attribute,self.__object)      @param data: the values in the tag
24        else:      """
25            return "reference to object %s"%self.__object      t = document.createTextNode(str(data))
26        n = document.createElement(tagName)
27    def getValue(self,name=None):      n.appendChild(t)
28        if not self.hasAttributeName():      return n
29           out=getattr(self.__object,name)  
30        else:  def esysDoc():
31           out=getattr(self.__object,self.__attribute)      """
32        if callable(out):      Global method for creating an instance of an EsysXML document.
33            return out()      """
34        else:      doc = minidom.Document()
35            return out      esys = doc.createElement('ESys')
36          doc.appendChild(esys)
37  class Model:      return doc, esys
38     """ the Model class provides a framework to run a time-dependent simulation. A Model has a set of parameter which  
39         may be fixed or altered by the Model itself or other Models over time.    def all(seq):
40        for x in seq:
41         The parameters of a models are declared at instantion, e.g.          if not x:
42                return False
43        return True
44    
45    def any(seq):
46        for x in seq:
47            if x:
48                return True
49        return False
50    
51             m=Model({"message" : "none" })  LinkableObjectRegistry = {}
52    
53         creates a Model with parameters p1 and p2 with inital values 1 and 2. Typically a particular model is defined as a subclass of Model:  def registerLinkableObject(obj_id, o):
54        LinkableObjectRegistry[obj_id] = o
55    
56          class Messenger(Model):  LinkRegistry = []
             def __init__(self):  
                Model.__init__(self,parameters={"message" : "none" })  
57    
58          m=MyModel()  def registerLink(obj_id, l):
59        LinkRegistry.append((obj_id,l))
60    
61         There are various ways how model parameters can be changed:  def parse(xml):
62        """
63        Generic parse method for EsysXML.  Without this, Links don't work.
64        """
65        global LinkRegistry, LinkableObjectRegistry
66        LinkRegistry = []
67        LinkableObjectRegistry = {}
68    
69         1) use object attributes:      doc = minidom.parseString(xml)
70        sim = getComponent(doc.firstChild)
71        for obj_id, link in LinkRegistry:
72            link.target = LinkableObjectRegistry[obj_id]
73    
74            m.message="Hello World!"      return sim
75    
76         2) use setParamter method  def importName(modulename, name):
77        """ Import a named object from a module in the context of this function,
78            which means you should use fully qualified module paths.
79                    
80                      Return None on failure.
           m.setParameters(message="Hello World!")  
   
        3) or dictonaries  
     
            d={ message : "Hello World!" }  
            m.setParameters(**d)  
   
   
        A model executed buy staring the run method of the model:  
   
           m=Messenger()  
           m.run()  
   
        The run methods marches through time. It first calls the  
        doInitialization() method of the Model to set up the process. In each time step the doStep() method is called  
        to get from the current to the next time step. The step size is defined by calling the getSafeTimeStepSize() method.  
        The time integration process is terminated when the finalize() methods return true. Final the doFinalization() method  
        is called to finalize the process. To implement a particular model a subclass  
        of the Model class is defined. The subclass overwrites the default methods of Model.  
   
        The following class defines a messenger printing in the doStep method what ever the current value of its parameter message is:  
   
        class Messenger(Model):  
             def __init__(self):  
                Model.__init__(self,parameters={"message" : "none" })  
   
             def doInitialization(self):  
                print "I start talking now!"  
81    
82              def doStep(self,t):          This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241
83                 print "Message (time %e) : %s "%(t,self.message)      """
84        module = __import__(modulename, globals(), locals(), [name])
85              def doFinalization(self):          
86                 print "I have no more to say!"      try:
87                  return vars(module)[name]
88         If a instance of the Messenger class is run, it will print the initialization and finalization message only.      except KeyError:
89         This is because the default method for finalize() does always returns True and therefore the transition is          raise ImportError("Could not import %s from %s" % (name, modulename))
90         terminated startcht away.  
91    def getComponent(doc):
92        """
93        Used to get components of Simualtions, Models.
94        """
95        for node in doc.childNodes:
96            
97            if isinstance(node, minidom.Element):
98                if node.tagName == 'Simulation':
99                    if node.getAttribute("type") == 'Simulation':
100                        return Simulation.fromDom(node)
101                if node.tagName == 'Model':
102                    if (node.getAttribute("module")):
103                        model_module = node.getAttribute("module")
104                        model_type = node.getAttribute("type")
105                        return importName(model_module, model_type).fromDom(node)
106                    else:
107                        model_type = node.getAttribute("type")
108                        model_subclasses = Model.__subclasses__()
109                        for model in model_subclasses:
110                            if model_type == model.__name__:
111                                return Model.fromDom(node)
112                if node.tagName == 'ParameterSet':
113                    parameter_type = node.getAttribute("type")
114                    return ParameterSet.fromDom(node)
115                raise "Invalid simulation type, %r" % node.getAttribute("type")
116                    
        Following example for solving the ODE using a forward euler scheme:  
   
                 u(t=0)=u0  
                 u_t=a*u**2       for all 0<t<=ten  
   
       exact solution is given by u(t)=1/(1/u0-a*t)  
   
       class  Ode1(Model):  
          def __init__(self,**args):  
             Model.__init__(self,parameters={"tend" : 1., "dt" : 0.0001 ,"a" : 0.1 ,"u" : 1. },name="test",debug=True)  
   
          def doInitialization(self):  
              self._tn=0  
   
          def doStep(self,t):  
              self.u=self.u+(t-self._tn)*self.a*self.u**2  
              self._tn=t  
   
          def doFinalization(self):  
              print "all done final error = ",abs(self.u-1./(1./3.-self.a*self._tn))  
   
          def getSafeTimeStepSize(self):  
              return self.dt  
117    
118           def finalize(self):      raise ValueError("No Simulation Found")
119               return self._tn>=self.tend              
120    
121         In some cases at a given time step an iteration process has to be performed to get the state of the Model for the next time step. `  class Link:
122         In this case the doStep() method is replaced by a sequance of methods which implements this iterative process.      """
123         The method then will control the iteration process by initializing the iteration through calling the      A Link makes an attribute of an object callable::
        doIterationInitialization() method. The iteration is preformed by calling the doIterationStep() method until  
        the terminate() method returns True. The doIterationFinalization() method is called to end the iteration.  
        For a particular model these methods have to overwritten by a suitable subclass without touching the doStep() method.  
124    
125         following example is a modification of the example above. Here an implicit euler scheme is used. in each time step the problem            o.object()
126              o.a=8
127              l=Link(o,"a")
128              assert l()==8
129         """
130        
131        def __init__(self,target,attribute=None):
132            """
133            Creates a link to the object target. If attribute is given, the link is
134            establised to this attribute of the target.  Otherwise the attribute is
135            undefined.
136            """
137            self.target = target
138            self.attribute = None
139            self.setAttributeName(attribute)
140        
141        def setAttributeName(self,attribute):
142            """
143            Set a new attribute name to be collected from the target object. The
144            target object must have the attribute with name attribute.
145            """
146            if attribute and self.target:
147                if isinstance(self.target,LinkableObject):
148                   if not self.target.hasAttribute(attribute):
149                      raise AttributeError("%s: target %s has no attribute %s."%(self, self.target, attribute))
150                else:
151                   if not hasattr(self.target,attribute):
152                      raise AttributeError("%s: target %s has no attribute %s."%(self, self.target, attribute))
153            self.attribute = attribute
154        
155        def hasDefinedAttributeName(self):
156            """
157            Returns true if an attribute name is set.
158            """
159            return self.attribute != None
160        
161        def __repr__(self):
162            """
163            Returns a string representation of the link.
164            """
165            if self.hasDefinedAttributeName():
166                return "<Link to attribute %s of %s>" % (self.attribute, self.target)
167            else:
168                return "<Link to target %s>" % self.target
169        
170        def __call__(self,name=None):
171            """
172            Returns the value of the attribute of the target object. If the
173            atrribute is callable then the return value of the call is returned.
174            """
175            if name:
176                out=getattr(self.target, name)
177            else:
178                out=getattr(self.target, self.attribute)
179    
180            if callable(out):
181                return out()
182            else:
183                return out
184    
185        def toDom(self, document, node):
186            """
187            C{toDom} method of Link. Creates a Link node and appends it to the
188        current XML document.
189            """
190            link = document.createElement('Link')
191            assert (self.target != None), ("Target was none, name was %r" % self.attribute)
192            link.appendChild(dataNode(document, 'Target', self.target.id))
193            # this use of id will not work for purposes of being able to retrieve the intended
194            # target from the xml later. I need a better unique identifier.
195            assert self.attribute, "You can't xmlify a Link without a target attribute"
196            link.appendChild(dataNode(document, 'Attribute', self.attribute))
197            node.appendChild(link)
198    
199        def fromDom(cls, doc):
200            targetid = doc.getElementsByTagName("Target")[0].firstChild.nodeValue.strip()
201            attribute = doc.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip()
202            l = cls(None, attribute)
203            registerLink(targetid, l)
204            return l
205    
206        fromDom = classmethod(fromDom)
207        
208        def writeXML(self,ostream=stdout):
209            """
210            Writes an XML representation of self to the output stream ostream.
211            If ostream is nor present the standart output stream is used.  If
212            esysheader==True the esys XML header is written
213            """
214            print 'I got to the Link writeXML method'
215            document, rootnode = esysDoc()
216            self.toDom(document, rootnode)
217    
218            ostream.write(document.toprettyxml())
219    
220    class LinkableObject(object):
221        """
222        An object that allows to link its attributes to attributes of other objects
223        via a Link object. For instance::
224                        
225             0= u_{n+1}-u_{n}+a*dt*u_{n+1}**2             p = LinkableObject()
226               p.x = Link(o,"name")
227         has to be solved for u_{n+1}. The Newton scheme is used to solve this non-linear problem.             print p.x
228        
229        links attribute C{x} of C{p} to the attribute name of object C{o}.
230        class  Ode2(Model):  
231        C{p.x} will contain the current value of attribute C{name} of object
232         def __init__(self,**args):      C{o}.  
233             Model.__init__(self,{"tend" : 1., "dt" : 0.1 ,"a" : 10. ,"u" : 1. , "tol " : 1.e-8},"test","bla",None,True)  
234        If the value of C{getattr(o, "name")} is callable, C{p.x} will return
235         def doInitialization(self):      the return value of the call.
236             self.__tn=0      """
237      
238         def doIterationInitialization(self,t):      number_sequence = itertools.count(100)
239              self.__iter=0      
240              self.u_last=self.u                  def __init__(self, debug=False):
241              self.current_dt=t-self.tn          """
242              self.__tn=t      Initializes LinkableObject so that we can operate on Links
243        """
244         def doIterationStep(self):          self.debug = debug
245            self.__iter+=1          self.__linked_attributes={}
246            self.u_old=self.u          self.id = self.number_sequence.next()
247            self.u=(self.current_dt*self.a*self.u**2-self.u_last)/(2*self.current_dt*self.a*self.u-1.)          registerLinkableObject(self.id, self)
248    
249         def terminate(self):      def trace(self, msg):
250             return abs(self.u_old-self.u)<self.tol*abs(self.u)          """
251        If debugging is on, print the message, otherwise do nothing
252         def doIterationFinalization(self)          """
253             print "all done"          if self.debug:
254                print "%s: %s"%(str(self),msg)
255         def getSafeTimeStepSize(self):      
256             return self.dt      def __getattr__(self,name):
257            """
258         def finalize(self):      Returns the value of attribute name. If the value is a Link object the
259              return self.__tn>self.tend          object is called and the return value is returned.
260        """
261         A model can be composed from submodels. Submodels are treated as model parameters. If a model parameter is set or a value of          out = self.getAttributeObject(name)
262         a model parameter is requested, the model will search for this parameter its submodels in the case the model does not have this          if isinstance(out,Link):
263         parameter itself. The order in which the submodels are searched is critical. By default a Model initializes all its submodels,              return out()
264         is finalized when all its submodels are finalized and finalizes all its submodels. In the case an iterative process is applied          else:
265         on a particular time step the iteration is initialized for all submodels, then the iteration step is performed for each submodel              return out
266         until all submodels indicate termination. Then the iteration is finalized for all submodels. Finally teh doStop() method for all      
267         submethods is called.      def getAttributeObject(self,name):
268            """
269         Here we are creating a model which groups ab instantiation of the Ode2 and the Messenger Model      Return the object stored for attribute name.
270        """
271         o=Ode2()  
272         m=Messenger()          if self.__dict__.has_key(name):
273         om=Model(submodels=[o,m],debug=True)              return self.__dict__[name]
274         om.dt=0.01  
275         om.u=1.          if self.__linked_attributes.has_key(name):
276         m.message="it's me!"              return self.__linked_attributes[name]
277         om.run()  
278            if self.__class__.__dict__.has_key(name):
279         Notice that dt and u are parameters of class Ode2 and message is a parameter of the Messenger class. The Model formed from these models              return self.__class.__dict__[name]
280         automatically hand the assignment of new values down to the submodel. om.run() starts this combined model where now the soStep() method  
281         of the Messenger object printing the value of its parameter message together with a time stamp is executed in each time step introduced          raise AttributeError,"No attribute %s."%name
282         by the Ode2 model.      
283        def hasAttribute(self,name):
284         A parameter of a Model can be linked to an attribute of onother object, typically an parameter of another Model object.              """
285              Returns True if self as attribute name.
286        """
287            return self.__dict__.has_key(name) or self.__linked_attributes.has_key(name) or  self.__class__.__dict__.has_key(name)
288    
289        def __setattr__(self,name,value):
290            """
291        Sets the value for attribute name. If value is a Link the target
292            attribute is set to name if no attribute has been specified.
293        """
294    
295            if self.__dict__.has_key(name):
296                del self.__dict__[name]
297    
298            if isinstance(value,Link):
299                if not value.hasDefinedAttributeName():
300                    value.setAttributeName(name)
301                self.__linked_attributes[name] = value
302    
303                self.trace("attribute %s is now linked by %s."%(name,value))
304            else:
305                self.__dict__[name] = value
306        
307        def __delattr__(self,name):
308            """
309        Removes the attribute name.
310        """
311    
312            if self.__linked_attributes.has_key[name]:
313                del self.__linked_attributes[name]
314            elif self.__dict__.has_key(name):
315                del self.__dict__[name]
316            else:
317                raise AttributeError,"No attribute %s."%name
318    
319    class _ParameterIterator:
320        def __init__(self,parameterset):
321    
322            self.__set=parameterset
323            self.__iter=iter(parameterset.parameters)
324    
325        def next(self):
326            o=self.__iter.next()
327            return (o,self.__set.getAttributeObject(o))
328    
329        def __iter__(self):
330            return self
331    
332    class ParameterSet(LinkableObject):
333        """
334        A class which allows to emphazise attributes to be written and read to XML
335                
336         which is comprised by a set of submodels.      Leaves of an ESySParameters object can be:
337         The simulation is run through its run method which in the simplest case has the form:      
338         - a real number
339         - a integer number
340         - a string
341         - a boolean value
342         - a ParameterSet object
343         - a Simulation object
344         - a Model object
345         - any other object (not considered by writeESySXML and writeXML)
346        
347        Example how to create an ESySParameters object::
348        
349            p11=ParameterSet(gamma1=1.,gamma2=2.,gamma3=3.)
350            p1=ParameterSet(dim=2,tol_v=0.001,output_file="/tmp/u.%3.3d.dx",runFlag=True,parm11=p11)
351            parm=ParameterSet(parm1=p1,parm2=ParameterSet(alpha=Link(p11,"gamma1")))
352        
353        This can be accessed as::
354        
355        parm.parm1.gamma=0.
356            parm.parm1.dim=2
357            parm.parm1.tol_v=0.001
358            parm.parm1.output_file="/tmp/u.%3.3d.dx"
359            parm.parm1.runFlag=True
360            parm.parm1.parm11.gamma1=1.
361            parm.parm1.parm11.gamma2=2.
362            parm.parm1.parm11.gamma3=3.
363            parm.parm2.alpha=1. (value of parm.parm1.parm11.gamma1)
364        """
365        def __init__(self, parameters=[], **kwargs):
366            """
367        Creates a ParameterSet with parameters parameters.
368        """
369            LinkableObject.__init__(self, **kwargs)
370            self.parameters = set()
371            self.declareParameters(parameters)
372    
373        def __repr__(self):
374            return "<%s %r>" % (self.__class__.__name__,
375                                [(p, getattr(self, p, None)) for p in self.parameters])
376        
377        def declareParameter(self,**parameters):
378            """
379        Declares a new parameter(s) and its (their) initial value.
380        """
381            self.declareParameters(parameters)
382        
383        def declareParameters(self,parameters):
384            """
385        Declares a set of parameters. parameters can be a list, a dictionary
386        or a ParameterSet.
387        """
388            if isinstance(parameters,ListType):
389                parameters = zip(parameters, itertools.repeat(None))
390            if isinstance(parameters,DictType):
391                parameters = parameters.iteritems()
392    
393            for prm, value in parameters:
394                setattr(self,prm,value)
395                self.parameters.add(prm)
396    
397                self.trace("parameter %s has been declared."%prm)
398    
399        def releaseParameters(self,name):
400            """
401        Removes parameter name from the paramameters.
402        """
403            if self.isParameter(name):
404                self.parameters.remove(name)
405                self.trace("parameter %s has been removed."%name)
406        
407        def __iter__(self):
408            """
409        Creates an iterator over the parameter and their values.
410        """
411            return _ParameterIterator(self)
412        
413        def showParameters(self):
414            """
415        Returns a descrition of the parameters.
416        """        
417            out="{"
418            notfirst=False
419            for i,v in self:
420                if notfirst: out=out+","
421                notfirst=True
422                if isinstance(v,ParameterSet):
423                    out="%s\"%s\" : %s"%(out,i,v.showParameters())
424                else:
425                    out="%s\"%s\" : %s"%(out,i,v)
426            return out+"}"
427        
428        def __delattr__(self,name):
429            """
430        Removes the attribute name.
431        """
432            LinkableObject.__delattr__(self,name)
433            try:
434                self.releaseParameter(name)
435            except:
436                pass
437    
438        def toDom(self, document, node):
439            """
440        C{toDom} method of ParameterSet class.
441        """
442            pset = document.createElement('ParameterSet')
443            node.appendChild(pset)
444            self._parametersToDom(document, pset)
445    
446        def _parametersToDom(self, document, node):
447            node.setAttribute ('id', str(self.id))
448            for name,value in self:
449                param = document.createElement('Parameter')
450                param.setAttribute('type', value.__class__.__name__)
451    
452                param.appendChild(dataNode(document, 'Name', name))
453    
454                val = document.createElement('Value')
455    
456                if isinstance(value,ParameterSet):
457                    value.toDom(document, val)
458                    param.appendChild(val)
459                elif isinstance(value, Link):
460                    value.toDom(document, val)
461                    param.appendChild(val)
462                elif isinstance(value,StringType):
463                    param.appendChild(dataNode(document, 'Value', value))
464                else:
465                    param.appendChild(dataNode(document, 'Value', str(value)))
466    
467            s=Model()              node.appendChild(param)
           s.run()  
468    
469         The run has an initializion and finalization phase. The latter is called if all submodels are to be finalized. The      def fromDom(cls, doc):
        simulation is processing in time through calling the stepForward methods which updates the observables of each submodel.  
        A time steps size which is save for all submodel is choosen.  
470    
471         At given time step an iterative process may be performed to make sure that all observables are consistent across all submodels.          # Define a host of helper functions to assist us.
472         In this case, similar the time dependence, an initialization and finalization of the iteration is performed.          def _children(node):
473                """
474                Remove the empty nodes from the children of this node.
475                """
476                return [x for x in node.childNodes
477                        if not isinstance(x, minidom.Text) or x.nodeValue.strip()]
478    
479         A Model has input and output parameters where each input parameter can be constant, time dependent or may depend on an          def _floatfromValue(doc):
480         output parameter of another model or the model itself. To create a parameter name of a model and to              return float(doc.nodeValue.strip())
        assign a value to it one can use the statement  
481    
482             model.name=object          def _stringfromValue(doc):
483                return str(doc.nodeValue.strip())
484          
485            def _intfromValue(doc):
486                return int(doc.nodeValue.strip())
487    
488            def _boolfromValue(doc):
489                return bool(doc.nodeValue.strip())
490    
491         At any time the current value of the parameter name can be obtained by          def _nonefromValue(doc):
492                return None
493          
494            # Mapping from text types in the xml to methods used to process trees of that type
495            ptypemap = {"Simulation": Simulation.fromDom,
496                        "Model":Model.fromDom,
497                        "ParameterSet":ParameterSet.fromDom,
498                        "Link":Link.fromDom,
499                        "float":_floatfromValue,
500                        "int":_intfromValue,
501                        "str":_stringfromValue,
502                        "bool":_boolfromValue
503                        "NoneType":_nonefromValue,
504                        }
505    
506    #        print doc.toxml()
507    
508            parameters = {}
509            for node in _children(doc):
510                ptype = node.getAttribute("type")
511    
512                pname = pvalue = None
513                for childnode in _children(node):
514    
515                    if childnode.tagName == "Name":
516                        pname = childnode.firstChild.nodeValue.strip()
517    
518                    if childnode.tagName == "Value":
519                        nodes = _children(childnode)
520                        pvalue = ptypemap[ptype](nodes[0])
521    
522                parameters[pname] = pvalue
523    
524            # Create the instance of ParameterSet
525            o = cls()
526            o.declareParameters(parameters)
527            registerLinkableObject(doc.getAttribute("id"), o)
528            return o
529        
530        fromDom = classmethod(fromDom)
531        
532        def writeXML(self,ostream=stdout):
533            """
534        Writes the object as an XML object into an output stream.
535        """
536            # ParameterSet(d) with d[Name]=Value
537            document, node = esysDoc()
538            self.toDom(document, node)
539            ostream.write(document.toprettyxml())
540    
541    class Model(ParameterSet):
542        """
543        A Model object represents a processess marching over time until a
544        finalizing condition is fullfilled. At each time step an iterative
545        process can be performed and the time step size can be controlled. A
546        Model has the following work flow::
547    
548              doInitialization()
549              while not finalize():
550                   dt=getSafeTimeStepSize(dt)
551                   doStepPreprocessing(dt)
552                   while not terminateIteration(): doStep(dt)
553                   doStepPostprocessing(dt)
554              doFinalization()
555    
556        where C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
557        C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
558        C{doFinalization} are methods of the particular instance of a Model. The
559        default implementations of these methods have to be overwritten by the
560        subclass implementing a Model.
561        """
562    
563        UNDEF_DT=1.e300
564    
565        def __init__(self,parameters=[],**kwarg):
566            """
567        Creates a model.
568    
569            Just calls the parent constructor.
570            """
571            ParameterSet.__init__(self, parameters=parameters,**kwarg)
572    
573        def __str__(self):
574           return "<%s %d>"%(self.__class__,id(self))
575    
576        def toDom(self, document, node):
577            """
578        C{toDom} method of Model class
579        """
580            pset = document.createElement('Model')
581            pset.setAttribute('type', self.__class__.__name__)
582            if not self.__class__.__module__.startswith('esys.escript'):
583                pset.setAttribute('module', self.__class__.__module__)
584            node.appendChild(pset)
585            self._parametersToDom(document, pset)
586    
587        def doInitialization(self):
588            """
589        Initializes the time stepping scheme.  
590        
591        This function may be overwritten.
592        """
593            pass
594        
595        def getSafeTimeStepSize(self,dt):
596            """
597        Returns a time step size which can safely be used.
598    
599            C{dt} gives the previously used step size.
600    
601            This function may be overwritten.
602        """
603            return self.UNDEF_DT
604        
605        def finalize(self):
606            """
607        Returns False if the time stepping is finalized.
608        
609        This function may be overwritten.
610        """
611            return False
612          
613        def doFinalization(self):
614            """
615        Finalizes the time stepping.
616        
617        This function may be overwritten.
618        """
619            pass
620        
621        def doStepPreprocessing(self,dt):
622            """
623        Sets up a time step of step size dt.
624        
625        This function may be overwritten.
626        """
627            pass
628        
629        def doStep(self,dt):
630            """
631        Executes an iteration step at a time step.
632    
633            C{dt} is the currently used time step size.
634    
635            This function may be overwritten.
636        """
637            pass
638        
639        def terminateIteration(self):
640            """
641        Returns True if iteration on a time step is terminated.
642        """
643            return True
644          
645        def doStepPostprocessing(self,dt):
646            """
647        Finalalizes the time step.
648    
649            dt is the currently used time step size.
650    
651            This function may be overwritten.
652        """
653            pass
654        
655        def writeXML(self, ostream=stdout):
656            document, node = esysDoc()
657            self.toDom(document, node)
658            ostream.write(document.toprettyxml())
659        
660    
661    class Simulation(Model):
662        """
663        A Simulation object is special Model which runs a sequence of Models.
664    
665        The methods C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
666        C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
667        C{doFinalization} are executing the corresponding methods of the models in
668        the simulation.
669        """
670        
671        FAILED_TIME_STEPS_MAX=20
672        MAX_ITER_STEPS=50
673        
674        def __init__(self, models=[], **kwargs):
675            """
676        Initiates a simulation from a list of models.
677        """
678            Model.__init__(self, **kwargs)
679            self.__models=[]
680            
681            for i in range(len(models)):
682                self[i] = models[i]
683                
684    
685                 value=model.name      def __repr__(self):
686            """
687            Returns a string representation of the Simulation.
688            """
689            return "<Simulation %r>" % self.__models
690    
691        def __str__(self):
692            """
693            Returning Simulation as a string.
694            """
695            return "<Simulation %d>"%id(self)
696        
697        def iterModels(self):
698            """
699        Returns an iterator over the models.
700        """
701            return self.__models
702        
703        def __getitem__(self,i):
704            """
705        Returns the i-th model.
706        """
707            return self.__models[i]
708        
709        def __setitem__(self,i,value):
710            """
711        Sets the i-th model.
712        """
713            if not isinstance(value,Model):
714                raise ValueError("assigned value is not a Model")
715            for j in range(max(i-len(self.__models)+1,0)):
716                self.__models.append(None)
717            self.__models[i]=value
718        
719        def __len__(self):
720            """
721        Returns the number of models.
722        """
723            return len(self.__models)
724    
725        def toDom(self, document, node):
726            """
727        C{toDom} method of Simulation class.
728        """
729            simulation = document.createElement('Simulation')
730            simulation.setAttribute('type', self.__class__.__name__)
731    
732            for rank, sim in enumerate(self.iterModels()):
733                component = document.createElement('Component')
734                component.setAttribute('rank', str(rank))
735    
736                sim.toDom(document, component)
737    
738                simulation.appendChild(component)
739    
740            node.appendChild(simulation)
741    
742        def writeXML(self,ostream=stdout):
743            """
744        Writes the object as an XML object into an output stream.
745        """
746            document, rootnode = esysDoc()
747            self.toDom(document, rootnode)
748            targetsList = document.getElementsByTagName('Target')
749            for i in targetsList:
750                targetId = int(i.firstChild.nodeValue.strip())
751                targetObj = LinkableObjectRegistry[targetId]
752                targetObj.toDom(document, rootnode)
753            ostream.write(document.toprettyxml())
754        
755        def getSafeTimeStepSize(self,dt):
756            """
757        Returns a time step size which can safely be used by all models.
758    
759            This is the minimum over the time step sizes of all models.
760        """
761            out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
762            #print "%s: safe step size is %e."%(str(self),out)
763            return out
764        
765        def doInitialization(self):
766            """
767        Initializes all models.
768        """
769            self.n=0
770            self.tn=0.
771            for o in self.iterModels():
772                o.doInitialization()
773        
774        def finalize(self):
775            """
776        Returns True if any of the models is to be finalized.
777        """
778            return any([o.finalize() for o in self.iterModels()])
779          
780        def doFinalization(self):
781            """
782        Finalalizes the time stepping for all models.
783        """
784            for i in self.iterModels(): i.doFinalization()
785            self.trace("end of time integation.")
786        
787        def doStepPreprocessing(self,dt):
788            """
789        Initializes the time step for all models.
790        """
791            for o in self.iterModels():
792                o.doStepPreprocessing(dt)
793        
794        def terminateIteration(self):
795            """
796        Returns True if all iterations for all models are terminated.
797        """
798            out=all([o.terminateIteration() for o in self.iterModels()])
799            return out
800          
801        def doStepPostprocessing(self,dt):
802            """
803        Finalalizes the iteration process for all models.
804        """
805            for o in self.iterModels():
806                o.doStepPostprocessing(dt)
807            self.n+=1
808            self.tn+=dt
809        
810        def doStep(self,dt):
811            """
812        Executes the iteration step at a time step for all model::
813    
814                self.doStepPreprocessing(dt)
815                while not self.terminateIteration():
816                for all models:
817                self.doStep(dt)
818                    self.doStepPostprocessing(dt)
819            """
820            self.iter=0
821            while not self.terminateIteration():
822                if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt))
823                self.iter+=1
824                self.trace("iteration step %d"%(self.iter))
825                for o in self.iterModels():
826                      o.doStep(dt)
827            if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.n+1,self.tn+dt))
828    
829        def run(self,check_point=None):
830            """
831        Run the simulation by performing essentially::
832        
833            self.doInitialization()
834            while not self.finalize():
835                dt=self.getSafeTimeStepSize()
836                self.doStep(dt)
837                if n%check_point==0:
838                self.writeXML()
839            self.doFinalization()
840    
841            If one of the models in throws a C{FailedTimeStepError} exception a
842        new time step size is computed through getSafeTimeStepSize() and the
843        time step is repeated.
844      
845            If one of the models in throws a C{IterationDivergenceError}
846        exception the time step size is halved and the time step is repeated.
847    
848         If the object that has been assigned to the paramter/attribute name has the attribute/parameter name isself the current value of this          In both cases the time integration is given up after
849         attribute of the object is returned (e.g. for model.name=object where object has an attribute name, the statement value=model.name whould assign      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
850         the value object.name to value.). If the name of the parameters of a model and an object don't match the setParameter method of model can be used. So          """
851            dt=self.UNDEF_DT
852            self.doInitialization()
853            while not self.finalize():
854                step_fail_counter=0
855                iteration_fail_counter=0
856                dt_new=self.getSafeTimeStepSize(dt)
857                self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))
858                end_of_step=False
859                while not end_of_step:
860                   end_of_step=True
861                   if not dt_new>0:
862                      raise NonPositiveStepSizeError("non-positive step size in step %d",self.n+1)
863                   try:
864                      self.doStepPreprocessing(dt_new)
865                      self.doStep(dt_new)
866                      self.doStepPostprocessing(dt_new)
867                   except IterationDivergenceError:
868                      dt_new*=0.5
869                      end_of_step=False
870                      iteration_fail_counter+=1
871                      if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
872                               raise SimulationBreakDownError("reduction of time step to achieve convergence failed.")
873                      self.trace("iteration fails. time step is repeated with new step size.")
874                   except FailedTimeStepError:
875                      dt_new=self.getSafeTimeStepSize(dt)
876                      end_of_step=False
877                      step_fail_counter+=1
878                      self.trace("time step is repeated.")
879                      if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
880                            raise SimulationBreakDownError("time integration is given up after %d attempts."%step_fail_counter)
881                dt=dt_new
882                if not check_point==None:
883                    if n%check_point==0:
884                        self.trace("check point is created.")
885                        self.writeXML()
886            self.doFinalization()
887    
888        def fromDom(cls, doc):
889            sims = []
890            for node in doc.childNodes:
891                if isinstance(node, minidom.Text):
892                    continue
893    
894             model.setParameter(name,object,name_for_object)              sims.append(getComponent(node))
895    
896         links the parameter name of model with the parameter name_for_object of object.          return cls(sims)
897    
898         The run method initiates checkpointing (it is not clear how to do this yet)      fromDom = classmethod(fromDom)
    =====  
               
    """  
    # step size used in case of an undefined value for the step size  
    UNDEF_DT=1.e300  
   
    def __init__(self,submodels=[],parameters={},name="model",description="none",check_pointing=None,debug=False):  
       """initiates a model from a list of submodels. """  
       self.setDebug(debug)  
       self.__check_pointing=check_pointing  
       self.__parameters={}  
       self.setName(name)  
       self.setDescription(description)  
       self.declareParameter(**parameters)  
       # get the models defined in parameters:  
       self.__submodels=[]  
       # submodels==None means no submodels used:  
       if submodels==None:  
          pass  
       # no submodel list given means all submodels are used as defined by the parameters dictionary:  
       elif len(submodels)==0:  
             for i in parameters.keys():  
                 if isinstance(parameters[i],Model): self.__submodels.append(i)  
       # submodel list of strings and Models is given, submodels defines the order in which the  
       # submodels are processed. if new models are found in the list they are added to the parameter dictionary.  
       else:  
          c=0  
          for i in submodels:  
             if isinstance(i,StringType):  
               m=self.getParameter(i)  
               if not isinstance(m,Model):  
                  raise ValueError,"submodel %s is not a model."%i  
             else:  
                if not isinstance(i,Model):  
                  raise ValueError,"submodel list does contain item which is not a Model class object."  
                m=i  
                i="__submodel%d__"%c  
                self.declareParameter(**{i : m})  
                c+=1  
             self.__submodels.append(i)  
             if self.debug(): print "%s: model %s is added as parameter %s."%(self,m,i)  
       if len(self.__submodels)>0 and self.debug(): print "%s: model ordering is %s"%(self,self.__submodels)  
    def setSubmodelOrder(submodels=[]):  
       """sets a new ordering for submodels"""  
         
       
    #  
    # some basic fuctions:  
    #  
    def debugOn(self):  
       """sets debugging to on"""  
       self.__debug=True  
    def debugOff(self):  
       """sets debugging to off"""  
       self.__debug=False  
    def debug(self):  
       """returns True if debug mode is set to on"""  
       return self.__debug  
    def setDebug(self,flag=False):  
       """sets debugging to flag"""  
       if flag:  
          self.debugOn()  
       else:  
          self.debugOff()  
    def setDebug(self,flag=False):  
       """sets debugging to flag"""  
       if flag:  
          self.debugOn()  
       else:  
          self.debugOff()  
    # name and description handling  
    def __str__(self):  
        """returns the name of the model"""  
        return self.getName()  
   
    def getName(self):  
        """returns the name of the model"""  
        return self.__name  
   
    def getFullName(self):  
        """returns the full name of the model including all the names of the submodels"""  
        out=str(self)+"("  
        notfirst=False  
        for i in self.__submodels:  
             if notfirst: out=out+","  
             out=out+i.getFullName()  
             notfirst=True  
        return out+")"  
899    
    def setName(self,name):  
        """sets the name of the model"""  
        self.__name=name  
   
    def setDescription(self,description="none"):  
        """sets new description"""  
        self.__description=description  
        if self.debug(): print "%s: description is set to %s."%(self,description)  
    def getDescription(self):  
        """returns the description of the model"""  
        return self.__description  
    #  
    #    parameter/attribute handling:  
    #  
    def declareParameter(self,**parameters):  
       """declares a new parameter and its inital value."""  
       for prm in parameters.keys():  
          if prm in self.__dict__.keys():  
              raise ValueError,"object attribute %s of %s cannot be used as a model parameter."%(prm,self)  
          self.__parameters[prm]=parameters[prm]  
          if self.debug(): print "%s: parameter %s has been declared."%(self,prm)  
   
   
   
    def showParameters(self):  
       """returns a descrition of the parameters"""  
       out=""  
       notfirst=False  
       for i in self.__parameters:  
           if notfirst: out=out+","  
           notfirst=True  
           out="%s%s=%s"%(out,i,self.__parameters[i])  
       return out  
   
   
    def deleteParameter(self,name):  
       """removes parameter name from the model"""  
       raise IllegalParameterError("Cannot delete parameter %s."%name)  
   
    def getParameter(self,name):  
       """returns the value of parameter name. If the parameter is not declared in self, the submodels are searched.  
          if the parameter is a Link, the current value of the obejective is returned."""  
       if self.__parameters.has_key(name):  
           if isinstance(self.__parameters[name],Link):  
              out=self.__parameters[name].getValue(name)  
           else:  
              out=self.__parameters[name]  
       else:  
           out=None  
           for i in self.__submodels:  
              try:  
                 out=self.__parameters[i].getParameter(name)  
              except IllegalParameterError:  
                 pass  
           if out==None: raise IllegalParameterError("Cannot find parameter %s."%name)  
       return out  
   
    def setParameter(self,**parameters):  
       """sets parameter name to value. If the initial value for the parameter is a Model, the new value has to be a Model."""  
       for name in parameters.keys():  
          if self.__parameters.has_key(name):  
             if not isinstance(parameters[name],Model) and isinstance(self.__parameters[name],Model):  
                 raise ValueError,"%s: parameter %s can assigned to a Model object only."%(self,name)  
             if isinstance(parameters[name],Model) and not isinstance(self.__parameters[name],Model):  
                 raise ValueError,"%s: parameter %s is not declared as a Model."%(self,name)  
             self.__parameters[name]=parameters[name]  
             if isinstance(self.__parameters[name],Link):  
                  if not self.__parameters[name].hasAttributeName(): self.__parameters[name].setAttributeName(name)  
             if self.debug(): print "%s: parameter %s has now value %s"%(self,name,self.__parameters[name])  
          else:  
             set=False  
             for i in self.__submodels:  
                 try:  
                    self.__parameters[i].setParameter(**{name : parameters[name]})  
                    set=True  
                 except IllegalParameterError:  
                     pass  
             if not set: raise IllegalParameterError("%s: Attempt to set undeclared parameter %s."%(self,name))  
   
    def hasParameter(self,name):  
       """returns True if self or one of the submodels has parameter name"""  
       if self.__parameters.has_key(name):  
          out=True  
       else:  
          out=False  
          for i in self.__submodels: out= out or self.__parameters[i].hasParameter(name)  
       return out  
   
    def checkParameter(self,name):  
       """checks if self has the parameter name. Otherewise ParameterError is thrown."""  
       if not self.hasParameter(name):  
            raise ParameterError("%s has no parameter %s."%(str(self),name))  
     
    def __getattr__(self,name):  
       """returns the value for attribute name. If name is in the Link list, the corresponding attribute is returned."""  
       if self.__dict__.has_key(name):  
          return self.__dict__[name]  
       elif self.__dict__.has_key("_Model__parameters") and self.__dict__.has_key("_Model__submodels"):  
          return self.getParameter(name)  
       else:  
          raise AttributeError,"No attribute %s."%name  
   
    def __setattr__(self,name,value):  
       """returns the value for attribute name."""  
       if self.__dict__.has_key("_Model__parameters") and self.__dict__.has_key("_Model__submodels"):  
          if self.hasParameter(name):  
             self.setParameter(**{ name : value })  
          else:  
             self.__dict__[name]=value  
       else:  
          self.__dict__[name]=value  
   
    def __delattr__(self,name):  
       """removes the attribute name."""  
       if self.__dict__.has_key(name):  
          del self.__dict__[name]  
       elif self.__dict__.has_key("_Model__parameters"):  
          self.deleteParameter(name)  
       else:  
          raise AttributeError,"No attribute %s."%name  
   
    #  
    #    submodel handeling:  
    #  
    def doInitializationOfSubmodels(self):  
       """initializes the time stepping for all submodels."""  
       for i in self.__submodels: self.getParameter(i).doInitialization()  
   
    def getSafeTimeStepSizeFromSubmodels(self):  
       """returns a time step size which can savely be used by all submodels. To avoid a big increase in the step size,  
          the new step size is restricted to the double of the precious step size."""  
       out=None  
       for i in self.__submodels:  
           dt=self.getParameter(i).getSafeTimeStepSize()  
           if not dt==None:  
               if out==None:  
                  out=dt  
               else:  
                  out=min(out,dt)  
       return out  
   
    def doStepOfSubmodels(self,t):  
       """executes the time step for each submodel"""  
       for i in self.__submodels: self.getParameter(i).doStep(t)  
   
    def finalizeAllSubmodels(self):  
       """returns True if all submodels can be finalized"""  
       out=True  
       for i in self.__submodels: out = out and self.getParameter(i).finalize()  
       return out  
         
    def doFinalizationOfSubmodels(self):  
       """finalalizes the time stepping for each of the submodels."""  
       for i in self.__submodels: self.getParameter(i).doFinalization()  
   
    def doIterationInitializationOfSubmodels(self,t):  
       """initializes the iteration for each of the submodels."""  
       for i in self.__submodels: self.getParameter(i).doIterationInitialization(t)  
   
    def doIterationStepOfSubmodels(self):  
       """executes the iteration step at time step for each submodel"""  
       for i in self.__submodels: self.getParameter(i).doIterationStep()  
   
    def terminateAllSubmodels(self):  
       """returns True if all iterations for all submodels are terminated."""  
       out=True  
       for i in self.__submodels: out = out and self.getParameter(i).terminate()  
       return out  
         
    def doIterationFinalizationOfSubmodels(self):  
       """finalalizes the iteration process for each of the submodels."""  
       for i in self.__submodels: self.getParameter(i).doIterationFinalization()  
   
    def checkPointSubmodels(self):  
       """performs check pointing for each submodel"""  
       for i in self.__submodels: self.getParameter(i).checkPoint()  
   
    #  
    #   these methods control the time stepping  
    #    
    def doInitialization(self):  
       """initializes the time stepping"""  
       self.doInitializationOfSubmodels()  
   
    def getSafeTimeStepSize(self):  
       """returns a time step size which can savely be used"""  
       return self.getSafeTimeStepSizeFromSubmodels()  
   
    def doStep(self,t):  
       """executes the time step by first iterating over time step t and then step forward"""  
       # run iteration on simulation until terminated:  
       self.doIterationInitialization(t)  
       while not self.terminate(): self.doIterationStep()  
       self.doIterationFinalization()  
       self.doStepOfSubmodels(t)  
   
    def finalize(self):  
       """returns True if all submodels are to be finalized"""  
       return self.finalizeAllSubmodels()  
         
    def doFinalization(self):  
       """finalizes the time stepping."""  
       self.doFinalizationOfSubmodels()  
    #  
    #   methods deal with iterations:  
    #  
    def doIterationInitialization(self,t):  
       """initializes the iteration on a time step"""  
       self.__iter=0  
       if self.debug(): print "%s: iteration starts"%self  
       self.doIterationInitializationOfSubmodels(t)  
   
    def doIterationStep(self):  
       """executes the iteration step"""  
       self.__iter+=1  
       if self.debug(): print "%s: iteration step %d"%(self,self.__iter)  
       try:  
          self.doIterationStepOfSubmodels()  
       except IterationDivergenceError,e:  
          raise IterationDivergenceError("divergence at time step %s in iteration step %s by reason: \n%s."%(self.__n,self.__iter,e.value))  
   
    def terminate(self):  
       """returns True if time steping is terminated"""  
       return self.terminateAllSubmodels()  
         
    def doIterationFinalization(self):  
       """finalalizes the iteration process."""  
       self.doIterationFinalizationOfSubmodels()  
       if self.debug(): print "%s: iteration finalized after %s step"%(self,self.__iter)  
    #  
    #   sum other method:  
    #  
    def checkPoint(self):  
       """performs check pointing for each submodel"""  
       if not self.__check_pointing==None:  
          if self.__n%self.__check_pointing==0: self.checkPointsSubmodels()  
   
    def run(self):  
       """After check_pointing time steps the model will start to create checkpoint files for each of the submodels"""  
       self.__tn=0.  
       self.__n=0  
       self.__dt=None  
       self.doInitialization()  
       while not self.finalize():  
          self.__n+=1  
          self.__dt=self.getSafeTimeStepSize()  
          if self.__dt==None: self.__dt=self.UNDEF_DT  
          if self.debug(): print "%s: %d. time step %e (step size %e.)"%(self,self.__n,self.__tn+self.__dt,self.__dt)  
          endoftimestep=False  
          while not endoftimestep:  
               endoftimestep=True  
               try:  
                  self.doStep(self.__tn+self.__dt)  
               except FailedTimeStepError:  
                  self.__dt=self.getSafeTimeStepSize()  
                  if self.__dt==None: self.__dt=self.UNDEF_DT  
                  endoftimestep=False  
                  if self.debug(): print "%s: time step is repeated with new step size %e."%(self,self.__dt)  
               except IterationDivergenceError:  
                  self.__dt*=0.5  
                  endoftimestep=False  
                  if self.debug(): print "%s: iteration failes. time step is repeated with new step size %e."%(self,self.__dt)  
          self.checkPoint()  
          self.__tn+=self.__dt  
       self.doFinalization()  
900    
901  class IterationDivergenceError(Exception):  class IterationDivergenceError(Exception):
902      """excpetion which should be thrown if an iteration at a time step fails"""      """
903        Exception which is thrown if there is no convergence of the iteration
904        process at a time step.
905    
906        But there is a chance that a smaller step could help to reach convergence.
907        """
908      pass      pass
909    
910  class FailedTimeStepError(Exception):  class FailedTimeStepError(Exception):
911      """excpetion which should be thrown if the time step fails because of a step size that have been choosen to be to large"""      """
912        Exception which is thrown if the time step fails because of a step
913        size that have been choosen to be too large.
914        """
915      pass      pass
916    
917  class IllegalParameterError(Exception):  class SimulationBreakDownError(Exception):
918      """excpetion which is thrown if model has not the desired parameter"""      """
919        Exception which is thrown if the simulation does not manage to
920        progress in time.
921        """
922      pass      pass
923    
924    class NonPositiveStepSizeError(Exception):
925        """
926        Exception which is thrown if the step size is not positive.
927        """
928        pass
929    
930  if __name__=="__main__":  # vim: expandtab shiftwidth=4:
    class Messenger(Model):  
       def __init__(self):  
          Model.__init__(self,parameters={"message" : "none" },name="messenger")  
   
       def doInitialization(self):  
          print "I start talking now!"  
   
       def doStep(self,t):  
          print "Message (time %e) : %s "%(t,self.message)  
   
       def doFinalization(self):  
          print "I have no more to say!"  
     
    # explicit scheme  
    class  Ode1(Model):  
       def __init__(self,**args):  
            Model.__init__(self,parameters={"tend" : 1., "dt" : 0.0001 ,"a" : 0.1 ,"u" : 1. , "message" : "none" },name="Ode1",debug=True)  
   
       def doInitialization(self):  
            self._tn=0  
   
       def doStep(self,t):  
            self.u=self.u+(t-self._tn)*self.a*self.u**2  
            self._tn=t  
   
       def doFinalization(self):  
            self.message="current error = %e"%abs(self.u-1./(1./3.-self.a*self._tn))  
            print self.message  
   
       def getSafeTimeStepSize(self):  
            return self.dt  
   
       def finalize(self):  
            return self._tn>=self.tend  
    # explicit scheme  
    class  Ode2(Model):  
   
        def __init__(self,**args):  
            Model.__init__(self,parameters={"tend" : 1., "dt" : 0.0001 ,"a" : 0.1 ,"u" : 10000. },name="Ode2",debug=True)  
            self.declareParameter(tol=1.e-8,message="none")  
             
   
        def doInitialization(self):  
            self._tn=0  
            self._iter=0  
   
        def doIterationInitialization(self,t):  
             self._iter=0  
             self._u_last=self.u              
             self._dt=t-self._tn  
             self._tn=t  
   
        def doIterationStep(self):  
           self._iter+=1  
           self._u_old=self.u  
           self.u=(self._dt*self.a*self.u**2-self._u_last)/(2*self._dt*self.a*self.u-1.)  
   
        def terminate(self):  
           if self._iter<1:  
               return False  
           else:  
              return abs(self._u_old-self.u)<self.tol*abs(self.u)  
   
        def doIterationFinalization(self):  
            self.message="current error = %e"%abs(self.u-1./(1-self.a*self._tn))  
            print self.message  
   
        def getSafeTimeStepSize(self):  
            return self.dt  
   
        def finalize(self):  
             return self._tn>=self.tend  
   
    # a simple model with paramemter tend, dt, p1, p2, and p3  
    class Test1(Model):  
   
        def __init__(self,**args):  
            Model.__init__(self,{"tend" : 1., "dt" : 0.1 ,"p1" : 0 ,"p2" : 0 ,"p3" : 0 },"test","bla",None,True)  
            self.setParameters(args)  
   
        def doInitialization(self):  
            self.__tn=0  
            self.__n=0  
   
        def doStep(self,t):  
            self.p3=self.p1+t*self.p2  
            self.__tn=t  
            print "test1 set the value out1 to ",self.p3  
   
        def doFinalization(self):  
            pass  
   
        def getSafeTimeStepSize(self):  
            return self.dt  
   
        def finalize(self):  
             return self._tn>self.tend  
   
   
    class Test2(Model):  
   
        def __init__(self):  
            Model.__init__(self,{"q1": None},"test2","",None,True)  
   
   
        def doInitialization(self):  
            print "the whole thing starts"  
   
        def doStep(self,t):  
            print "test2 things that out1 is now ",self.out1  
   
        def doFinalization(self):  
            print "all done"  
   
        def finalize(self):  
             return True  
   
    class Test12(Model):  
      """model build from two models in a transperent way"""  
      def __init__(self):  
          Model.__init__(self,{"sm1": None, a : 0, "sm2": None},"test2","",None,True)  
          self.setExecutionOrder(["sm2","sm1"])  
   
    # test messenger  
    m=Messenger()  
    m.run()  
    # ode1        
    o=Ode1()  
    o.dt=0.001  
    o.u=3.  
    o.run()  
    # ode1  
    o=Ode2()  
    o.dt=0.01  
    o.a=0.1  
    o.u=1.  
    o.run()  
    # and they are linked together:  
    o=Ode2()  
    m=Messenger()  
    om=Model(submodels=[o,m],debug=True)  
    om.dt=0.01  
    om.u=1.  
    m.message=Link(o)  
    om.run()  
    print om.showParameters()  
    1/0  
   
    t=Test1()  
    t.tend=1.  
    t.dt=0.25  
    t.in1=1.  
    t.in2=3.  
    t.run()  
    # and a coupled problem:  
    t2=Test2()  
    t2.out1=Link(t)  
    Model([t,t2],debug=True).run()  

Legend:
Removed from v.121  
changed lines
  Added in v.266

  ViewVC Help
Powered by ViewVC 1.1.26