/[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

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

  ViewVC Help
Powered by ViewVC 1.1.26