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

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

  ViewVC Help
Powered by ViewVC 1.1.26