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

  ViewVC Help
Powered by ViewVC 1.1.26