/[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 282 by elspeth, Wed Nov 30 09:18:38 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!"  
   
             def doStep(self,t):  
                print "Message (time %e) : %s "%(t,self.message)  
81    
82              def doFinalization(self):          This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241
83                 print "I have no more to say!"      """
84              module = __import__(modulename, globals(), locals(), [name])
85         If a instance of the Messenger class is run, it will print the initialization and finalization message only.          
86         This is because the default method for finalize() does always returns True and therefore the transition is      try:
87         terminated startcht away.          return vars(module)[name]
88        except KeyError:
89            raise ImportError("Could not import %s from %s" % (name, modulename))
90    
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            node.setIdAttribute("id")
449            for name,value in self:
450                param = document.createElement('Parameter')
451                param.setAttribute('type', value.__class__.__name__)
452    
453                param.appendChild(dataNode(document, 'Name', name))
454    
455                val = document.createElement('Value')
456    
457                if isinstance(value,ParameterSet):
458                    value.toDom(document, val)
459                    param.appendChild(val)
460                elif isinstance(value, Link):
461                    value.toDom(document, val)
462                    param.appendChild(val)
463                elif isinstance(value,StringType):
464                    param.appendChild(dataNode(document, 'Value', value))
465                else:
466                    param.appendChild(dataNode(document, 'Value', str(value)))
467    
468            s=Model()              node.appendChild(param)
           s.run()  
469    
470         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.  
471    
472         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.
473         In this case, similar the time dependence, an initialization and finalization of the iteration is performed.          def _children(node):
474                """
475                Remove the empty nodes from the children of this node.
476                """
477                return [x for x in node.childNodes
478                        if not isinstance(x, minidom.Text) or x.nodeValue.strip()]
479    
480         A Model has input and output parameters where each input parameter can be constant, time dependent or may depend on an          def _floatfromValue(doc):
481         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  
482    
483             model.name=object          def _stringfromValue(doc):
484                return str(doc.nodeValue.strip())
485          
486            def _intfromValue(doc):
487                return int(doc.nodeValue.strip())
488    
489            def _boolfromValue(doc):
490                return bool(doc.nodeValue.strip())
491    
492         At any time the current value of the parameter name can be obtained by          def _nonefromValue(doc):
493                return None
494          
495            # Mapping from text types in the xml to methods used to process trees of that type
496            ptypemap = {"Simulation": Simulation.fromDom,
497                        "Model":Model.fromDom,
498                        "ParameterSet":ParameterSet.fromDom,
499                        "Link":Link.fromDom,
500                        "float":_floatfromValue,
501                        "int":_intfromValue,
502                        "str":_stringfromValue,
503                        "bool":_boolfromValue,
504                        "NoneType":_nonefromValue
505                        }
506    
507    #        print doc.toxml()
508    
509            parameters = {}
510            for node in _children(doc):
511                ptype = node.getAttribute("type")
512    
513                pname = pvalue = None
514                for childnode in _children(node):
515    
516                    if childnode.tagName == "Name":
517                        pname = childnode.firstChild.nodeValue.strip()
518    
519                    if childnode.tagName == "Value":
520                        nodes = _children(childnode)
521                        pvalue = ptypemap[ptype](nodes[0])
522    
523                parameters[pname] = pvalue
524    
525            # Create the instance of ParameterSet
526            o = cls()
527            o.declareParameters(parameters)
528            registerLinkableObject(doc.getAttribute("id"), o)
529            return o
530        
531        fromDom = classmethod(fromDom)
532        
533        def writeXML(self,ostream=stdout):
534            """
535        Writes the object as an XML object into an output stream.
536        """
537            # ParameterSet(d) with d[Name]=Value
538            document, node = esysDoc()
539            self.toDom(document, node)
540            ostream.write(document.toprettyxml())
541    
542    class Model(ParameterSet):
543        """
544        A Model object represents a processess marching over time until a
545        finalizing condition is fullfilled. At each time step an iterative
546        process can be performed and the time step size can be controlled. A
547        Model has the following work flow::
548    
549              doInitialization()
550              while not finalize():
551                   dt=getSafeTimeStepSize(dt)
552                   doStepPreprocessing(dt)
553                   while not terminateIteration(): doStep(dt)
554                   doStepPostprocessing(dt)
555              doFinalization()
556    
557        where C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
558        C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
559        C{doFinalization} are methods of the particular instance of a Model. The
560        default implementations of these methods have to be overwritten by the
561        subclass implementing a Model.
562        """
563    
564        UNDEF_DT=1.e300
565    
566        def __init__(self,parameters=[],**kwarg):
567            """
568        Creates a model.
569    
570            Just calls the parent constructor.
571            """
572            ParameterSet.__init__(self, parameters=parameters,**kwarg)
573    
574        def __str__(self):
575           return "<%s %d>"%(self.__class__,id(self))
576    
577        def toDom(self, document, node):
578            """
579        C{toDom} method of Model class
580        """
581            pset = document.createElement('Model')
582            pset.setAttribute('type', self.__class__.__name__)
583            if not self.__class__.__module__.startswith('esys.escript'):
584                pset.setAttribute('module', self.__class__.__module__)
585            node.appendChild(pset)
586            self._parametersToDom(document, pset)
587    
588        def doInitialization(self):
589            """
590        Initializes the time stepping scheme.  
591        
592        This function may be overwritten.
593        """
594            pass
595        
596        def getSafeTimeStepSize(self,dt):
597            """
598        Returns a time step size which can safely be used.
599    
600            C{dt} gives the previously used step size.
601    
602            This function may be overwritten.
603        """
604            return self.UNDEF_DT
605        
606        def finalize(self):
607            """
608        Returns False if the time stepping is finalized.
609        
610        This function may be overwritten.
611        """
612            return False
613          
614        def doFinalization(self):
615            """
616        Finalizes the time stepping.
617        
618        This function may be overwritten.
619        """
620            pass
621        
622        def doStepPreprocessing(self,dt):
623            """
624        Sets up a time step of step size dt.
625        
626        This function may be overwritten.
627        """
628            pass
629        
630        def doStep(self,dt):
631            """
632        Executes an iteration step at a time step.
633    
634            C{dt} is the currently used time step size.
635    
636            This function may be overwritten.
637        """
638            pass
639        
640        def terminateIteration(self):
641            """
642        Returns True if iteration on a time step is terminated.
643        """
644            return True
645          
646        def doStepPostprocessing(self,dt):
647            """
648        Finalalizes the time step.
649    
650            dt is the currently used time step size.
651    
652            This function may be overwritten.
653        """
654            pass
655        
656        def writeXML(self, ostream=stdout):
657            document, node = esysDoc()
658            self.toDom(document, node)
659            ostream.write(document.toprettyxml())
660        
661    
662    class Simulation(Model):
663        """
664        A Simulation object is special Model which runs a sequence of Models.
665    
666        The methods C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
667        C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
668        C{doFinalization} are executing the corresponding methods of the models in
669        the simulation.
670        """
671        
672        FAILED_TIME_STEPS_MAX=20
673        MAX_ITER_STEPS=50
674        
675        def __init__(self, models=[], **kwargs):
676            """
677        Initiates a simulation from a list of models.
678        """
679            Model.__init__(self, **kwargs)
680            self.__models=[]
681            
682            for i in range(len(models)):
683                self[i] = models[i]
684                
685    
686                 value=model.name      def __repr__(self):
687            """
688            Returns a string representation of the Simulation.
689            """
690            return "<Simulation %r>" % self.__models
691    
692        def __str__(self):
693            """
694            Returning Simulation as a string.
695            """
696            return "<Simulation %d>"%id(self)
697        
698        def iterModels(self):
699            """
700        Returns an iterator over the models.
701        """
702            return self.__models
703        
704        def __getitem__(self,i):
705            """
706        Returns the i-th model.
707        """
708            return self.__models[i]
709        
710        def __setitem__(self,i,value):
711            """
712        Sets the i-th model.
713        """
714            if not isinstance(value,Model):
715                raise ValueError("assigned value is not a Model, Model was:", i, " an instance of: ", value.__class__.__name__)
716            for j in range(max(i-len(self.__models)+1,0)):
717                self.__models.append(None)
718            self.__models[i]=value
719        
720        def __len__(self):
721            """
722        Returns the number of models.
723        """
724            return len(self.__models)
725    
726        def toDom(self, document, node):
727            """
728        C{toDom} method of Simulation class.
729        """
730            simulation = document.createElement('Simulation')
731            simulation.setAttribute('type', self.__class__.__name__)
732    
733            for rank, sim in enumerate(self.iterModels()):
734                component = document.createElement('Component')
735                component.setAttribute('rank', str(rank))
736    
737                sim.toDom(document, component)
738    
739                simulation.appendChild(component)
740    
741            node.appendChild(simulation)
742    
743        def writeXML(self,ostream=stdout):
744            """
745        Writes the object as an XML object into an output stream.
746        """
747            document, rootnode = esysDoc()
748            self.toDom(document, rootnode)
749            targetsList = document.getElementsByTagName('Target')
750            
751            for element in targetsList:
752                targetId = int(element.firstChild.nodeValue.strip())
753                if document.getElementById(str(targetId)):
754                    continue
755                targetObj = LinkableObjectRegistry[targetId]
756                targetObj.toDom(document, rootnode)
757            ostream.write(document.toprettyxml())
758        
759        def getSafeTimeStepSize(self,dt):
760            """
761        Returns a time step size which can safely be used by all models.
762    
763            This is the minimum over the time step sizes of all models.
764        """
765            out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
766            #print "%s: safe step size is %e."%(str(self),out)
767            return out
768        
769        def doInitialization(self):
770            """
771        Initializes all models.
772        """
773            self.n=0
774            self.tn=0.
775            for o in self.iterModels():
776                o.doInitialization()
777        
778        def finalize(self):
779            """
780        Returns True if any of the models is to be finalized.
781        """
782            return any([o.finalize() for o in self.iterModels()])
783          
784        def doFinalization(self):
785            """
786        Finalalizes the time stepping for all models.
787        """
788            for i in self.iterModels(): i.doFinalization()
789            self.trace("end of time integation.")
790        
791        def doStepPreprocessing(self,dt):
792            """
793        Initializes the time step for all models.
794        """
795            for o in self.iterModels():
796                o.doStepPreprocessing(dt)
797        
798        def terminateIteration(self):
799            """
800        Returns True if all iterations for all models are terminated.
801        """
802            out=all([o.terminateIteration() for o in self.iterModels()])
803            return out
804          
805        def doStepPostprocessing(self,dt):
806            """
807        Finalalizes the iteration process for all models.
808        """
809            for o in self.iterModels():
810                o.doStepPostprocessing(dt)
811            self.n+=1
812            self.tn+=dt
813        
814        def doStep(self,dt):
815            """
816        Executes the iteration step at a time step for all model::
817    
818                self.doStepPreprocessing(dt)
819                while not self.terminateIteration():
820                for all models:
821                self.doStep(dt)
822                    self.doStepPostprocessing(dt)
823            """
824            self.iter=0
825            while not self.terminateIteration():
826                if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt))
827                self.iter+=1
828                self.trace("iteration step %d"%(self.iter))
829                for o in self.iterModels():
830                      o.doStep(dt)
831            if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.n+1,self.tn+dt))
832    
833        def run(self,check_point=None):
834            """
835        Run the simulation by performing essentially::
836        
837            self.doInitialization()
838            while not self.finalize():
839                dt=self.getSafeTimeStepSize()
840                self.doStep(dt)
841                if n%check_point==0:
842                self.writeXML()
843            self.doFinalization()
844    
845            If one of the models in throws a C{FailedTimeStepError} exception a
846        new time step size is computed through getSafeTimeStepSize() and the
847        time step is repeated.
848      
849            If one of the models in throws a C{IterationDivergenceError}
850        exception the time step size is halved and the time step is repeated.
851    
852         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
853         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.
854         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          """
855            dt=self.UNDEF_DT
856            self.doInitialization()
857            while not self.finalize():
858                step_fail_counter=0
859                iteration_fail_counter=0
860                dt_new=self.getSafeTimeStepSize(dt)
861                self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))
862                end_of_step=False
863                while not end_of_step:
864                   end_of_step=True
865                   if not dt_new>0:
866                      raise NonPositiveStepSizeError("non-positive step size in step %d",self.n+1)
867                   try:
868                      self.doStepPreprocessing(dt_new)
869                      self.doStep(dt_new)
870                      self.doStepPostprocessing(dt_new)
871                   except IterationDivergenceError:
872                      dt_new*=0.5
873                      end_of_step=False
874                      iteration_fail_counter+=1
875                      if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
876                               raise SimulationBreakDownError("reduction of time step to achieve convergence failed.")
877                      self.trace("iteration fails. time step is repeated with new step size.")
878                   except FailedTimeStepError:
879                      dt_new=self.getSafeTimeStepSize(dt)
880                      end_of_step=False
881                      step_fail_counter+=1
882                      self.trace("time step is repeated.")
883                      if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
884                            raise SimulationBreakDownError("time integration is given up after %d attempts."%step_fail_counter)
885                dt=dt_new
886                if not check_point==None:
887                    if n%check_point==0:
888                        self.trace("check point is created.")
889                        self.writeXML()
890            self.doFinalization()
891    
892        def fromDom(cls, doc):
893            sims = []
894            for node in doc.childNodes:
895                if isinstance(node, minidom.Text):
896                    continue
897    
898             model.setParameter(name,object,name_for_object)              sims.append(getComponent(node))
899    
900         links the parameter name of model with the parameter name_for_object of object.          return cls(sims)
901    
902         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+")"  
903    
    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()  
904    
905  class IterationDivergenceError(Exception):  class IterationDivergenceError(Exception):
906      """excpetion which should be thrown if an iteration at a time step fails"""      """
907        Exception which is thrown if there is no convergence of the iteration
908        process at a time step.
909    
910        But there is a chance that a smaller step could help to reach convergence.
911        """
912      pass      pass
913    
914  class FailedTimeStepError(Exception):  class FailedTimeStepError(Exception):
915      """excpetion which should be thrown if the time step fails because of a step size that have been choosen to be to large"""      """
916        Exception which is thrown if the time step fails because of a step
917        size that have been choosen to be too large.
918        """
919      pass      pass
920    
921  class IllegalParameterError(Exception):  class SimulationBreakDownError(Exception):
922      """excpetion which is thrown if model has not the desired parameter"""      """
923        Exception which is thrown if the simulation does not manage to
924        progress in time.
925        """
926      pass      pass
927    
928    class NonPositiveStepSizeError(Exception):
929        """
930        Exception which is thrown if the step size is not positive.
931        """
932        pass
933    
934  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.282

  ViewVC Help
Powered by ViewVC 1.1.26