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

  ViewVC Help
Powered by ViewVC 1.1.26