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

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

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

revision 122 by jgs, Thu Jun 9 05:38:05 2005 UTC revision 147 by jgs, Fri Aug 12 01:45:47 2005 UTC
# Line 2  Line 2 
2    
3  from types import StringType,IntType,FloatType,BooleanType,ListType,DictType  from types import StringType,IntType,FloatType,BooleanType,ListType,DictType
4  from sys import stdout  from sys import stdout
5    import itertools
6    # import modellib  temporarily removed!!!
7    
8  from xml.dom import minidom  # import the 'set' module if it's not defined (python2.3/2.4 difference)
9    try:
10        set
11    except NameError:
12        from sets import Set as set
13    
14  _HEADER_START="<?xml version=\"1.0\"?><ESyS>\n"  from xml.dom import minidom
 _HEADER_END="<\ESyS>\n"  
15    
16  def dataNode(document, tagName, data):  def dataNode(document, tagName, data):
17      t = document.createTextNode(str(data))      """
18      n = document.createElement(tagName)      dataNodes are the building blocks of the xml documents constructed in
19      n.appendChild(t)      this module. document is the current xml document, tagName is the
20      return n      associated xml tag, and data is the values in the tag.
21        """
22        t = document.createTextNode(str(data))
23        n = document.createElement(tagName)
24        n.appendChild(t)
25        return n
26    
27  def esysDoc():  def esysDoc():
28      doc = minidom.Document()      """
29      esys = doc.createElement('ESys')      Global method for creating an instance of an EsysXML document.
30      doc.appendChild(esys)      """
31      return doc, esys      doc = minidom.Document()
32        esys = doc.createElement('ESys')
33        doc.appendChild(esys)
34        return doc, esys
35    
36    def all(seq):
37        for x in seq:
38            if not x:
39                return False
40        return True
41    
42    def any(seq):
43        for x in seq:
44            if x:
45                return True
46        return False
47    
48    LinkableObjectRegistry = {}
49    
50    def registerLinkableObject(obj_id, o):
51        LinkableObjectRegistry[obj_id] = o
52    
53    LinkRegistry = []
54    
55    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                if node.tagName == 'Simulation':
81                    if node.getAttribute("type") == 'Simulation':
82                        return Simulation.fromDom(node)
83                if node.tagName == 'Model':
84                    model_type = node.getAttribute("type")
85                    model_subclasses = Model.__subclasses__()
86                    for model in model_subclasses:
87                        if model_type == model.__name__:
88                            return Model.fromDom(node)
89                if node.tagName == 'ParameterSet':
90                    parameter_type = node.getAttribute("type")
91                    return ParameterSet.fromDom(node)
92                raise "Invalid simulation type, %r" % node.getAttribute("type")
93            
94    
95  class Link:      raise ValueError("No Simulation Found")
96      """              
     a Link makes an attribute of an object callable:  
           o.object()  
           o.a=8  
           l=Link(o,"a")  
           assert l()==8  
      """  
       
     def __init__(self,target=None,attribute=None):  
         """creates a link to the object target. If attribute is given, the link is  
         establised to this attribute of the target.  Otherwise the attribute is  
         undefined."""  
         self.__target=target  
         self.setAttributeName(attribute)  
       
     def setAttributeName(self,name):  
         """set a new attribute name to be collected from the target object. The  
         target object must have the attribute with name name."""  
         if not name==None:  
             if not hasattr(self.__target,name):  
                 raise AttributeError("%s: target %s has no attribute %s."%(self,self.__target,name))  
         self.__attribute=name  
       
     def hasDefinedAttributeName(self):  
         """returns true if an attribute name is set"""  
         if self.__attribute==None:  
             return False  
         else:  
             return True  
       
     def __str__(self):  
         """returns a string representation of the link"""  
         if self.hasDefinedAttributeName():  
             return "reference to attribute %s of %s"%(self.__attribute,self.__target)  
         else:  
             return "reference to target %s"%self.__target  
       
     def __call__(self,name=None):  
         """returns the value of the attribute of the target object. If the  
         atrribute is callable then the return value of the call is returned."""  
         if not name == None:  
             out=getattr(self.__target, name)  
         else:  
             out=getattr(self.__target, self.__attribute)  
         if callable(out):  
             return out()  
         else:  
             return out  
   
     def toDom(self, document, node):  
         """ toDom method of Link. Creates a Link node and appends it to the current XML  
         document """  
         link = document.createElement('link')  
         link.appendChild(dataNode(document, 'target', id(self.__target)))  
         link.appendChild(dataNode(document, 'attribute', self.__attribute))  
         node.appendChild(link)  
       
     def writeXML(self,ostream=stdout):  
         """writes an XML representation of self to the output stream ostream.  
         If ostream is nor present the standart output stream is used.  If  
         esysheader==True the esys XML header is written"""  
97    
98          document, rootnode = esysDoc()  class Link:
99          self.toDom(document, rootnode)      """
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())          ostream.write(document.toprettyxml())
195    
196  class LinkableObject(object):  class LinkableObject(object):
197      """an object that allows to link its attributes to attributes of other      """
198      objects via a Link object. For instance      An object that allows to link its attributes to attributes of other objects
199                  via a Link object. For instance
200             p=LinkableObject()            
201             p.x=Link(o,"name")             p = LinkableObject()
202             print p.x             p.x = Link(o,"name")
203                   print p.x
204          links attribute x of p to the attribute name of object o. p.x will print      
205          the current value of attribute name of object o.  if the value is      links attribute x of p to the attribute name of object o.
206          callable p.x will rturn the return value of the call.  
207      """      p.x will contain the current value of attribute name of object o.  
208        
209      def __init__(self,debug=False):      If the value of getattr(o, "name") is callable, p.x will rturn the return
210          """initiates a model from a list of subsimulations. """      value of the call.
211          self.setDebug(debug)      """
212          self.__linked_attributes={}    
213      #      number_sequence = itertools.count(100)
214      # some basic fuctions:      
215      #      def __init__(self, debug=False):
216      def debugOn(self):          """ initializes LinkableObject so that we can operate on Links """
217          """sets debugging to on"""          self.debug = debug
218          self.__debug=True          self.__linked_attributes={}
219      def debugOff(self):          self.id = self.number_sequence.next()
220          """sets debugging to off"""  
221          self.__debug=False      def trace(self, msg):
222      def debug(self):          """ If debugging is on, print the message, otherwise do nothing
223          """returns True if debug mode is set to on"""          """
224          return self.__debug          if self.debug:
225      def setDebug(self,flag=False):              print "%s: %s"%(str(self),msg)
226          """sets debugging to flag"""      
227          if flag:      def __getattr__(self,name):
228              self.debugOn()          """returns the value of attribute name. If the value is a Link object the
229          else:          object is called and the return value is returned."""
230              self.debugOff()          out = self.getAttributeObject(name)
231            if isinstance(out,Link):
232      def trace(self, msg):              return out()
233          if self.__debug:          else:
234              print msg              return out
235            
236      def __getattr__(self,name):      def getAttributeObject(self,name):
237          """returns the value of attribute name. If the value is a Link object the          """return the object stored for attribute name."""
238          object is called and the return value is returned."""  
239          out=self.getAttributeObject(name)          if self.__dict__.has_key(name):
240          if isinstance(out,Link):              return self.__dict__[name]
241              return out()  
242          else:          if self.__linked_attributes.has_key(name):
243              return out              return self.__linked_attributes[name]
244        
245      def getAttributeObject(self,name):          if self.__class__.__dict__.has_key(name):
246          """return the object stored for attribute name."""              return self.__class.__dict__[name]
247          if self.__dict__.has_key(name):  
248              out=self.__dict__[name]          raise AttributeError,"No attribute %s."%name
249          elif self.__linked_attributes.has_key(name):      
250              out=self.__linked_attributes[name]      def hasAttribute(self,name):
251          else:          """returns True if self as attribute name"""
252              raise AttributeError,"No attribute %s."%name          return self.__dict__.has_key(name) or self.__linked_attributes.has_key(name) or  self.__class__.__dict__.has_key(name)
253          return out  
254            def __setattr__(self,name,value):
255      def __setattr__(self,name,value):          """sets the value for attribute name. If value is a Link the target
256          """sets the value for attribute name. If value is a Link the target          attribute is set to name if no attribute has been specified."""
257          attribute is set to name if no attribute has been specified."""  
258          if self.__dict__.has_key(name):  
259              del self.__dict__[name]          if self.__dict__.has_key(name):
260          if isinstance(value,Link):              del self.__dict__[name]
261             if not value.hasDefinedAttributeName():  
262                 value.setAttributeName(name)          if isinstance(value,Link):
263             self.__linked_attributes[name]=value              if not value.hasDefinedAttributeName():
264             if self.debug():                  value.setAttributeName(name)
265                 print "DEBUG: %s: attribute %s is now linked by %s."%(self,name,value)              self.__linked_attributes[name] = value
266          else:  
267             self.__dict__[name]=value              self.trace("attribute %s is now linked by %s."%(name,value))
268                else:
269      def __delattr__(self,name):              self.__dict__[name] = value
270          """removes the attribute name."""      
271          if self.__linked_attributes.has_key[name]:      def __delattr__(self,name):
272              del self.__linked_attributes[name]          """removes the attribute name."""
273          elif self.__dict__.has_key(name):  
274              del self.__dict__[name]          if self.__linked_attributes.has_key[name]:
275          else:              del self.__linked_attributes[name]
276              raise AttributeError,"No attribute %s."%name          elif self.__dict__.has_key(name):
277                del self.__dict__[name]
278  class SimulationFrame(LinkableObject):          else:
279      """A SimulationFrame objects represents a processess marching over time              raise AttributeError,"No attribute %s."%name
     until a finalizing condition is fullfilled.  At each time step an iterative  
     process can be performed and the time step size can be controlled  
     """  
     UNDEF_DT=1.e300  
     MAX_TIME_STEP_REDUCTION=20  
     MAX_ITER_STEPS=50  
       
     def __init__(self,debug=False):  
         """initiates a simulation"""  
         LinkableObject.__init__(self,debug)  
       
     def doInitialization(self,t):  
         """initializes the time stepping scheme. This function may be  
         overwritten."""  
         pass  
       
     def getSafeTimeStepSize(self,dt):  
         """returns a time step size which can savely be used. This function may  
         be overwritten."""  
         return self.UNDEF_DT  
       
     def finalize(self):  
         """returns True if the time stepping is finalized. This function may be  
         overwritten."""  
         return True  
         
     def doFinalization(self):  
         """finalizes the time stepping.  This function may be overwritten."""  
         pass  
       
     def doIterationInitialization(self,dt):  
         """initializes the iteration at time step t. This function may be  
         overwritten. (only called if doStep is not overwritten)"""  
         pass  
       
     def doIterationStep(self,dt):  
         """executes the iteration step. This function may be overwritten. (only  
         called if doStep is not overwritten)"""  
         pass  
       
     def terminate(self):  
         """returns True if iteration on a time step is terminated. (only called  
         if doStep is not overwritten)"""  
         return True  
         
     def doIterationFinalization(self,dt):  
         """finalalizes the iteration process. (only called if doStep is not  
         overwritten)"""  
         pass  
       
     def run(self,check_point=None):  
         """run the simulation by performing essentially  
       
             self.doInitialization()  
             while not self.finalize():  
                dt=self.getSafeTimeStepSize()  
                self.doStep(dt)  
                if n%check_point==0: self.writeXML()  
             self.doFinalization()  
       
         """  
         self.__tn=0.  
         self.__n=0  
         self.__dt=None  
         self.doInitialization(self.__tn)  
         while not self.finalize():  
             self.__n+=1  
             self.__dt=self.getSafeTimeStepSize(self.__dt)  
             if self.__dt==None: self.__dt=self.UNDEF_DT  
             if not self.__dt>0:  
                  raise NonPositiveStepSizeError("non-positive step size in step %d",self.__n)  
             if self.debug(): print "%s: %d. time step %e (step size %e.)"%(self,self.__n,self.__tn+self.__dt,self.__dt)  
             endoftimestep=False  
             failcounter=0  
             while not endoftimestep:  
                 endoftimestep=True  
                 try:  
                     self.doStep(self.__dt)  
                 except FailedTimeStepError:  
                     self.__dt=self.getSafeTimeStepSize(self.__dt)  
                     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  
                     failcounter+=1  
                     if failcounter>self.MAX_TIME_STEP_REDUCTION:  
                         raise IterationBreakDownError("reduction of time step to achieve convergence failed.")  
   
                     self.trace("%s: iteration failes. time step is repeated with new step size %e."  
                         % (self,self.__dt))  
             self.__tn+=self.__dt  
             if not check_point==None:  
                 if self.__n%check_point==0:  
                     self.trace("%s: check point is created."%self)  
                     self.writeXML()  
         self.doFinalization()  
   
     def writeXML(self):  
         raise RuntimeError, "Not implemented"  
       
     def doStep(self,dt):  
         """executes a time step by iteration. This function may be overwritten.  
             
            basicly it performs :  
       
             self.doIterationInitialization(dt)  
             while not self.terminate(): self.doIterationStep(dt)  
             self.doIterationFinalization(dt)  
       
         """  
         self.doIterationInitialization(dt)  
         self.__iter=0  
         while not self.terminate():  
             if self.debug(): print "%s: iteration step %d"%(self,self.__iter)  
             self.doIterationStep(dt)  
             self.__iter+=1  
             if self.__iter>self.MAX_ITER_STEPS:  
                 raise IterationDivergenceError("%s: divergence in step %d"%(self,self.__iter))  
         self.doIterationFinalization(dt)  
   
 class Simulation(SimulationFrame):  
     """A Simulation object is comprised by SimulationFrame(s) called subsimulations."""  
       
     def __init__(self,subsimulations=[],debug=False):  
         """initiates a simulation from a list of subsimulations. """  
         SimulationFrame.__init__(self,debug)  
         self.__subsimulations=[]  
         for i in range(len(subsimulations)): self[i]=subsimulations[i]  
       
     def iterSubsimulations(self):  
         """returns an iterator over the subsimulations"""  
         return self.__subsimulations  
       
     def __getitem__(self,i):  
         """returns the i-th subsimulation"""  
         return self.__subsimulations[i]  
       
     def __setitem__(self,i,value):  
         """sets the i-th subsimulation"""  
         if not isinstance(value,SimulationFrame):  
             raise ValueError("assigned value is not a Simulation")  
         for j in range(max(i-len(self.__subsimulations)+1,0)): self.__subsimulations.append(None)  
         self.__subsimulations[i]=value  
       
     def __len__(self):  
         """returns the number of subsimulations"""  
         return len(self.__subsimulations)  
   
     def toDom(self, document, node):  
         """ toDom method of Simualtion class """  
         simulation = document.createElement('Simulation')  
         simulation.setAttribute('type', self.__class__.__name__)  
   
         for rank, sim in enumerate(self.iterSubsimulations()):  
             component = document.createElement('Component')  
             component.setAttribute('rank', str(rank))  
   
             sim.toDom(document, component)  
   
             simulation.appendChild(component)  
   
         node.appendChild(simulation)  
   
     def writeXML(self,ostream=stdout):  
         """writes the object as an XML object into an output stream"""  
         document, rootnode = esysDoc()  
         self.toDom(document, rootnode)  
         ostream.write(document.toprettyxml())  
       
     def getSafeTimeStepSize(self,dt):  
         """returns a time step size which can savely be used by all subsimulations"""  
         out=self.UNDEF_DT  
         for i in self.iterSubsimulations():  
             dt_new=i.getSafeTimeStepSize(dt)  
             if dt_new!=None: out=min(out,dt_new)  
         return out  
       
     def doInitialization(self,dt):  
         """initializes all subsimulations """  
         for i in self.iterSubsimulations(): i.doInitialization(dt)  
       
     def finalize(self):  
         """returns True if all subsimulations are finalized"""  
         out=True  
         for i in self.iterSubsimulations(): out = out and i.finalize()  
         return out  
         
     def doFinalization(self):  
         """finalalizes the time stepping for all subsimulations."""  
         for i in self.iterSubsimulations(): i.doFinalization()  
       
     def doIterationInitialization(self,dt):  
         """initializes the iteration at time t for all subsimulations."""  
         self.__iter=0  
         if self.debug(): print "%s: iteration starts"%self  
         for i in self.iterSubsimulations(): i.doIterationInitialization(dt)  
       
     def terminate(self):  
         """returns True if all iterations for all subsimulations are terminated."""  
         out=True  
         for i in self.iterSubsimulations(): out = out and i.terminate()  
         return out  
         
     def doIterationFinalization(self,dt):  
         """finalalizes the iteration process for each of the subsimulations."""  
         for i in self.iterSubsimulations(): i.doIterationFinalization(dt)  
         if self.debug(): print "%s: iteration finalized after %s steps"%(self,self.__iter+1)  
       
     def doIterationStep(self,dt):  
         """executes the iteration step at time step for each subsimulation"""  
         self.__iter+=1  
         if self.debug(): print "%s: iteration step %d"%(self,self.__iter)  
         for i in self.iterSubsimulations(): i.doIterationStep(dt)  
   
 class ExplicitSimulation(Simulation):  
     """This is a modified form of the Simulation class. In fact it overwrites  
     the doStep method by executing the doStep method of all subsimulations  
     rather then iterating over all subsimulations."""  
   
     def doStep(self,dt):  
         """executes the time step for all subsimulation"""  
         for i in self.iterSubsimulations(): i.doStep(dt)  
280    
281  class _ParameterIterator:  class _ParameterIterator:
282      def __init__(self,parameterset):      def __init__(self,parameterset):
         self.__set=parameterset  
         self.__iter=iter(parameterset.getParameterList())  
     def next(self):  
         o=self.__iter.next()  
         return (o,self.__set.getAttributeObject(o))  
     def __iter__(self):  
         return self  
   
 class ParameterSet(LinkableObject):  
     """a class which allows to emphazise attributes to be written and read to XML  
         
        Leaves of  an ESySParameters objects can be  
       
             a real number  
             a integer number  
             a string  
             a boolean value  
             a ParameterSet object  
             a Simulation object  
             a Model object  
             any other object (not considered by writeESySXML and writeXML)  
       
            Example how to create an ESySParameters object:  
       
                  p11=ParameterSet(gamma1=1.,gamma2=2.,gamma3=3.)  
                  p1=ParameterSet(dim=2,tol_v=0.001,output_file="/tmp/u.%3.3d.dx",runFlag=True,parm11=p11)  
                  parm=ParameterSet(parm1=p1,parm2=ParameterSet(alpha=Link(p11,"gamma1")))  
       
            This can be accessed as  
       
                  parm.parm1.gamma=0.  
                  parm.parm1.dim=2  
                  parm.parm1.tol_v=0.001  
                  parm.parm1.output_file="/tmp/u.%3.3d.dx"  
                  parm.parm1.runFlag=True  
                  parm.parm1.parm11.gamma1=1.  
                  parm.parm1.parm11.gamma2=2.  
                  parm.parm1.parm11.gamma3=3.  
                  parm.parm2.alpha=1. (value of parm.parm1.parm11.gamma1)  
               
     """  
     def __init__(self,parameters=[]):  
         """creates a ParameterSet with parameters parameters"""  
         LinkableObject.__init__(self,debug=False)  
         self.__parameters=[]  
         self.declareParameters(parameters)  
       
     def getParameterList(self):  
         """returns the list of parameters"""  
         return self.__parameters  
       
     def isParameter(self,name):  
         """returns true if name is a parameter"""  
         return name in self.getParameterList()  
       
     def declareParameter(self,**parameters):  
         """declares a new parameter(s) and its (their) inital value."""  
         self.declareParameters(parameters)  
       
     def declareParameters(self,parameters):  
         """declares a set of parameters. parameters can be a list, a dictonary or a ParameterSet."""  
         if isinstance(parameters,ListType):  
             for prm in parameters:  
                 setattr(self,prm,None)  
                 if not self.isParameter(prm): self.getParameterList().append(prm)  
                 if self.debug(): print "%s: parameter %s has been declared."%(self,prm)  
         elif isinstance(parameters,DictType):  
             for prm,value in parameters.iteritems():  
                 setattr(self,prm,value)  
                 if not self.isParameter(prm): self.getParameterList().append(prm)    
                 if self.debug(): print "%s: parameter %s has been declared."%(self,prm)  
         else:  
             for prm,value in parameters:  
                 setattr(self,prm,value)  
                 if not self.isParameter(prm): self.getParameterList().append(prm)    
                 if self.debug(): print "%s: parameter %s has been declared."%(self,prm)  
       
     def releaseParameters(self,name):  
         """removes parameter name from the paramameters"""  
         if self.isParameter(name):  
             self.getParameterList().remove(name)  
             if self.debug(): print "%s: parameter %s has been removed."%(self,prm)  
       
     def __iter__(self):  
         """creates an iterator over the parameter and their values"""  
         return _ParameterIterator(self)  
       
     def showParameters(self):  
         """returns a descrition of the parameters"""          
         out="{"  
         notfirst=False  
         for i,v in self:  
             if notfirst: out=out+","  
             notfirst=True  
             if isinstance(v,ParameterSet):  
                 out="%s\"%s\" : %s"%(out,i,v.showParameters())  
             else:  
                 out="%s\"%s\" : %s"%(out,i,v)  
         return out+"}"  
       
     def __delattr__(self,name):  
         """removes the attribute name."""  
         LinkableObject.__delattr__(self,name)  
         try:  
             self.releaseParameter(name)  
         except:  
             pass  
   
     def toDom(self, document, node):  
         """ toDom method of ParameterSet class """  
         pset = document.createElement('ParameterSet')  
         node.appendChild(pset)  
         self._parametersToDom(document, pset)  
   
     def _parametersToDom(self, document, node):  
         for name,value in self:  
             param = document.createElement('Parameter')  
             param.setAttribute('type', value.__class__.__name__)  
   
             param.appendChild(dataNode(document, 'Name', name))  
   
             val = document.createElement('Value')  
   
             if isinstance(value,ParameterSet):  
                 value.toDom(document, val)  
             elif isinstance(value, Link):  
                 value.toDom(document, val)  
                 param.appendChild(val)  
             elif isinstance(value,StringType):  
                 param.appendChild(dataNode(document, 'Value', value))  
             else:  
                 param.appendChild(dataNode(document, 'Value', str(value)))  
   
             node.appendChild(param)  
       
     def writeXML(self,ostream=stdout):  
         """writes the object as an XML object into an output stream"""  
         # ParameterSet(d) with d[Name]=Value  
         document, node = esysDoc()  
         self.toDom(document, node)  
         ostream.write(document.toprettyxml())  
   
 class Model(ParameterSet,SimulationFrame):  
     """a Model is a SimulationFrame which is also a ParameterSet."""  
   
     def __init__(self,debug=False):  
         """creates a model"""  
         ParameterSet.__init__(self)  
         SimulationFrame.__init__(self,debug=debug)  
   
     def writeXML(self,ostream=stdout,esysheader=True,modelheader=True):  
         """writes the object as an XML object into an output stream"""  
         # x=type() with x.Name=Value where type is a Model from the model library.  
         if esysheader: ostream.write(_HEADER_START)      
         ostream.write("<Model type=\"%s\" module=\"%s\">\n"%(self.__class__.__name__,self.__class__.__module__))  
         self. writeParameterXML(ostream)        
         ostream.write("</Model>\n")  
         if esysheader: ostream.write(_HEADER_END)  
   
 class IterationDivergenceError(Exception):  
     """excpetion which should be thrown if there is no convergence of the iteration process at a time step but there is a chance taht a smaller step could help  
        to reach convergence."""  
     pass  
   
 class IterationBreakDownError(Exception):  
     """excpetion which should be thrown if there is no conevregence and there is no chance that a time step reduction would help"""  
     pass  
   
 class FailedTimeStepError(Exception):  
     """excpetion which should be thrown if the time step fails because of a step size that have been choosen to be to large"""  
     pass  
   
 class NonPositiveStepSizeError(Exception):  
     """excpetion which is thrown if the step size is not positive"""  
     pass  
   
 #  
 #   ignore this text:  
 #  
 """ the Model class provides a framework to run a time-dependent simulation. A  
 Model has a set of parameter which may be fixed or altered by the Model itself  
 or other Models over time.    
   
        The parameters of a models are declared at instantion, e.g.  
   
            m=Model({"message" : "none" })  
283    
284         creates a Model with parameters p1 and p2 with inital values 1 and 2.          self.__set=parameterset
285         Typically a particular model is defined as a subclass of Model:          self.__iter=iter(parameterset.parameters)
286    
287          class Messenger(Model):      def next(self):
288              def __init__(self):          o=self.__iter.next()
289                 Model.__init__(self,parameters={"message" : "none" })          return (o,self.__set.getAttributeObject(o))
290    
291          m=MyModel()      def __iter__(self):
292            return self
293    
294         There are various ways how model parameters can be changed:  class ParameterSet(LinkableObject):
295        """a class which allows to emphazise attributes to be written and read to XML
296         1) use object attributes:        
297           Leaves of  an ESySParameters objects can be
298            m.message="Hello World!"      
299                a real number
300         2) use setParamter method              a integer number
301                        a string
302                          a boolean value
303            m.setParameters(message="Hello World!")              a ParameterSet object
304                a Simulation object
305         3) or dictonaries              a Model object
306                  any other object (not considered by writeESySXML and writeXML)
307             d={ message : "Hello World!" }      
308             m.setParameters(**d)             Example how to create an ESySParameters object:
309        
310                     p11=ParameterSet(gamma1=1.,gamma2=2.,gamma3=3.)
311         A model executed buy staring the run method of the model:                   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                node.appendChild(param)
413    
414        def fromDom(cls, doc):
415    
416            # Define a host of helper functions to assist us.
417            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 _floatfromValue(doc):
425                return float(doc.nodeValue.strip())
426    
427            def _stringfromValue(doc):
428                return str(doc.nodeValue.strip())
429          
430            def _intfromValue(doc):
431                return int(doc.nodeValue.strip())
432    
433            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        """
576        
577        FAILED_TIME_STEPS_MAX=20
578        MAX_ITER_STEPS=50
579        
580        def __init__(self, models=[], **kwargs):
581            """initiates a simulation from a list of models. """
582            Model.__init__(self, **kwargs)
583            self.__models=[]
584    
585            for i in range(len(models)):
586                self[i] = models[i]
587    
588        def __repr__(self):
589            """
590            returns a string representation of the Simulation
591            """
592            return "<Simulation %r>" % self.__models
593    
594        def __str__(self):
595            """
596            returning Simulation as a string
597            """
598            return "<Simulation %d>"%id(self)
599        
600        def iterModels(self):
601            """returns an iterator over the models"""
602            return self.__models
603        
604        def __getitem__(self,i):
605            """returns the i-th model"""
606            return self.__models[i]
607        
608        def __setitem__(self,i,value):
609            """sets the i-th model"""
610            if not isinstance(value,Model):
611                raise ValueError("assigned value is not a Model")
612            for j in range(max(i-len(self.__models)+1,0)): self.__models.append(None)
613            self.__models[i]=value
614        
615        def __len__(self):
616            """returns the number of models"""
617            return len(self.__models)
618    
619        def toDom(self, document, node):
620            """ toDom method of Simulation class """
621            simulation = document.createElement('Simulation')
622            simulation.setAttribute('type', self.__class__.__name__)
623    
624            for rank, sim in enumerate(self.iterModels()):
625                component = document.createElement('Component')
626                component.setAttribute('rank', str(rank))
627    
628                sim.toDom(document, component)
629    
630                simulation.appendChild(component)
631    
632            node.appendChild(simulation)
633    
634        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        def doStepPostprocessing(self,dt):
674            """finalalizes the iteration process for all models."""
675            for o in self.iterModels():
676                o.doStepPostprocessing(dt)
677            self.n+=1
678            self.tn+=dt
679        
680        def doStep(self,dt):
681            """
682                 executes the iteration step at a time step for all model:
683    
684            m=Messenger()                    self.doStepPreprocessing(dt)
685            m.run()                    while not self.terminateIteration(): for all models: self.doStep(dt)
686                      self.doStepPostprocessing(dt)
687         The run methods marches through time. It first calls the  
688         doInitialization() method of the Model to set up the process. In each          """
689         time step the doStep() method is called to get from the current to the          self.iter=0
690         next time step. The step size is defined by calling the          while not self.terminateIteration():
691         getSafeTimeStepSize() method.  the time integration process is              if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt))
692         terminated when the finalize() methods return true. Final the              self.iter+=1
693         doFinalization() method is called to finalize the process. To implement              self.trace("iteration step %d"%(self.iter))
694         a particular model a subclass of the Model class is defined. The              for o in self.iterModels():
695         subclass overwrites the default methods of Model.                    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         The following class defines a messenger printing in the doStep method  
698         what ever the current value of its parameter message is:      def run(self,check_point=None):
699            """
700         class Messenger(Model):  
701              def __init__(self):             run the simulation by performing essentially
702                 Model.__init__(self,parameters={"message" : "none" })      
703                   self.doInitialization()
704              def doInitialization(self):                 while not self.finalize():
705                 print "I start talking now!"                    dt=self.getSafeTimeStepSize()
706                      self.doStep(dt)
707              def doStep(self,t):                    if n%check_point==0: self.writeXML()
708                 print "Message (time %e) : %s "%(t,self.message)                 self.doFinalization()
   
             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.  
           
        Following example for solving the ODE using a forward euler scheme:  
   
                 u(t=0)=u0  
                 u_t=a*u**2       for all 0<t<=ten  
   
       exact solution is given by u(t)=1/(1/u0-a*t)  
   
       class  Ode1(Model):  
          def __init__(self,**args):  
             Model.__init__(self,parameters={"tend" : 1., "dt" : 0.0001 ,"a" : 0.1 ,"u" : 1. },name="test",debug=True)  
   
          def doInitialization(self):  
              self._tn=0  
   
          def doStep(self,t):  
              self.u=self.u+(t-self._tn)*self.a*self.u**2  
              self._tn=t  
   
          def doFinalization(self):  
              print "all done final error = ",abs(self.u-1./(1./3.-self.a*self._tn))  
   
          def getSafeTimeStepSize(self):  
              return self.dt  
   
          def finalize(self):  
              return self._tn>=self.tend  
   
        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. ` In  
        this case the doStep() method is replaced by a sequance of methods which  
        implements this iterative process.  The method then will control the  
        iteration process by initializing the iteration through calling the  
        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.  
   
        following example is a modification of the example above. Here an  
        implicit euler scheme is used. in each time step the problem  
             
            0= u_{n+1}-u_{n}+a*dt*u_{n+1}**2  
709    
710         has to be solved for u_{n+1}. The Newton scheme is used to solve this non-linear problem.             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               In both cases the time integration is given up after Simulation.FAILED_TIME_STEPS_MAX
717        class  Ode2(Model):             attempts.
718    
719         def __init__(self,**args):      
720             Model.__init__(self,{"tend" : 1., "dt" : 0.1 ,"a" : 10. ,"u" : 1. , "tol " : 1.e-8},"test","bla",None,True)          """
721            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         def doInitialization(self):              sims.append(getComponent(node))
            self.__tn=0  
765    
766         def doIterationInitialization(self,t):          return cls(sims)
             self.__iter=0  
             self.u_last=self.u              
             self.current_dt=t-self.tn  
             self.__tn=t  
   
        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 subsimulations. Subsimulations 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  
        subsimulations in the case the model does not have this parameter  
        itself. The order in which the subsimulations are searched is critical.  
        By default a Model initializes all its subsimulations, is finalized when  
        all its subsimulations are finalized and finalizes all its  
        subsimulations. In the case an iterative process is applied on a  
        particular time step the iteration is initialized for all  
        subsimulations, then the iteration step is performed for each  
        subsimulation until all subsimulations indicate termination. Then the  
        iteration is finalized for all subsimulations. 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(subsimulations=[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  
        subsimulation. 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.  
   
        A parameter of a Model can be linked to an attribute of onother object,  
        typically an parameter of another Model object.      
         
         
        which is comprised by a set of subsimulations.  
        The simulation is run through its run method which in the simplest case has the form:  
   
           s=Model()  
           s.run()  
   
        The run has an initializion and finalization phase. The latter is called  
        if all subsimulations are to be finalized. The simulation is processing  
        in time through calling the stepForward methods which updates the  
        observables of each subsimulation.  A time steps size which is save for  
        all subsimulation is choosen.  
   
        At given time step an iterative process may be performed to make sure  
        that all observables are consistent across all subsimulations.  In this  
        case, similar the time dependence, an initialization and finalization of  
        the iteration is performed.  
   
        A Model has input and output parameters where each input parameter can  
        be constant, time dependent or may depend on an output parameter of  
        another model or the model itself. To create a parameter name of a model  
        and to assign a value to it one can use the statement  
   
            model.name=object  
   
   
        At any time the current value of the parameter name can be obtained by  
   
                value=model.name  
   
        If the object that has been assigned to the paramter/attribute name has  
        the attribute/parameter name isself the current value of this 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 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  
   
            model.setParameter(name,object,name_for_object)  
   
        links the parameter name of model with the parameter name_for_object of  
        object.  
   
        The run method initiates checkpointing (it is not clear how to do this  
        yet)  
    =====  
               
    """  
   
   
   
 if __name__=="__main__":  
     import math  
     #  
     # test for parameter set  
     #  
     p11=ParameterSet()  
     p11.declareParameter(gamma1=1.,gamma2=2.,gamma3=3.)  
     p1=ParameterSet()  
     p1.declareParameter(dim=2,tol_v=0.001,output_file="/tmp/u.%3.3d.dx",runFlag=True,parm11=p11)  
     parm=ParameterSet({ "parm1" : p1 , "parm2" : ParameterSet(["alpha"])})  
     parm.parm2.alpha=Link(p11,"gamma1")  
     parm.x="that should not be here!"  
     print parm.showParameters()  
     # should be something like: {"parm2" : {"alpha" : reference to attribute  
     # gamma1 of <__main__.ParameterSet instance at 0xf6db51cc>},"parm1" : {"dim"  
     # : 2,"runFlag" : True,"tol_v": 0.001,"parm11" : {"gamma3" : 3.0,"gamma2" :  
     # 2.0,"gamma1" : 1.0},"output_file" : /tmp/u.%3.3d.dx}}  
     assert parm.parm2.alpha==1.  
     parm.writeXML()  
       
     #=======================  
     class Messenger(Model):  
         def __init__(self):  
             Model.__init__(self)  
             self.declareParameter(message="none")  
   
         def doInitialization(self,t):  
             self.__t=t  
             print "I start talking now!"  
   
         def doStep(self,dt):  
             self.__t+=dt  
             print "Message (time %e) : %s "%(self.__t,self.message)  
767    
768          def doFinalization(self):      fromDom = classmethod(fromDom)
             print "I have no more to say!"  
     
     class ODETEST(Model):  
         """ implements a solver for the ODE  
769    
               du/dt=a*u+f(t)  
770    
771             we use a implicit euler scheme :  class IterationDivergenceError(Exception):
772        """
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                u_n-u_{n-1}= dt*a u_n + st*f(t_n)      """
777        pass
778    
779             to get u_n we run an iterative process  class FailedTimeStepError(Exception):
780        """excpetion which is thrown if the time step fails because of a step size that have been choosen to be too large"""
781                 u_{n.k}=u_{n-1}+dt*(a u_{n.i-1} + f(t_n))      pass
782    
783    class SimulationBreakDownError(Exception):
784        """excpetion which is thrown if the simulation does not manage to progress in time."""
785        pass
786    
787             input for this model are step size dt, end time tend and a value for  class NonPositiveStepSizeError(Exception):
788             a, f and initial value for u. we need also a tolerance tol for a      """excpetion which is thrown if the step size is not positive"""
789             stopping criterion.      pass
   
         """  
   
         def __init__(self):  
             Model.__init__(self,debug=True)  
             self.declareParameter(tend=1.,dt=0.1,a=0.9,u=10.,f=0.,message="",tol=1.e-8)  
   
         def doInitialization(self,t):  
             self.__tn=t  
             self.__iter=0  
             
         def doIterationInitialization(self,dt):  
             self.__iter=0  
             self.__u_last=self.u              
   
         def doIterationStep(self,dt):  
             self.__iter+=1  
             self.__u_old=self.u  
             self.u=self.__u_last+dt*(self.a*self.__u_old+self.f)  
           
         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,dt):  
             self.__tn+=dt  
             self.message="current error = %e"%abs(self.u-10.*math.exp((self.a-1.)*self.__tn))  
   
         def getSafeTimeStepSize(self,dt):  
             return min(self.dt,1./(abs(self.a)+1.))  
   
         def finalize(self):  
             return self.__tn>=self.tend  
   
     #  
     #   s solves the coupled ODE:  
     #  
     #     du/dt=a*u+  v  
     #     dv/dt=  u+a*v  
     #    
     #   each equation is treated through the ODETEST class. The equations are  
     #   linked and iteration over each time step is performed.  the current  
     #   error of v is reported by the Messenger class.  
     #  
     o1=ODETEST()  
     o1.u=10  
     o2=ODETEST()  
     o2.u=-10.  
     o1.f=Link(o2,"u")  
     o2.f=Link(o1,"u")  
     m=Messenger()  
     o1.dt=0.01  
     m.message=Link(o1)  
     s=ExplicitSimulation([Simulation([o1,o2],debug=True),m],debug=True)  
     s.run()  
     s.writeXML()  

Legend:
Removed from v.122  
changed lines
  Added in v.147

  ViewVC Help
Powered by ViewVC 1.1.26