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

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

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

trunk/esys2/escript/py_src/modelframe.py revision 122 by jgs, Thu Jun 9 05:38:05 2005 UTC temp/escript/py_src/modelframe.py revision 1387 by trankine, Fri Jan 11 07:45:26 2008 UTC
# Line 1  Line 1 
1    #
2  # $Id$  # $Id$
3    #
4    #######################################################
5    #
6    #           Copyright 2003-2007 by ACceSS MNRF
7    #       Copyright 2007 by University of Queensland
8    #
9    #                http://esscc.uq.edu.au
10    #        Primary Business: Queensland, Australia
11    #  Licensed under the Open Software License version 3.0
12    #     http://www.opensource.org/licenses/osl-3.0.php
13    #
14    #######################################################
15    #
16    
17    """
18    Environment for implementing models in escript
19    
20    @var __author__: name of author
21    @var __copyright__: copyrights
22    @var __license__: licence agreement
23    @var __url__: url entry point on documentation
24    @var __version__: version
25    @var __date__: date of the version
26    """
27    
28    __author__="Lutz Gross, l.gross@uq.edu.au"
29    __copyright__="""  Copyright (c) 2006 by ACcESS MNRF
30                        http://www.access.edu.au
31                    Primary Business: Queensland, Australia"""
32    __license__="""Licensed under the Open Software License version 3.0
33                 http://www.opensource.org/licenses/osl-3.0.php"""
34    __url__="http://www.iservo.edu.au/esys"
35    __version__="$Revision$"
36    __date__="$Date$"
37    
38    
39  from types import StringType,IntType,FloatType,BooleanType,ListType,DictType  from types import StringType,IntType,FloatType,BooleanType,ListType,DictType
40  from sys import stdout  from sys import stdout
41    import numarray
42    import operator
43    import itertools
44    import time
45    import os
46    
47    # import the 'set' module if it's not defined (python2.3/2.4 difference)
48    try:
49        set
50    except NameError:
51        from sets import Set as set
52    
53  from xml.dom import minidom  from xml.dom import minidom
54    
 _HEADER_START="<?xml version=\"1.0\"?><ESyS>\n"  
 _HEADER_END="<\ESyS>\n"  
   
 def dataNode(document, tagName, data):  
     t = document.createTextNode(str(data))  
     n = document.createElement(tagName)  
     n.appendChild(t)  
     return n  
   
 def esysDoc():  
     doc = minidom.Document()  
     esys = doc.createElement('ESys')  
     doc.appendChild(esys)  
     return doc, esys  
55    
56    def all(seq):
57        for x in seq:
58            if not x:
59                return False
60        return True
61    
62    def any(seq):
63        for x in seq:
64            if x:
65                return True
66        return False
67    
68    def importName(modulename, name):
69        """ Import a named object from a module in the context of this function,
70            which means you should use fully qualified module paths.
71            Return None on failure.
72    
73            This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241
74        """
75        module = __import__(modulename, globals(), locals(), [name])
76            
77        try:
78            return vars(module)[name]
79        except KeyError:
80            raise ImportError("Could not import %s from %s" % (name, modulename))
81    
82    class ESySXMLParser(object):
83        """
84        parser for ESysXML file
85        """
86        def __init__(self,xml, debug=False):
87          self.__dom = minidom.parseString(xml)
88          self.__linkable_object_registry= {}
89          self.__link_registry=  []
90          self.__esys=self.__dom.getElementsByTagName('ESys')[0]
91          self.debug=debug
92      
93        def getClassPath(self, node):
94            type = node.getAttribute("type")
95            if (node.getAttribute("module")):
96                module = node.getAttribute("module")
97                return importName(module, type)
98            else:
99                return importName("__main__", type)
100    
101        def setLinks(self):
102            for obj_id, link in self.__link_registry:
103                link.target = self.__linkable_object_registry[obj_id]
104    
105        def parse(self):
106           """
107           parser method for EsysXML and returns the list of generating ParameterSets
108           """
109           found=[]
110           for node in self.__esys.childNodes:
111               if isinstance(node, minidom.Element):
112                   if node.tagName == 'Simulation':
113                            found.append(Simulation.fromDom(self, node))
114                   elif node.tagName == 'Model':
115                            found.append(self.getClassPath(node).fromDom(self, node))
116                   elif node.tagName == 'ParameterSet':
117                            found.append(self.getClassPath(node).fromDom(self, node))
118                   else:
119                      raise "Invalid type, %r" % node.getAttribute("type")
120           self.setLinks()
121           return found
122    
123        def registerLink(self,obj_id, link):
124            self.__link_registry.append((int(obj_id),link))
125    
126        def registerLinkableObject(self,obj, node):
127            id_str=node.getAttribute('id').strip()
128            if len(id_str)>0:
129               id=int(id_str)
130               if self.__linkable_object_registry.has_key(id):
131                   raise ValueError("Object id %s already exists."%id)
132               else:
133                   self.__linkable_object_registry[id]=obj
134    
135        def getComponent(self, node):
136           """
137           returns a single component + rank from a simulation
138           parser method for EsysXML and returns the list of generating ParameterSets
139           """
140           rank  = int(node.getAttribute("rank"))
141           for n in node.childNodes:
142               if isinstance(n, minidom.Element):
143                   if n.tagName == 'Simulation':
144                            return (rank, Simulation.fromDom(self, n))
145                   elif n.tagName == 'Model':
146                            return (rank, self.getClassPath(n).fromDom(self, n))
147                   elif n.tagName == 'ParameterSet':
148                            return (rank, self.getClassPath(n).fromDom(self, n))
149                   else:
150                     raise ValueError("illegal component type %s"%n.tagName)
151           raise ValueError("cannot resolve Component")
152    
153    class ESySXMLCreator(object):
154        """
155        creates an XML Dom representation
156        """
157        def __init__(self):
158           self.__dom=minidom.Document()
159           self.__esys =self.__dom.createElement('ESys')
160           self.__dom.appendChild(self.__esys)
161           self.__linkable_object_registry={}
162           self.__number_sequence = itertools.count(100)
163        def getRoot(self):
164           return self.__esys
165        def createElement(self,name):
166          return self.__dom.createElement(name)
167        def createTextNode(self,name):
168          return self.__dom.createTextNode(name)
169        def getElementById(self,name):
170          return self.__dom.getElementById(name)
171        def createDataNode(self, tagName, data):
172              """
173              C{createDataNode}s are the building blocks of the xml documents constructed in
174              this module.  
175        
176              @param tagName: the associated xml tag
177              @param data: the values in the tag
178              """
179              n = self.createElement(tagName)
180              n.appendChild(self.createTextNode(str(data)))
181              return n
182        def getLinkableObjectId(self, obj):
183            for id, o in self.__linkable_object_registry.items():
184                if o == obj: return id
185            id =self.__number_sequence.next()
186            self.__linkable_object_registry[id]=obj
187            return id
188            
189        def registerLinkableObject(self, obj, node):
190            """
191            returns a unique object id for object obj
192            """
193            id=self.getLinkableObjectId(obj)
194            node.setAttribute('id',str(id))
195            node.setIdAttribute("id")
196    
197        def includeTargets(self):
198            target_written=True
199            while target_written:
200                targetsList =self.__dom.getElementsByTagName('Target')
201                target_written=False
202                for element in targetsList:
203                   targetId = int(element.firstChild.nodeValue.strip())
204                   if self.getElementById(str(targetId)): continue
205                   targetObj = self.__linkable_object_registry[targetId]
206                   targetObj.toDom(self, self.__esys)
207                   target_written=True
208    
209        def toprettyxml(self):
210            self.includeTargets()
211            return self.__dom.toprettyxml()
212    
213  class Link:  class Link:
214      """      """
215      a Link makes an attribute of an object callable:      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"""  
216    
217          document, rootnode = esysDoc()            o.object()
218          self.toDom(document, rootnode)            o.a=8
219              l=Link(o,"a")
220          ostream.write(document.toprettyxml())            assert l()==8
221         """
222        
223        def __init__(self,target,attribute=None):
224            """
225            Creates a link to the object target. If attribute is given, the link is
226            establised to this attribute of the target.  Otherwise the attribute is
227            undefined.
228            """
229            self.target = target
230            self.attribute = None
231            self.setAttributeName(attribute)
232    
233        def getTarget(self):
234            """
235            returns the target
236            """
237            return self.target
238        def getAttributeName(self):
239            """
240            returns the name of the attribute the link is pointing to
241            """
242            return self.attribute
243        
244        def setAttributeName(self,attribute):
245            """
246            Set a new attribute name to be collected from the target object. The
247            target object must have the attribute with name attribute.
248            """
249            if attribute and self.target:
250                if isinstance(self.target,LinkableObject):
251                   if not self.target.hasAttribute(attribute):
252                      raise AttributeError("%s: target %s has no attribute %s."%(self, self.target, attribute))
253                else:
254                   if not hasattr(self.target,attribute):
255                      raise AttributeError("%s: target %s has no attribute %s."%(self, self.target, attribute))
256            self.attribute = attribute
257        
258        def hasDefinedAttributeName(self):
259            """
260            Returns true if an attribute name is set.
261            """
262            return self.attribute != None
263        
264        def __repr__(self):
265            """
266            Returns a string representation of the link.
267            """
268            if self.hasDefinedAttributeName():
269                return "<Link to attribute %s of %s>" % (self.attribute, self.target)
270            else:
271                return "<Link to target %s>" % self.target
272        
273        def __call__(self,name=None):
274            """
275            Returns the value of the attribute of the target object. If the
276            atrribute is callable then the return value of the call is returned.
277            """
278            if name:
279                out=getattr(self.target, name)
280            else:
281                out=getattr(self.target, self.attribute)
282    
283            if callable(out):
284                return out()
285            else:
286                return out
287    
288        def toDom(self, esysxml, node):
289            """
290            C{toDom} method of Link. Creates a Link node and appends it to the
291        current XML esysxml.
292            """
293            link = esysxml.createElement('Link')
294            assert (self.target != None), ("Target was none, name was %r" % self.attribute)
295            link.appendChild(esysxml.createDataNode('Target', esysxml.getLinkableObjectId(self.target)))
296            # this use of id will not work for purposes of being able to retrieve the intended
297            # target from the xml later. I need a better unique identifier.
298            assert self.attribute, "You can't xmlify a Link without a target attribute"
299            link.appendChild(esysxml.createDataNode('Attribute', self.attribute))
300            node.appendChild(link)
301    
302        def fromDom(cls, esysxml, node):
303            targetid = int(node.getElementsByTagName("Target")[0].firstChild.nodeValue.strip())
304            attribute =str(node.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip())
305            l = cls(None, attribute)
306            esysxml.registerLink(targetid, l)
307            return l
308    
309        fromDom = classmethod(fromDom)
310        
311  class LinkableObject(object):  class LinkableObject(object):
312      """an object that allows to link its attributes to attributes of other      """
313      objects via a Link object. For instance      An object that allows to link its attributes to attributes of other objects
314                  via a Link object. For instance::
315             p=LinkableObject()            
316             p.x=Link(o,"name")             p = LinkableObject()
317             print p.x             p.x = Link(o,"name")
318                   print p.x
319          links attribute x of p to the attribute name of object o. p.x will print      
320          the current value of attribute name of object o.  if the value is      links attribute C{x} of C{p} to the attribute name of object C{o}.
321          callable p.x will rturn the return value of the call.  
322        C{p.x} will contain the current value of attribute C{name} of object
323        C{o}.  
324    
325        If the value of C{getattr(o, "name")} is callable, C{p.x} will return
326        the return value of the call.
327        """
328      
329        
330        def __init__(self, id = None, debug=False):
331            """
332        Initializes LinkableObject so that we can operate on Links
333        """
334            self.debug = debug
335            self.__linked_attributes={}
336            
337        def trace(self, msg):
338            """
339        If debugging is on, print the message, otherwise do nothing
340            """
341            if self.debug:
342                print "%s: %s"%(str(self),msg)
343        
344        def __getattr__(self,name):
345            """
346        Returns the value of attribute name. If the value is a Link object the
347            object is called and the return value is returned.
348        """
349            out = self.getAttributeObject(name)
350            if isinstance(out,Link):
351                return out()
352            else:
353                return out
354        
355        def getAttributeObject(self,name):
356            """
357        Return the object stored for attribute name.
358      """      """
       
     def __init__(self,debug=False):  
         """initiates a model from a list of subsimulations. """  
         self.setDebug(debug)  
         self.__linked_attributes={}  
     #  
     # some basic fuctions:  
     #  
     def debugOn(self):  
         """sets debugging to on"""  
         self.__debug=True  
     def debugOff(self):  
         """sets debugging to off"""  
         self.__debug=False  
     def debug(self):  
         """returns True if debug mode is set to on"""  
         return self.__debug  
     def setDebug(self,flag=False):  
         """sets debugging to flag"""  
         if flag:  
             self.debugOn()  
         else:  
             self.debugOff()  
   
     def trace(self, msg):  
         if self.__debug:  
             print msg  
       
     def __getattr__(self,name):  
         """returns the value of attribute name. If the value is a Link object the  
         object is called and the return value is returned."""  
         out=self.getAttributeObject(name)  
         if isinstance(out,Link):  
             return out()  
         else:  
             return out  
       
     def getAttributeObject(self,name):  
         """return the object stored for attribute name."""  
         if self.__dict__.has_key(name):  
             out=self.__dict__[name]  
         elif self.__linked_attributes.has_key(name):  
             out=self.__linked_attributes[name]  
         else:  
             raise AttributeError,"No attribute %s."%name  
         return out  
       
     def __setattr__(self,name,value):  
         """sets the value for attribute name. If value is a Link the target  
         attribute is set to name if no attribute has been specified."""  
         if self.__dict__.has_key(name):  
             del self.__dict__[name]  
         if isinstance(value,Link):  
            if not value.hasDefinedAttributeName():  
                value.setAttributeName(name)  
            self.__linked_attributes[name]=value  
            if self.debug():  
                print "DEBUG: %s: attribute %s is now linked by %s."%(self,name,value)  
         else:  
            self.__dict__[name]=value  
       
     def __delattr__(self,name):  
         """removes the attribute name."""  
         if self.__linked_attributes.has_key[name]:  
             del self.__linked_attributes[name]  
         elif self.__dict__.has_key(name):  
             del self.__dict__[name]  
         else:  
             raise AttributeError,"No attribute %s."%name  
   
 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,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()  
359    
360      def writeXML(self):          if self.__dict__.has_key(name):
361          raise RuntimeError, "Not implemented"              return self.__dict__[name]
       
     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)  
362    
363  class Simulation(SimulationFrame):          if self.__linked_attributes.has_key(name):
364      """A Simulation object is comprised by SimulationFrame(s) called subsimulations."""              return self.__linked_attributes[name]
       
     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)  
365    
366  class _ParameterIterator:          if self.__class__.__dict__.has_key(name):
367      def __init__(self,parameterset):              return self.__class.__dict__[name]
         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  
368    
369  class ParameterSet(LinkableObject):          raise AttributeError,"No attribute %s."%name
370      """a class which allows to emphazise attributes to be written and read to XML      
371              def hasAttribute(self,name):
372         Leaves of  an ESySParameters objects can be          """
373            Returns True if self as attribute name.
374              a real number      """
375              a integer number          return self.__dict__.has_key(name) or self.__linked_attributes.has_key(name) or  self.__class__.__dict__.has_key(name)
             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)  
376    
377  class IterationDivergenceError(Exception):      def __setattr__(self,name,value):
378      """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          """
379         to reach convergence."""      Sets the value for attribute name. If value is a Link the target
380      pass          attribute is set to name if no attribute has been specified.
381        """
 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  
382    
383  class FailedTimeStepError(Exception):          if self.__dict__.has_key(name):
384      """excpetion which should be thrown if the time step fails because of a step size that have been choosen to be to large"""              del self.__dict__[name]
     pass  
385    
386  class NonPositiveStepSizeError(Exception):          if isinstance(value,Link):
387      """excpetion which is thrown if the step size is not positive"""              if not value.hasDefinedAttributeName():
388      pass                  value.setAttributeName(name)
389                self.__linked_attributes[name] = value
390    
391                self.trace("attribute %s is now linked by %s."%(name,value))
392            else:
393                self.__dict__[name] = value
394        
395        def __delattr__(self,name):
396            """
397        Removes the attribute name.
398        """
399    
400  #          if self.__linked_attributes.has_key[name]:
401  #   ignore this text:              del self.__linked_attributes[name]
402  #          elif self.__dict__.has_key(name):
403  """ the Model class provides a framework to run a time-dependent simulation. A              del self.__dict__[name]
404  Model has a set of parameter which may be fixed or altered by the Model itself          else:
405  or other Models over time.                raise AttributeError,"No attribute %s."%name
406    
407         The parameters of a models are declared at instantion, e.g.  class _ParameterIterator:
408        def __init__(self,parameterset):
409    
410             m=Model({"message" : "none" })          self.__set=parameterset
411            self.__iter=iter(parameterset.parameters)
412    
413         creates a Model with parameters p1 and p2 with inital values 1 and 2.      def next(self):
414         Typically a particular model is defined as a subclass of Model:          o=self.__iter.next()
415            return (o,self.__set.getAttributeObject(o))
416    
417          class Messenger(Model):      def __iter__(self):
418              def __init__(self):          return self
                Model.__init__(self,parameters={"message" : "none" })  
419    
420          m=MyModel()  class ParameterSet(LinkableObject):
421        """
422        A class which allows to emphazise attributes to be written and read to XML
423          
424        Leaves of an ESySParameters object can be:
425        
426         - a real number
427         - a integer number
428         - a string
429         - a boolean value
430         - a ParameterSet object
431         - a Simulation object
432         - a Model object
433         - a numarray object
434             - a list of booleans
435            - any other object (not considered by writeESySXML and writeXML)
436        
437        Example how to create an ESySParameters object::
438        
439            p11=ParameterSet(gamma1=1.,gamma2=2.,gamma3=3.)
440            p1=ParameterSet(dim=2,tol_v=0.001,output_file="/tmp/u.%3.3d.dx",runFlag=True,parm11=p11)
441            parm=ParameterSet(parm1=p1,parm2=ParameterSet(alpha=Link(p11,"gamma1")))
442        
443        This can be accessed as::
444        
445        parm.parm1.gamma=0.
446            parm.parm1.dim=2
447            parm.parm1.tol_v=0.001
448            parm.parm1.output_file="/tmp/u.%3.3d.dx"
449            parm.parm1.runFlag=True
450            parm.parm1.parm11.gamma1=1.
451            parm.parm1.parm11.gamma2=2.
452            parm.parm1.parm11.gamma3=3.
453            parm.parm2.alpha=1. (value of parm.parm1.parm11.gamma1)
454        """
455        def __init__(self, parameters=[], **kwargs):
456            """
457        Creates a ParameterSet with parameters parameters.
458        """
459            LinkableObject.__init__(self, **kwargs)
460            self.parameters = set()
461            self.declareParameters(parameters)
462    
463        def __repr__(self):
464            return "<%s %d>"%(self.__class__.__name__,id(self))
465        
466        def declareParameter(self,**parameters):
467            """
468        Declares a new parameter(s) and its (their) initial value.
469        """
470            self.declareParameters(parameters)
471        
472        def declareParameters(self,parameters):
473            """
474        Declares a set of parameters. parameters can be a list, a dictionary
475        or a ParameterSet.
476        """
477            if isinstance(parameters,ListType):
478                parameters = zip(parameters, itertools.repeat(None))
479            if isinstance(parameters,DictType):
480                parameters = parameters.iteritems()
481    
482            for prm, value in parameters:
483                setattr(self,prm,value)
484                self.parameters.add(prm)
485    
486        def releaseParameters(self,name):
487            """
488        Removes parameter name from the paramameters.
489        """
490            if self.isParameter(name):
491                self.parameters.remove(name)
492                self.trace("parameter %s has been removed."%name)
493    
494        def checkLinkTargets(self, models, hash):
495            """
496            returns a set of tuples ("<self>(<name>)", <target model>) if the parameter <name> is linked to model <target model>
497            but <target model> is not in the list models. If the a parameter is linked to another parameter set which is not in the hash list
498            the parameter set is checked for its models. hash gives the call history.
499            """
500            out=set()
501            for name, value in self:
502                if isinstance(value, Link):
503                   m=value.getTarget()
504                   if isinstance(m, Model):
505                       if not m in models: out.add( (str(self)+"("+name+")",m) )
506                   elif isinstance(m, ParameterSet) and not m in hash:
507                         out|=set( [ (str(self)+"("+name+")."+f[0],f[1]) for f in m.checkLinkTargets(models, hash+[ self ] ) ] )
508            return out
509        
510        def __iter__(self):
511            """
512        Creates an iterator over the parameter and their values.
513        """
514            return _ParameterIterator(self)
515        
516        def showParameters(self):
517            """
518        Returns a descrition of the parameters.
519        """        
520            out="{"
521            notfirst=False
522            for i,v in self:
523                if notfirst: out=out+","
524                notfirst=True
525                if isinstance(v,ParameterSet):
526                    out="%s\"%s\" : %s"%(out,i,v.showParameters())
527                else:
528                    out="%s\"%s\" : %s"%(out,i,v)
529            return out+"}"
530        
531        def __delattr__(self,name):
532            """
533        Removes the attribute name.
534        """
535            LinkableObject.__delattr__(self,name)
536            try:
537                self.releaseParameter(name)
538            except:
539                pass
540    
541        def toDom(self, esysxml, node):
542            """
543        C{toDom} method of Model class
544        """
545            pset = esysxml.createElement('ParameterSet')
546            pset.setAttribute('type', self.__class__.__name__)
547            pset.setAttribute('module', self.__class__.__module__)
548            esysxml.registerLinkableObject(self, pset)
549            self._parametersToDom(esysxml, pset)
550            node.appendChild(pset)
551    
552        def _parametersToDom(self, esysxml, node):
553            for name,value in self:
554                # convert list to numarray when possible:
555                if isinstance (value, list):
556                    elem_type=-1
557                    for i in value:
558                        if isinstance(i, bool):
559                            elem_type = max(elem_type,0)
560                        elif isinstance(i, int):
561                            elem_type = max(elem_type,1)
562                        elif isinstance(i, float):
563                            elem_type = max(elem_type,2)
564                    if elem_type == 0: value = numarray.array(value,numarray.Bool)
565                    if elem_type == 1: value = numarray.array(value,numarray.Int)
566                    if elem_type == 2: value = numarray.array(value,numarray.Float)
567    
568                param = esysxml.createElement('Parameter')
569                param.setAttribute('type', value.__class__.__name__)
570    
571                param.appendChild(esysxml.createDataNode('Name', name))
572    
573                val = esysxml.createElement('Value')
574                if isinstance(value,(ParameterSet,Link,DataSource)):
575                    value.toDom(esysxml, val)
576                    param.appendChild(val)
577                elif isinstance(value, numarray.NumArray):
578                    shape = value.getshape()
579                    if isinstance(shape, tuple):
580                        size = reduce(operator.mul, shape)
581                        shape = ' '.join(map(str, shape))
582                    else:
583                        size = shape
584                        shape = str(shape)
585    
586                    arraytype = value.type()
587                    if isinstance(arraytype, numarray.BooleanType):
588                          arraytype_str="Bool"
589                    elif isinstance(arraytype, numarray.IntegralType):
590                          arraytype_str="Int"
591                    elif isinstance(arraytype, numarray.FloatingType):
592                          arraytype_str="Float"
593                    elif isinstance(arraytype, numarray.ComplexType):
594                          arraytype_str="Complex"
595                    else:
596                          arraytype_str=str(arraytype)
597                    numarrayElement = esysxml.createElement('NumArray')
598                    numarrayElement.appendChild(esysxml.createDataNode('ArrayType', arraytype_str))
599                    numarrayElement.appendChild(esysxml.createDataNode('Shape', shape))
600                    numarrayElement.appendChild(esysxml.createDataNode('Data', ' '.join(
601                        [str(x) for x in numarray.reshape(value, size)])))
602                    val.appendChild(numarrayElement)
603                    param.appendChild(val)
604                elif isinstance(value, list):
605                    param.appendChild(esysxml.createDataNode('Value', ' '.join([str(x) for x in value]) ))
606                elif isinstance(value, (str, bool, int, float, type(None))):
607                    param.appendChild(esysxml.createDataNode('Value', str(value)))
608                elif isinstance(value, dict):
609                     dic = esysxml.createElement('dictionary')
610                     if len(value.keys())>0:
611                         dic.setAttribute('key_type', value.keys()[0].__class__.__name__)
612                         dic.setAttribute('value_type', value[value.keys()[0]].__class__.__name__)
613                     for k,v in value.items():
614                        i=esysxml.createElement('item')
615                        i.appendChild(esysxml.createDataNode('key', k))
616                        i.appendChild(esysxml.createDataNode('value', v))
617                        dic.appendChild(i)
618                     param.appendChild(dic)
619                else:
620                    raise ValueError("cannot serialize %s type to XML."%str(value.__class__))
621    
622                node.appendChild(param)
623    
624        def fromDom(cls, esysxml, node):
625            # Define a host of helper functions to assist us.
626            def _children(node):
627                """
628                Remove the empty nodes from the children of this node.
629                """
630                ret = []
631                for x in node.childNodes:
632                    if isinstance(x, minidom.Text):
633                        if x.nodeValue.strip():
634                            ret.append(x)
635                    else:
636                        ret.append(x)
637                return ret
638    
639            def _floatfromValue(esysxml, node):
640                return float(node.nodeValue.strip())
641    
642            def _stringfromValue(esysxml, node):
643                return str(node.nodeValue.strip())
644          
645            def _intfromValue(esysxml, node):
646                return int(node.nodeValue.strip())
647    
648            def _boolfromValue(esysxml, node):
649                return _boolfromstring(node.nodeValue.strip())
650    
651            def _nonefromValue(esysxml, node):
652                return None
653    
654            def _numarrayfromValue(esysxml, node):
655                for node in _children(node):
656                    if node.tagName == 'ArrayType':
657                        arraytype = node.firstChild.nodeValue.strip()
658                    if node.tagName == 'Shape':
659                        shape = node.firstChild.nodeValue.strip()
660                        shape = [int(x) for x in shape.split()]
661                    if node.tagName == 'Data':
662                        data = node.firstChild.nodeValue.strip()
663                        data = [float(x) for x in data.split()]
664                return numarray.reshape(numarray.array(data, type=getattr(numarray, arraytype)),
665                                        shape)
666          
667            def _listfromValue(esysxml, node):
668                return [x for x in node.nodeValue.split()]
669    
670            def _boolfromstring(s):
671                if s == 'True':
672                    return True
673                else:
674                    return False
675            # Mapping from text types in the xml to methods used to process trees of that type
676            ptypemap = {"Simulation": Simulation.fromDom,
677                        "Model":Model.fromDom,
678                        "ParameterSet":ParameterSet.fromDom,
679                        "Link":Link.fromDom,
680                        "DataSource":DataSource.fromDom,
681                        "float":_floatfromValue,
682                        "int":_intfromValue,
683                        "str":_stringfromValue,
684                        "bool":_boolfromValue,
685                        "list":_listfromValue,
686                        "NumArray":_numarrayfromValue,
687                        "NoneType":_nonefromValue,
688                        }
689    
690            parameters = {}
691            for n in _children(node):
692                ptype = n.getAttribute("type")
693                if not ptypemap.has_key(ptype):
694                   raise KeyError("cannot handle parameter type %s."%ptype)
695    
696                pname = pvalue = None
697                for childnode in _children(n):
698                    if childnode.tagName == "Name":
699                        pname = childnode.firstChild.nodeValue.strip()
700    
701                    if childnode.tagName == "Value":
702                        nodes = _children(childnode)
703                        pvalue = ptypemap[ptype](esysxml, nodes[0])
704    
705                parameters[pname] = pvalue
706    
707            # Create the instance of ParameterSet
708            try:
709               o = cls(debug=esysxml.debug)
710            except TypeError, inst:
711               print inst.args[0]
712               if inst.args[0]=="__init__() got an unexpected keyword argument 'debug'":
713                  raise TypeError("The Model class %s __init__ needs to have argument 'debug'.")
714               else:
715                  raise inst
716            o.declareParameters(parameters)
717            esysxml.registerLinkableObject(o, node)
718            return o
719        
720        fromDom = classmethod(fromDom)
721    
722        def writeXML(self,ostream=stdout):
723            """
724        Writes the object as an XML object into an output stream.
725        """
726            esysxml=ESySXMLCreator()
727            self.toDom(esysxml, esysxml.getRoot())
728            ostream.write(esysxml.toprettyxml())
729        
730    class Model(ParameterSet):
731        """
732        A Model object represents a processess marching over time until a
733        finalizing condition is fullfilled. At each time step an iterative
734        process can be performed and the time step size can be controlled. A
735        Model has the following work flow::
736              
737              doInitialization()
738              while not terminateInitialIteration(): doInitializationiStep()
739              doInitialPostprocessing()
740              while not finalize():
741                   dt=getSafeTimeStepSize(dt)
742                   doStepPreprocessing(dt)
743                   while not terminateIteration(): doStep(dt)
744                   doStepPostprocessing(dt)
745              doFinalization()
746    
747        where C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
748        C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
749        C{doFinalization} are methods of the particular instance of a Model. The
750        default implementations of these methods have to be overwritten by the
751        subclass implementing a Model.
752        """
753    
754        UNDEF_DT=1.e300
755    
756        def __init__(self,parameters=[],**kwargs):
757            """
758        Creates a model.
759    
760            Just calls the parent constructor.
761            """
762            ParameterSet.__init__(self, parameters=parameters,**kwargs)
763    
764        def __str__(self):
765           return "<%s %d>"%(self.__class__.__name__,id(self))
766    
767    
768        def setUp(self):
769            """
770            Sets up the model.
771    
772            This function may be overwritten.
773            """
774            pass
775    
776        def doInitialization(self):
777            """
778        Initializes the time stepping scheme. This method is not called in case of a restart.
779        
780        This function may be overwritten.
781        """
782            pass
783        def doInitialStep(self):
784            """
785        performs an iteration step in the initialization phase. This method is not called in case of a restart.
786    
787         There are various ways how model parameters can be changed:      This function may be overwritten.
788        """
789            pass
790    
791         1) use object attributes:      def terminateInitialIteration(self):
792            """
793        Returns True if iteration at the inital phase is terminated.
794        """
795            return True
796    
797            m.message="Hello World!"      def doInitialPostprocessing(self):
798            """
799        finalises the initialization iteration process. This method is not called in case of a restart.
800    
801         2) use setParamter method      This function may be overwritten.
802                """
803                      pass
804            m.setParameters(message="Hello World!")      
805        def getSafeTimeStepSize(self,dt):
806            """
807        Returns a time step size which can safely be used.
808    
809         3) or dictonaries          C{dt} gives the previously used step size.
     
            d={ message : "Hello World!" }  
            m.setParameters(**d)  
810    
811            This function may be overwritten.
812        """
813            return self.UNDEF_DT
814        
815        def finalize(self):
816            """
817        Returns False if the time stepping is finalized.
818        
819        This function may be overwritten.
820        """
821            return False
822          
823        def doFinalization(self):
824            """
825        Finalizes the time stepping.
826        
827        This function may be overwritten.
828        """
829            pass
830        
831        def doStepPreprocessing(self,dt):
832            """
833        Sets up a time step of step size dt.
834        
835        This function may be overwritten.
836        """
837            pass
838        
839        def doStep(self,dt):
840            """
841        Executes an iteration step at a time step.
842    
843         A model executed buy staring the run method of the model:          C{dt} is the currently used time step size.
   
           m=Messenger()  
           m.run()  
844    
845         The run methods marches through time. It first calls the          This function may be overwritten.
846         doInitialization() method of the Model to set up the process. In each      """
847         time step the doStep() method is called to get from the current to the          pass
848         next time step. The step size is defined by calling the      
849         getSafeTimeStepSize() method.  the time integration process is      def terminateIteration(self):
850         terminated when the finalize() methods return true. Final the          """
851         doFinalization() method is called to finalize the process. To implement      Returns True if iteration on a time step is terminated.
852         a particular model a subclass of the Model class is defined. The      """
853         subclass overwrites the default methods of Model.          return True
   
        The following class defines a messenger printing in the doStep method  
        what ever the current value of its parameter message is:  
   
        class Messenger(Model):  
             def __init__(self):  
                Model.__init__(self,parameters={"message" : "none" })  
   
             def doInitialization(self):  
                print "I start talking now!"  
   
             def doStep(self,t):  
                print "Message (time %e) : %s "%(t,self.message)  
   
             def doFinalization(self):  
                print "I have no more to say!"  
         
        If a instance of the Messenger class is run, it will print the  
        initialization and finalization message only.  This is because the  
        default method for finalize() does always returns True and therefore the  
        transition is terminated startcht away.  
           
        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  
854    
855         has to be solved for u_{n+1}. The Newton scheme is used to solve this non-linear problem.        
856        def doStepPostprocessing(self,dt):
857            """
858        finalises the time step.
859    
860            dt is the currently used time step size.
       class  Ode2(Model):  
861    
862         def __init__(self,**args):          This function may be overwritten.
863             Model.__init__(self,{"tend" : 1., "dt" : 0.1 ,"a" : 10. ,"u" : 1. , "tol " : 1.e-8},"test","bla",None,True)      """
864            pass
865    
866         def doInitialization(self):      def toDom(self, esysxml, node):
867             self.__tn=0          """
868        C{toDom} method of Model class
869        """
870            pset = esysxml.createElement('Model')
871            pset.setAttribute('type', self.__class__.__name__)
872            pset.setAttribute('module', self.__class__.__module__)
873            esysxml.registerLinkableObject(self, pset)
874            node.appendChild(pset)
875            self._parametersToDom(esysxml, pset)
876        
877    class Simulation(Model):
878        """
879        A Simulation object is special Model which runs a sequence of Models.
880    
881        The methods C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
882        C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
883        C{doFinalization} are executing the corresponding methods of the models in
884        the simulation.
885        """
886        
887        FAILED_TIME_STEPS_MAX=20
888        MAX_ITER_STEPS=50
889        MAX_CHANGE_OF_DT=2.
890        
891        def __init__(self, models=[], **kwargs):
892            """
893        Initiates a simulation from a list of models.
894        """
895            super(Simulation, self).__init__(**kwargs)
896            self.declareParameter(time=0.,
897                                  time_step=0,
898                                  dt = self.UNDEF_DT)
899            for m in models:
900                if not isinstance(m, Model):
901                     raise TypeError("%s is not a subclass of Model."%m)
902            self.__models=[]
903            for i in range(len(models)):
904                self[i] = models[i]
905                
906    
907        def __repr__(self):
908            """
909            Returns a string representation of the Simulation.
910            """
911            return "<Simulation %r>" % self.__models
912    
913        def __str__(self):
914            """
915            Returning Simulation as a string.
916            """
917            return "<Simulation %d>"%id(self)
918        
919        def iterModels(self):
920            """
921        Returns an iterator over the models.
922        """
923            return self.__models
924        
925        def __getitem__(self,i):
926            """
927        Returns the i-th model.
928        """
929            return self.__models[i]
930        
931        def __setitem__(self,i,value):
932            """
933        Sets the i-th model.
934        """
935            if not isinstance(value,Model):
936                raise ValueError,"assigned value is not a Model but instance of %s"%(value.__class__.__name__,)
937            for j in range(max(i-len(self.__models)+1,0)):
938                self.__models.append(None)
939            self.__models[i]=value
940        
941        def __len__(self):
942            """
943        Returns the number of models.
944        """
945            return len(self.__models)
946    
947         def doIterationInitialization(self,t):      def getAllModels(self):
948              self.__iter=0          """
949              self.u_last=self.u                      returns a list of all models used in the Simulation including subsimulations
950              self.current_dt=t-self.tn          """
951              self.__tn=t          out=[]
952            for m in self.iterModels():
953         def doIterationStep(self):              if isinstance(m, Simulation):
954            self.__iter+=1                 out+=m.getAllModels()
955            self.u_old=self.u              else:
956            self.u=(self.current_dt*self.a*self.u**2-self.u_last)/(2*self.current_dt*self.a*self.u-1.)                 out.append(m)
957            return list(set(out))
958         def terminate(self):  
959             return abs(self.u_old-self.u)<self.tol*abs(self.u)      def checkModels(self, models, hash):
960            """
961         def doIterationFinalization(self)          returns a list of (model,parameter, target model ) if the the parameter of model
962             print "all done"          is linking to the target_model which is not in list of models.
963            """
964         def getSafeTimeStepSize(self):          out=self.checkLinkTargets(models, hash + [self])
965             return self.dt          for m in self.iterModels():
966                if isinstance(m, Simulation):
967         def finalize(self):                   out|=m.checkModels(models, hash)
968              return self.__tn>self.tend              else:
969                     out|=m.checkLinkTargets(models, hash + [self])
970         A model can be composed from subsimulations. Subsimulations are treated          return set( [ (str(self)+"."+f[0],f[1]) for f in out ] )
971         as model parameters. If a model parameter is set or a value of a model  
972         parameter is requested, the model will search for this parameter its      
973         subsimulations in the case the model does not have this parameter      def getSafeTimeStepSize(self,dt):
974         itself. The order in which the subsimulations are searched is critical.          """
975         By default a Model initializes all its subsimulations, is finalized when      Returns a time step size which can safely be used by all models.
        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)  
976    
977          def doFinalization(self):          This is the minimum over the time step sizes of all models.
978              print "I have no more to say!"      """
979              out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
980      class ODETEST(Model):          return out
         """ implements a solver for the ODE  
981    
982                du/dt=a*u+f(t)      def setUp(self):
983            """
984            performs the setup for all models
985            """
986            for o in self.iterModels():
987                 o.setUp()
988        
989        def doInitialization(self):
990            """
991        Initializes all models.
992        """
993            for o in self.iterModels():
994                 o.doInitialization()
995        def doInitialStep(self):
996            """
997        performs an iteration step in the initialization step for all models
998        """
999            iter=0
1000            while not self.terminateInitialIteration():
1001                if iter==0: self.trace("iteration for initialization starts")
1002                iter+=1
1003                self.trace("iteration step %d"%(iter))
1004                for o in self.iterModels():
1005                     o.doInitialStep()
1006                if iter>self.MAX_ITER_STEPS:
1007                     raise IterationDivergenceError("initial iteration did not converge after %s steps."%iter)
1008            self.trace("Initialization finalized after %s iteration steps."%iter)
1009    
1010        def doInitialPostprocessing(self):
1011            """
1012        finalises the initialization iteration process for all models.
1013        """
1014            for o in self.iterModels():
1015                o.doInitialPostprocessing()
1016        def finalize(self):
1017            """
1018        Returns True if any of the models is to be finalized.
1019        """
1020            return any([o.finalize() for o in self.iterModels()])
1021          
1022        def doFinalization(self):
1023            """
1024        finalises the time stepping for all models.
1025        """
1026            for i in self.iterModels(): i.doFinalization()
1027            self.trace("end of time integation.")
1028        
1029        def doStepPreprocessing(self,dt):
1030            """
1031        Initializes the time step for all models.
1032        """
1033            for o in self.iterModels():
1034                o.doStepPreprocessing(dt)
1035        
1036        def terminateIteration(self):
1037            """
1038        Returns True if all iterations for all models are terminated.
1039        """
1040            out=all([o.terminateIteration() for o in self.iterModels()])
1041            return out
1042    
1043             we use a implicit euler scheme :      def terminateInitialIteration(self):
1044            """
1045        Returns True if all initial iterations for all models are terminated.
1046        """
1047            out=all([o.terminateInitialIteration() for o in self.iterModels()])
1048            return out
1049          
1050        def doStepPostprocessing(self,dt):
1051            """
1052        finalises the iteration process for all models.
1053        """
1054            for o in self.iterModels():
1055                o.doStepPostprocessing(dt)
1056            self.time_step+=1
1057            self.time+=dt
1058            self.dt=dt
1059        
1060        def doStep(self,dt):
1061            """
1062        Executes the iteration step at a time step for all model::
1063    
1064                self.doStepPreprocessing(dt)
1065                while not self.terminateIteration():
1066                for all models:
1067                self.doStep(dt)
1068                    self.doStepPostprocessing(dt)
1069            """
1070            self.iter=0
1071            while not self.terminateIteration():
1072                if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.time_step+1,self.time+dt))
1073                self.iter+=1
1074                self.trace("iteration step %d"%(self.iter))
1075                for o in self.iterModels():
1076                      o.doStep(dt)
1077            if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.time_step+1,self.time+dt))
1078    
1079        def run(self,check_pointing=None):
1080            """
1081        Run the simulation by performing essentially::
1082        
1083                self.setUp()
1084                if not restart:
1085                self.doInitialization()
1086                    while not self.terminateInitialIteration(): self.doInitialStep()
1087                    self.doInitialPostprocessing()
1088            while not self.finalize():
1089                dt=self.getSafeTimeStepSize()
1090                    self.doStepPreprocessing(dt_new)
1091                    self.doStep(dt_new)
1092                    self.doStepPostprocessing(dt_new)
1093            self.doFinalization()
1094    
1095            If one of the models in throws a C{FailedTimeStepError} exception a
1096        new time step size is computed through getSafeTimeStepSize() and the
1097        time step is repeated.
1098      
1099            If one of the models in throws a C{IterationDivergenceError}
1100        exception the time step size is halved and the time step is repeated.
1101    
1102                u_n-u_{n-1}= dt*a u_n + st*f(t_n)          In both cases the time integration is given up after
1103        C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
1104            """
1105            # check the completness of the models:
1106            # first a list of all the models involved in the simulation including subsimulations:
1107            #
1108            missing=self.checkModels(self.getAllModels(), [])
1109            if len(missing)>0:
1110                msg=""
1111                for l in missing:
1112                     msg+="\n\t"+str(l[1])+" at "+l[0]
1113                raise MissingLink("link targets missing in the Simulation: %s"%msg)
1114            #==============================
1115            self.setUp()
1116            if self.time_step < 1:
1117               self.doInitialization()
1118               self.doInitialStep()
1119               self.doInitialPostprocessing()
1120            while not self.finalize():
1121                step_fail_counter=0
1122                iteration_fail_counter=0
1123                if self.time_step==0:
1124                    dt_new=self.getSafeTimeStepSize(self.dt)
1125                else:
1126                    dt_new=min(max(self.getSafeTimeStepSize(self.dt),self.dt/self.MAX_CHANGE_OF_DT),self.dt*self.MAX_CHANGE_OF_DT)
1127                self.trace("%d. time step %e (step size %e.)" % (self.time_step+1,self.time+dt_new,dt_new))
1128                end_of_step=False
1129                while not end_of_step:
1130                   end_of_step=True
1131                   if not dt_new>0:
1132                      raise NonPositiveStepSizeError("non-positive step size in step %d"%(self.time_step+1))
1133                   try:
1134                      self.doStepPreprocessing(dt_new)
1135                      self.doStep(dt_new)
1136                      self.doStepPostprocessing(dt_new)
1137                   except IterationDivergenceError:
1138                      dt_new*=0.5
1139                      end_of_step=False
1140                      iteration_fail_counter+=1
1141                      if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
1142                               raise SimulationBreakDownError("reduction of time step to achieve convergence failed after %s steps."%self.FAILED_TIME_STEPS_MAX)
1143                      self.trace("Iteration failed. Time step is repeated with new step size %s."%dt_new)
1144                   except FailedTimeStepError:
1145                      dt_new=self.getSafeTimeStepSize(self.dt)
1146                      end_of_step=False
1147                      step_fail_counter+=1
1148                      self.trace("Time step is repeated with new time step size %s."%dt_new)
1149                      if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
1150                            raise SimulationBreakDownError("Time integration is given up after %d attempts."%step_fail_counter)
1151                if not check_pointing==None:
1152                   if check_pointing.doDump():
1153                        self.trace("check point is created.")
1154                        self.writeXML()
1155            self.doFinalization()
1156    
1157    
1158        def toDom(self, esysxml, node):
1159            """
1160        C{toDom} method of Simulation class.
1161        """
1162            simulation = esysxml.createElement('Simulation')
1163            esysxml.registerLinkableObject(self, simulation)
1164            for rank, sim in enumerate(self.iterModels()):
1165                component = esysxml.createElement('Component')
1166                component.setAttribute('rank', str(rank))
1167                sim.toDom(esysxml, component)
1168                simulation.appendChild(component)
1169            node.appendChild(simulation)
1170    
1171    
1172        def fromDom(cls, esysxml, node):
1173            sims = []
1174            for n in node.childNodes:
1175                if isinstance(n, minidom.Text):
1176                    continue
1177                sims.append(esysxml.getComponent(n))
1178            sims.sort(_comp)
1179            sim=cls([s[1] for s in sims], debug=esysxml.debug)
1180            esysxml.registerLinkableObject(sim, node)
1181            return sim
1182    
1183        fromDom = classmethod(fromDom)
1184    
1185    def _comp(a,b):
1186        if a[0]<a[1]:
1187          return 1
1188        elif a[0]>a[1]:
1189          return -1
1190        else:
1191          return 0
1192    
1193             to get u_n we run an iterative process  class IterationDivergenceError(Exception):
1194        """
1195                 u_{n.k}=u_{n-1}+dt*(a u_{n.i-1} + f(t_n))      Exception which is thrown if there is no convergence of the iteration
1196        process at a time step.
1197    
1198        But there is a chance that a smaller step could help to reach convergence.
1199        """
1200        pass
1201    
1202    class FailedTimeStepError(Exception):
1203        """
1204        Exception which is thrown if the time step fails because of a step
1205        size that have been choosen to be too large.
1206        """
1207        pass
1208    
1209    class SimulationBreakDownError(Exception):
1210        """
1211        Exception which is thrown if the simulation does not manage to
1212        progress in time.
1213        """
1214        pass
1215    
1216             input for this model are step size dt, end time tend and a value for  class NonPositiveStepSizeError(Exception):
1217             a, f and initial value for u. we need also a tolerance tol for a      """
1218             stopping criterion.      Exception which is thrown if the step size is not positive.
1219        """
1220          """      pass
1221    
1222          def __init__(self):  class MissingLink(Exception):
1223              Model.__init__(self,debug=True)      """
1224              self.declareParameter(tend=1.,dt=0.1,a=0.9,u=10.,f=0.,message="",tol=1.e-8)      Exception thrown when a link is missing
1225        """
1226          def doInitialization(self,t):      pass
1227              self.__tn=t  
1228              self.__iter=0  class DataSource(object):
1229                  """
1230          def doIterationInitialization(self,dt):      Class for handling data sources, including local and remote files. This class is under development.
1231              self.__iter=0      """
1232              self.__u_last=self.u              
1233        def __init__(self, uri="file.ext", fileformat="unknown"):
1234          def doIterationStep(self,dt):          self.uri = uri
1235              self.__iter+=1          self.fileformat = fileformat
1236              self.__u_old=self.u  
1237              self.u=self.__u_last+dt*(self.a*self.__u_old+self.f)      def toDom(self, esysxml, node):
1238                    """
1239          def terminate(self):          C{toDom} method of DataSource. Creates a DataSource node and appends it to the
1240              if self.__iter<1:      current XML esysxml.
1241                  return False          """
1242              else:          ds = esysxml.createElement('DataSource')
1243                  return abs(self.__u_old-self.u)<self.tol*abs(self.u)          ds.appendChild(esysxml.createDataNode('URI', self.uri))
1244            ds.appendChild(esysxml.createDataNode('FileFormat', self.fileformat))
1245          def doIterationFinalization(self,dt):          node.appendChild(ds)
1246              self.__tn+=dt  
1247              self.message="current error = %e"%abs(self.u-10.*math.exp((self.a-1.)*self.__tn))      def fromDom(cls, esysxml, node):
1248            uri= str(node.getElementsByTagName("URI")[0].firstChild.nodeValue.strip())
1249          def getSafeTimeStepSize(self,dt):          fileformat= str(node.getElementsByTagName("FileFormat")[0].firstChild.nodeValue.strip())
1250              return min(self.dt,1./(abs(self.a)+1.))          ds = cls(uri, fileformat)
1251            return ds
1252          def finalize(self):  
1253              return self.__tn>=self.tend      def getLocalFileName(self):
1254            return self.uri
1255      #  
1256      #   s solves the coupled ODE:      fromDom = classmethod(fromDom)
1257      #  
1258      #     du/dt=a*u+  v  class RestartManager(object):
1259      #     dv/dt=  u+a*v       """
1260      #         A restart manager which does two things: it decides when restart files have created (when doDump returns true) and
1261      #   each equation is treated through the ODETEST class. The equations are       manages directories for restart files. The method getNewDumper creates a new directory and returns its name.
1262      #   linked and iteration over each time step is performed.  the current      
1263      #   error of v is reported by the Messenger class.       This restart manager will decide to dump restart files if every dump_step calls of doDump or
1264      #       if more than dump_time since the last dump has elapsed. The restart manager controls two directories for dumping restart data, namely
1265      o1=ODETEST()       for the current and previous dump. This way the previous dump can be used for restart in the case the current dump failed.
1266      o1.u=10  
1267      o2=ODETEST()       @cvar SEC: unit of seconds, for instance for 5*RestartManager.SEC to define 5 seconds.
1268      o2.u=-10.       @cvar MIN: unit of minutes, for instance for 5*RestartManager.MIN to define 5 minutes.
1269      o1.f=Link(o2,"u")       @cvar H: unit of hours, for instance for 5*RestartManager.H to define 5 hours.
1270      o2.f=Link(o1,"u")       @cvar D: unit of days, for instance for 5*RestartManager.D to define 5 days.
1271      m=Messenger()       """
1272      o1.dt=0.01       SEC=1.
1273      m.message=Link(o1)       MIN=60.
1274      s=ExplicitSimulation([Simulation([o1,o2],debug=True),m],debug=True)       H=360.
1275      s.run()       D=8640.
1276      s.writeXML()       def __init__(self,dump_time=1080., dump_step=None, dumper=None):
1277             """
1278             initializes the RestartManager.
1279    
1280             @param dump_time: defines the minimum time interval in SEC between to dumps. If None, time is not used as criterion.
1281             @param dump_step: defines the number of calls of doDump between to dump events. If None, the call counter is not used as criterion.
1282             @param dumper: defines the directory for dumping restart files. Additionally the directories dumper+"_bkp" and dumper+"_bkp2" are used.
1283                            if the directory does not exist it is created. If dumper is not present a unique directory within the current
1284                            working directory is used.
1285             """
1286             self.__dump_step=dump_time
1287             self.__dump_time=dump_step
1288             self.__counter=0
1289             self.__saveMarker()
1290             if dumper == None:
1291                self.__dumper="restart"+str(os.getpid())
1292             else:
1293                self.__dumper=dumper
1294             self.__dumper_bkp=self.__dumper+"_bkp"
1295             self.__dumper_bkp2=self.__dumper+"_bkp2"
1296             self.__current_dumper=None
1297         def __saveMarker(self):
1298             self.__last_restart_time=time.time()
1299             self.__last_restart_counter=self.__counter
1300         def getCurrentDumper(self):
1301             """
1302             returns the name of the currently used dumper
1303             """
1304             return self.__current_dumper
1305         def doDump(self):
1306            """
1307            returns true the restart should be dumped. use C{getNewDumper} to get the directory name to be used.
1308            """
1309            if self.__dump_step == None:
1310               if self.__dump_step == None:
1311                  out = False
1312               else:
1313                  out = (self.__dump_step + self.__last_restart_counter) <= self.__counter
1314            else:
1315               if dump_step == None:
1316                  out = (self.__last_restart_time + self.__dump_time) <= time.time()
1317               else:
1318                  out =    ( (self.__dump_step + self.__last_restart_counter) <= self.__counter)  \
1319                        or ( (self.__last_restart_time + self.__dump_time) <= time.time() )
1320            if out: self.__saveMarker()
1321            self__counter+=1
1322         def getNewDumper(self):
1323           """
1324           creates a new directory to be used for dumping and returns its name.
1325           """
1326           if os.access(self.__dumper_bkp,os.F_OK):
1327              if os.access(self.__dumper_bkp2, os.F_OK):
1328                 raise RunTimeError("please remove %s."%self.__dumper_bkp2)
1329              try:
1330                 os.rename(self.__dumper_bkp, self.__dumper_bkp2)
1331              except:
1332                 self.__current_dumper=self.__dumper
1333                 raise RunTimeError("renaming back-up directory %s failed. Use %s for restart."%(self.__dumper_bkp,self.__dumper))
1334           if os.access(self.__dumper,os.F_OK):
1335              if os.access(self.__dumper_bkp, os.F_OK):
1336                 raise RunTimeError("please remove %s."%self.__dumper_bkp)
1337              try:
1338                 os.rename(self.__dumper, self.__dumper_bkp)
1339              except:
1340                 self.__current_dumper=self.__dumper_bkp2
1341                 raise RunTimeError("moving directory %s to back-up failed. Use %s for restart."%(self.__dumper,self.__dumper_bkp2))
1342           try:
1343              os.mkdir(self.__dumper)
1344           except:
1345              self.__current_dumper=self.__dumper_bkp
1346              raise RunTimeError("creating a new restart directory %s failed. Use %s for restart."%(self.__dumper,self.__dumper_bkp))
1347           if os.access(self.__dumper_bkp2, os.F_OK): os.rmdir(self.__dumper_bkp2)
1348           return self.getCurrentDumper()
1349            
1350        
1351    # vim: expandtab shiftwidth=4:

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

  ViewVC Help
Powered by ViewVC 1.1.26