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

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

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

revision 728 by gross, Mon May 15 02:01:18 2006 UTC revision 926 by gross, Fri Jan 12 06:31:37 2007 UTC
# Line 24  __date__="$Date$" Line 24  __date__="$Date$"
24    
25  from types import StringType,IntType,FloatType,BooleanType,ListType,DictType  from types import StringType,IntType,FloatType,BooleanType,ListType,DictType
26  from sys import stdout  from sys import stdout
27    import numarray
28    import operator
29  import itertools  import itertools
 # import modellib  temporarily removed!!!  
30    
31  # import the 'set' module if it's not defined (python2.3/2.4 difference)  # import the 'set' module if it's not defined (python2.3/2.4 difference)
32  try:  try:
# Line 35  except NameError: Line 36  except NameError:
36    
37  from xml.dom import minidom  from xml.dom import minidom
38    
 def dataNode(document, tagName, data):  
     """  
     C{dataNode}s are the building blocks of the xml documents constructed in  
     this module.    
       
     @param document: the current xml document  
     @param tagName: the associated xml tag  
     @param data: the values in the tag  
     """  
     t = document.createTextNode(str(data))  
     n = document.createElement(tagName)  
     n.appendChild(t)  
     return n  
   
 def esysDoc():  
     """  
     Global method for creating an instance of an EsysXML document.  
     """  
     doc = minidom.Document()  
     esys = doc.createElement('ESys')  
     doc.appendChild(esys)  
     return doc, esys  
39    
40  def all(seq):  def all(seq):
41      for x in seq:      for x in seq:
# Line 70  def any(seq): Line 49  def any(seq):
49              return True              return True
50      return False      return False
51    
 LinkableObjectRegistry = {}  
   
 def registerLinkableObject(obj_id, o):  
     LinkableObjectRegistry[obj_id] = o  
   
 LinkRegistry = []  
   
 def registerLink(obj_id, l):  
     LinkRegistry.append((obj_id,l))  
   
 def parse(xml):  
     """  
     Generic parse method for EsysXML.  Without this, Links don't work.  
     """  
     global LinkRegistry, LinkableObjectRegistry  
     LinkRegistry = []  
     LinkableObjectRegistry = {}  
   
     doc = minidom.parseString(xml)  
     sim = getComponent(doc.firstChild)  
     for obj_id, link in LinkRegistry:  
         link.target = LinkableObjectRegistry[obj_id]  
   
     return sim  
   
52  def importName(modulename, name):  def importName(modulename, name):
53      """ Import a named object from a module in the context of this function,      """ Import a named object from a module in the context of this function,
54          which means you should use fully qualified module paths.          which means you should use fully qualified module paths.
           
55          Return None on failure.          Return None on failure.
56    
57          This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241          This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241
# Line 110  def importName(modulename, name): Line 63  def importName(modulename, name):
63      except KeyError:      except KeyError:
64          raise ImportError("Could not import %s from %s" % (name, modulename))          raise ImportError("Could not import %s from %s" % (name, modulename))
65    
66  def getComponent(doc):  class ESySXMLParser(object):
     """  
     Used to get components of Simualtions, Models.  
67      """      """
68      for node in doc.childNodes:      parser for ESysXML file
69                """
70          if isinstance(node, minidom.Element):      def __init__(self,xml, debug=False):
71              if node.tagName == 'Simulation':        self.__dom = minidom.parseString(xml)
72                  if node.getAttribute("type") == 'Simulation':        self.__linkable_object_registry= {}
73                      return Simulation.fromDom(node)        self.__link_registry=  []
74              if node.tagName == 'Model':        self.__esys=self.__dom.firstChild
75                  if (node.getAttribute("module")):        self.debug=debug
76                      model_module = node.getAttribute("module")    
77                      model_type = node.getAttribute("type")      def getClassPath(self, node):
78                      return importName(model_module, model_type).fromDom(node)          type = node.getAttribute("type")
79                  else:          if (node.getAttribute("module")):
80                      model_type = node.getAttribute("type")              module = node.getAttribute("module")
81                      model_subclasses = Model.__subclasses__()              return importName(module, type)
82                      for model in model_subclasses:          else:
83                          if model_type == model.__name__:              return importName("__main__", type)
                             return Model.fromDom(node)  
             if node.tagName == 'ParameterSet':  
                 parameter_type = node.getAttribute("type")  
                 return ParameterSet.fromDom(node)  
             raise "Invalid simulation type, %r" % node.getAttribute("type")  
           
84    
85      raise ValueError("No Simulation Found")      def setLinks(self):
86                        for obj_id, link in self.__link_registry:
87                link.target = self.__linkable_object_registry[obj_id]
88    
89        def parse(self):
90           """
91           parser method for EsysXML and returns the list of generating ParameterSets
92           """
93           found=[]
94           for node in self.__esys.childNodes:
95               if isinstance(node, minidom.Element):
96                   if node.tagName == 'Simulation':
97                            found.append(Simulation.fromDom(self, node))
98                   elif node.tagName == 'Model':
99                            found.append(self.getClassPath(node).fromDom(self, node))
100                   elif node.tagName == 'ParameterSet':
101                            found.append(self.getClassPath(node).fromDom(self, node))
102                   else:
103                      raise "Invalid type, %r" % node.getAttribute("type")
104           self.setLinks()
105           return found
106    
107        def registerLink(self,obj_id, link):
108            self.__link_registry.append((int(obj_id),link))
109    
110        def registerLinkableObject(self,obj, node):
111            id_str=node.getAttribute('id').strip()
112            if len(id_str)>0:
113               id=int(id_str)
114               if self.__linkable_object_registry.has_key(id):
115                   raise ValueError("Object id %s already exists."%id)
116               else:
117                   self.__linkable_object_registry[id]=obj
118    
119        def getComponent(self, node):
120           """
121           returns a single component + rank from a simulation
122           parser method for EsysXML and returns the list of generating ParameterSets
123           """
124           rank  = int(node.getAttribute("rank"))
125           for n in node.childNodes:
126               if isinstance(n, minidom.Element):
127                   if n.tagName == 'Simulation':
128                            return (rank, Simulation.fromDom(self, n))
129                   elif n.tagName == 'Model':
130                            return (rank, self.getClassPath(n).fromDom(self, n))
131                   elif n.tagName == 'ParameterSet':
132                            return (rank, self.getClassPath(n).fromDom(self, n))
133                   else:
134                     raise ValueError("illegal component type %s"%n.tagName)
135           raise ValueError("cannot resolve Component")
136    
137    class ESySXMLCreator(object):
138        """
139        creates an XML Dom representation
140        """
141        def __init__(self):
142           self.__dom=minidom.Document()
143           self.__esys =self.__dom.createElement('ESys')
144           self.__dom.appendChild(self.__esys)
145           self.__linkable_object_registry={}
146           self.__number_sequence = itertools.count(100)
147        def getRoot(self):
148           return self.__esys
149        def createElement(self,name):
150          return self.__dom.createElement(name)
151        def createTextNode(self,name):
152          return self.__dom.createTextNode(name)
153        def getElementById(self,name):
154          return self.__dom.getElementById(name)
155        def createDataNode(self, tagName, data):
156              """
157              C{createDataNode}s are the building blocks of the xml documents constructed in
158              this module.  
159        
160              @param tagName: the associated xml tag
161              @param data: the values in the tag
162              """
163              n = self.createElement(tagName)
164              n.appendChild(self.createTextNode(str(data)))
165              return n
166        def getLinkableObjectId(self, obj):
167            for id, o in self.__linkable_object_registry.items():
168                if o == obj: return id
169            id =self.__number_sequence.next()
170            self.__linkable_object_registry[id]=obj
171            return id
172            
173        def registerLinkableObject(self, obj, node):
174            """
175            returns a unique object id for object obj
176            """
177            id=self.getLinkableObjectId(obj)
178            node.setAttribute('id',str(id))
179            node.setIdAttribute("id")
180    
181        def includeTargets(self):
182            target_written=True
183            while target_written:
184                targetsList =self.__dom.getElementsByTagName('Target')
185                target_written=False
186                for element in targetsList:
187                   targetId = int(element.firstChild.nodeValue.strip())
188                   if self.getElementById(str(targetId)): continue
189                   targetObj = self.__linkable_object_registry[targetId]
190                   targetObj.toDom(self, self.__esys)
191                   target_written=True
192    
193        def toprettyxml(self):
194            self.includeTargets()
195            return self.__dom.toprettyxml()
196    
197  class Link:  class Link:
198      """      """
199      A Link makes an attribute of an object callable::      A Link makes an attribute of an object callable::
# Line 159  class Link: Line 213  class Link:
213          self.target = target          self.target = target
214          self.attribute = None          self.attribute = None
215          self.setAttributeName(attribute)          self.setAttributeName(attribute)
216    
217        def getAttributeName(self):
218            """
219            returns the name of the attribute the link is pointing to
220            """
221            return self.attribute
222            
223      def setAttributeName(self,attribute):      def setAttributeName(self,attribute):
224          """          """
# Line 204  class Link: Line 264  class Link:
264          else:          else:
265              return out              return out
266    
267      def toDom(self, document, node):      def toDom(self, esysxml, node):
268          """          """
269          C{toDom} method of Link. Creates a Link node and appends it to the          C{toDom} method of Link. Creates a Link node and appends it to the
270      current XML document.      current XML esysxml.
271          """          """
272          link = document.createElement('Link')          link = esysxml.createElement('Link')
273          assert (self.target != None), ("Target was none, name was %r" % self.attribute)          assert (self.target != None), ("Target was none, name was %r" % self.attribute)
274          link.appendChild(dataNode(document, 'Target', self.target.id))          link.appendChild(esysxml.createDataNode('Target', esysxml.getLinkableObjectId(self.target)))
275          # this use of id will not work for purposes of being able to retrieve the intended          # this use of id will not work for purposes of being able to retrieve the intended
276          # target from the xml later. I need a better unique identifier.          # target from the xml later. I need a better unique identifier.
277          assert self.attribute, "You can't xmlify a Link without a target attribute"          assert self.attribute, "You can't xmlify a Link without a target attribute"
278          link.appendChild(dataNode(document, 'Attribute', self.attribute))          link.appendChild(esysxml.createDataNode('Attribute', self.attribute))
279          node.appendChild(link)          node.appendChild(link)
280    
281      def fromDom(cls, doc):      def fromDom(cls, esysxml, node):
282          targetid = doc.getElementsByTagName("Target")[0].firstChild.nodeValue.strip()          targetid = int(node.getElementsByTagName("Target")[0].firstChild.nodeValue.strip())
283          attribute = doc.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip()          attribute =str(node.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip())
284          l = cls(None, attribute)          l = cls(None, attribute)
285          registerLink(targetid, l)          esysxml.registerLink(targetid, l)
286          return l          return l
287    
288      fromDom = classmethod(fromDom)      fromDom = classmethod(fromDom)
289            
     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  
         """  
         print 'I got to the Link writeXML method'  
         document, rootnode = esysDoc()  
         self.toDom(document, rootnode)  
   
         ostream.write(document.toprettyxml())  
   
290  class LinkableObject(object):  class LinkableObject(object):
291      """      """
292      An object that allows to link its attributes to attributes of other objects      An object that allows to link its attributes to attributes of other objects
# Line 257  class LinkableObject(object): Line 305  class LinkableObject(object):
305      the return value of the call.      the return value of the call.
306      """      """
307        
     number_sequence = itertools.count(100)  
308            
309      def __init__(self, debug=False):      def __init__(self, id = None, debug=False):
310          """          """
311      Initializes LinkableObject so that we can operate on Links      Initializes LinkableObject so that we can operate on Links
312      """      """
313          self.debug = debug          self.debug = debug
314          self.__linked_attributes={}          self.__linked_attributes={}
315          self.id = self.number_sequence.next()          
         registerLinkableObject(self.id, self)  
   
316      def trace(self, msg):      def trace(self, msg):
317          """          """
318      If debugging is on, print the message, otherwise do nothing      If debugging is on, print the message, otherwise do nothing
# Line 364  class ParameterSet(LinkableObject): Line 409  class ParameterSet(LinkableObject):
409       - a ParameterSet object       - a ParameterSet object
410       - a Simulation object       - a Simulation object
411       - a Model object       - a Model object
412       - any other object (not considered by writeESySXML and writeXML)       - a numarray object
413             - a list of booleans
414            - any other object (not considered by writeESySXML and writeXML)
415            
416      Example how to create an ESySParameters object::      Example how to create an ESySParameters object::
417            
# Line 393  class ParameterSet(LinkableObject): Line 440  class ParameterSet(LinkableObject):
440          self.declareParameters(parameters)          self.declareParameters(parameters)
441    
442      def __repr__(self):      def __repr__(self):
443          return "<%s %r>" % (self.__class__.__name__,          return "<%s %d>"%(self.__class__.__name__,id(self))
                             [(p, getattr(self, p, None)) for p in self.parameters])  
444            
445      def declareParameter(self,**parameters):      def declareParameter(self,**parameters):
446          """          """
# Line 457  class ParameterSet(LinkableObject): Line 503  class ParameterSet(LinkableObject):
503          except:          except:
504              pass              pass
505    
506      def toDom(self, document, node):      def toDom(self, esysxml, node):
507          """          """
508      C{toDom} method of ParameterSet class.      C{toDom} method of Model class
509      """      """
510          pset = document.createElement('ParameterSet')          pset = esysxml.createElement('ParameterSet')
511            pset.setAttribute('type', self.__class__.__name__)
512            pset.setAttribute('module', self.__class__.__module__)
513            esysxml.registerLinkableObject(self, pset)
514            self._parametersToDom(esysxml, pset)
515          node.appendChild(pset)          node.appendChild(pset)
         self._parametersToDom(document, pset)  
516    
517      def _parametersToDom(self, document, node):      def _parametersToDom(self, esysxml, node):
         node.setAttribute('id', str(self.id))  
         node.setIdAttribute("id")  
518          for name,value in self:          for name,value in self:
519              param = document.createElement('Parameter')              # convert list to numarray when possible:
520              param.setAttribute('type', value.__class__.__name__)              if isinstance (value, list):
521                    elem_type=-1
522                    for i in value:
523                        if isinstance(i, bool):
524                            elem_type = max(elem_type,0)
525                        if isinstance(i, int) and not isinstance(i, bool):
526                            elem_type = max(elem_type,1)
527                        if isinstance(i, float):
528                            elem_type = max(elem_type,2)
529                    if elem_type == 0: value = numarray.array(value,numarray.Bool)
530                    if elem_type == 1: value = numarray.array(value,numarray.Int)
531                    if elem_type == 2: value = numarray.array(value,numarray.Float)
532    
533              param.appendChild(dataNode(document, 'Name', name))              param = esysxml.createElement('Parameter')
534                param.setAttribute('type', value.__class__.__name__)
535    
536              val = document.createElement('Value')              param.appendChild(esysxml.createDataNode('Name', name))
537    
538              if isinstance(value,ParameterSet):              val = esysxml.createElement('Value')
539                  value.toDom(document, val)              if isinstance(value,(ParameterSet,Link,DataSource)):
540                    value.toDom(esysxml, val)
541                  param.appendChild(val)                  param.appendChild(val)
542              elif isinstance(value, Link):              elif isinstance(value, numarray.NumArray):
543                  value.toDom(document, val)                  shape = value.getshape()
544                    if isinstance(shape, tuple):
545                        size = reduce(operator.mul, shape)
546                        shape = ' '.join(map(str, shape))
547                    else:
548                        size = shape
549                        shape = str(shape)
550    
551                    arraytype = value.type()
552                    if isinstance(arraytype, numarray.BooleanType):
553                          arraytype_str="Bool"
554                    elif isinstance(arraytype, numarray.IntegralType):
555                          arraytype_str="Int"
556                    elif isinstance(arraytype, numarray.FloatingType):
557                          arraytype_str="Float"
558                    elif isinstance(arraytype, numarray.ComplexType):
559                          arraytype_str="Complex"
560                    else:
561                          arraytype_str=str(arraytype)
562                    numarrayElement = esysxml.createElement('NumArray')
563                    numarrayElement.appendChild(esysxml.createDataNode('ArrayType', arraytype_str))
564                    numarrayElement.appendChild(esysxml.createDataNode('Shape', shape))
565                    numarrayElement.appendChild(esysxml.createDataNode('Data', ' '.join(
566                        [str(x) for x in numarray.reshape(value, size)])))
567                    val.appendChild(numarrayElement)
568                  param.appendChild(val)                  param.appendChild(val)
569              elif isinstance(value,StringType):              elif isinstance(value, list):
570                  param.appendChild(dataNode(document, 'Value', value))                  param.appendChild(esysxml.createDataNode('Value', ' '.join([str(x) for x in value]) ))
571                elif isinstance(value, (str, bool, int, float, type(None))):
572                    param.appendChild(esysxml.createDataNode('Value', str(value)))
573                elif isinstance(value, dict):
574                     dic = esysxml.createElement('dictionary')
575                     if len(value.keys())>0:
576                         dic.setAttribute('key_type', value.keys()[0].__class__.__name__)
577                         dic.setAttribute('value_type', value[value.keys()[0]].__class__.__name__)
578                     for k,v in value.items():
579                        i=esysxml.createElement('item')
580                        i.appendChild(esysxml.createDataNode('key', k))
581                        i.appendChild(esysxml.createDataNode('value', v))
582                        dic.appendChild(i)
583                     param.appendChild(dic)
584              else:              else:
585                  param.appendChild(dataNode(document, 'Value', str(value)))                  print value
586                    raise ValueError("cannot serialize %s type to XML."%str(value.__class__))
587    
588              node.appendChild(param)              node.appendChild(param)
589    
590      def fromDom(cls, doc):      def fromDom(cls, esysxml, node):
   
591          # Define a host of helper functions to assist us.          # Define a host of helper functions to assist us.
592          def _children(node):          def _children(node):
593              """              """
594              Remove the empty nodes from the children of this node.              Remove the empty nodes from the children of this node.
595              """              """
596              return [x for x in node.childNodes              ret = []
597                      if not isinstance(x, minidom.Text) or x.nodeValue.strip()]              for x in node.childNodes:
598                    if isinstance(x, minidom.Text):
599                        if x.nodeValue.strip():
600                            ret.append(x)
601                    else:
602                        ret.append(x)
603                return ret
604    
605          def _floatfromValue(doc):          def _floatfromValue(esysxml, node):
606              return float(doc.nodeValue.strip())              return float(node.nodeValue.strip())
607    
608          def _stringfromValue(doc):          def _stringfromValue(esysxml, node):
609              return str(doc.nodeValue.strip())              return str(node.nodeValue.strip())
610                
611          def _intfromValue(doc):          def _intfromValue(esysxml, node):
612              return int(doc.nodeValue.strip())              return int(node.nodeValue.strip())
613    
614          def _boolfromValue(doc):          def _boolfromValue(esysxml, node):
615              return bool(doc.nodeValue.strip())              return _boolfromstring(node.nodeValue.strip())
616    
617          def _nonefromValue(doc):          def _nonefromValue(esysxml, node):
618              return None              return None
619          
620            def _numarrayfromValue(esysxml, node):
621                for node in _children(node):
622                    if node.tagName == 'ArrayType':
623                        arraytype = node.firstChild.nodeValue.strip()
624                    if node.tagName == 'Shape':
625                        shape = node.firstChild.nodeValue.strip()
626                        shape = [int(x) for x in shape.split()]
627                    if node.tagName == 'Data':
628                        data = node.firstChild.nodeValue.strip()
629                        data = [float(x) for x in data.split()]
630                return numarray.reshape(numarray.array(data, type=getattr(numarray, arraytype)),
631                                        shape)
632          
633            def _listfromValue(esysxml, node):
634                return [x for x in node.nodeValue.split()]
635    
636            def _boolfromstring(s):
637                if s == 'True':
638                    return True
639                else:
640                    return False
641          # Mapping from text types in the xml to methods used to process trees of that type          # Mapping from text types in the xml to methods used to process trees of that type
642          ptypemap = {"Simulation": Simulation.fromDom,          ptypemap = {"Simulation": Simulation.fromDom,
643                      "Model":Model.fromDom,                      "Model":Model.fromDom,
644                      "ParameterSet":ParameterSet.fromDom,                      "ParameterSet":ParameterSet.fromDom,
645                      "Link":Link.fromDom,                      "Link":Link.fromDom,
646                        "DataSource":DataSource.fromDom,
647                      "float":_floatfromValue,                      "float":_floatfromValue,
648                      "int":_intfromValue,                      "int":_intfromValue,
649                      "str":_stringfromValue,                      "str":_stringfromValue,
650                      "bool":_boolfromValue,                      "bool":_boolfromValue,
651                      "NoneType":_nonefromValue                      "list":_listfromValue,
652                        "NumArray":_numarrayfromValue,
653                        "NoneType":_nonefromValue,
654                      }                      }
655    
 #        print doc.toxml()  
   
656          parameters = {}          parameters = {}
657          for node in _children(doc):          for n in _children(node):
658              ptype = node.getAttribute("type")              ptype = n.getAttribute("type")
659                if not ptypemap.has_key(ptype):
660                   raise KeyError("cannot handle parameter type %s."%ptype)
661    
662              pname = pvalue = None              pname = pvalue = None
663              for childnode in _children(node):              for childnode in _children(n):
   
664                  if childnode.tagName == "Name":                  if childnode.tagName == "Name":
665                      pname = childnode.firstChild.nodeValue.strip()                      pname = childnode.firstChild.nodeValue.strip()
666    
667                  if childnode.tagName == "Value":                  if childnode.tagName == "Value":
668                      nodes = _children(childnode)                      nodes = _children(childnode)
669                      pvalue = ptypemap[ptype](nodes[0])                      pvalue = ptypemap[ptype](esysxml, nodes[0])
670    
671              parameters[pname] = pvalue              parameters[pname] = pvalue
672    
673          # Create the instance of ParameterSet          # Create the instance of ParameterSet
674          o = cls()          o = cls(debug=esysxml.debug)
675          o.declareParameters(parameters)          o.declareParameters(parameters)
676          registerLinkableObject(doc.getAttribute("id"), o)          esysxml.registerLinkableObject(o, node)
677          return o          return o
678            
679      fromDom = classmethod(fromDom)      fromDom = classmethod(fromDom)
680        
681      def writeXML(self,ostream=stdout):      def writeXML(self,ostream=stdout):
682          """          """
683      Writes the object as an XML object into an output stream.      Writes the object as an XML object into an output stream.
684      """      """
685          # ParameterSet(d) with d[Name]=Value          esysxml=ESySXMLCreator()
686          document, node = esysDoc()          self.toDom(esysxml, esysxml.getRoot())
687          self.toDom(document, node)          ostream.write(esysxml.toprettyxml())
688          ostream.write(document.toprettyxml())      
   
689  class Model(ParameterSet):  class Model(ParameterSet):
690      """      """
691      A Model object represents a processess marching over time until a      A Model object represents a processess marching over time until a
692      finalizing condition is fullfilled. At each time step an iterative      finalizing condition is fullfilled. At each time step an iterative
693      process can be performed and the time step size can be controlled. A      process can be performed and the time step size can be controlled. A
694      Model has the following work flow::      Model has the following work flow::
695              
696            doInitialization()            doInitialization()
697              while not terminateInitialIteration(): doInitializationiStep()
698              doInitialPostprocessing()
699            while not finalize():            while not finalize():
700                 dt=getSafeTimeStepSize(dt)                 dt=getSafeTimeStepSize(dt)
701                 doStepPreprocessing(dt)                 doStepPreprocessing(dt)
# Line 585  class Model(ParameterSet): Line 712  class Model(ParameterSet):
712    
713      UNDEF_DT=1.e300      UNDEF_DT=1.e300
714    
715      def __init__(self,parameters=[],**kwarg):      def __init__(self,parameters=[],**kwargs):
716          """          """
717      Creates a model.      Creates a model.
718    
719          Just calls the parent constructor.          Just calls the parent constructor.
720          """          """
721          ParameterSet.__init__(self, parameters=parameters,**kwarg)          ParameterSet.__init__(self, parameters=parameters,**kwargs)
722    
723      def __str__(self):      def __str__(self):
724         return "<%s %d>"%(self.__class__,id(self))         return "<%s %d>"%(self.__class__.__name__,id(self))
725    
     def toDom(self, document, node):  
         """  
     C{toDom} method of Model class  
     """  
         pset = document.createElement('Model')  
         pset.setAttribute('type', self.__class__.__name__)  
         if not self.__class__.__module__.startswith('esys.escript'):  
             pset.setAttribute('module', self.__class__.__module__)  
         node.appendChild(pset)  
         self._parametersToDom(document, pset)  
726    
727      def doInitialization(self):      def doInitialization(self):
728          """          """
# Line 614  class Model(ParameterSet): Line 731  class Model(ParameterSet):
731      This function may be overwritten.      This function may be overwritten.
732      """      """
733          pass          pass
734        def doInitialStep(self):
735            """
736        performs an iteration step in the initialization phase
737    
738        This function may be overwritten.
739        """
740            pass
741    
742        def terminateInitialIteration(self):
743            """
744        Returns True if iteration at the inital phase is terminated.
745        """
746            return True
747    
748        def doInitialPostprocessing(self):
749            """
750        finalises the initialization iteration process
751    
752        This function may be overwritten.
753        """
754            pass
755            
756      def getSafeTimeStepSize(self,dt):      def getSafeTimeStepSize(self,dt):
757          """          """
# Line 664  class Model(ParameterSet): Line 802  class Model(ParameterSet):
802      Returns True if iteration on a time step is terminated.      Returns True if iteration on a time step is terminated.
803      """      """
804          return True          return True
805    
806                
807      def doStepPostprocessing(self,dt):      def doStepPostprocessing(self,dt):
808          """          """
809      Finalalizes the time step.      finalises the time step.
810    
811          dt is the currently used time step size.          dt is the currently used time step size.
812    
813          This function may be overwritten.          This function may be overwritten.
814      """      """
815          pass          pass
       
     def writeXML(self, ostream=stdout):  
         document, node = esysDoc()  
         self.toDom(document, node)  
         ostream.write(document.toprettyxml())  
       
816    
817        def toDom(self, esysxml, node):
818            """
819        C{toDom} method of Model class
820        """
821            pset = esysxml.createElement('Model')
822            pset.setAttribute('type', self.__class__.__name__)
823            pset.setAttribute('module', self.__class__.__module__)
824            esysxml.registerLinkableObject(self, pset)
825            node.appendChild(pset)
826            self._parametersToDom(esysxml, pset)
827        
828  class Simulation(Model):  class Simulation(Model):
829      """      """
830      A Simulation object is special Model which runs a sequence of Models.      A Simulation object is special Model which runs a sequence of Models.
# Line 693  class Simulation(Model): Line 837  class Simulation(Model):
837            
838      FAILED_TIME_STEPS_MAX=20      FAILED_TIME_STEPS_MAX=20
839      MAX_ITER_STEPS=50      MAX_ITER_STEPS=50
840        MAX_CHANGE_OF_DT=2.
841            
842      def __init__(self, models=[], **kwargs):      def __init__(self, models=[], **kwargs):
843          """          """
844      Initiates a simulation from a list of models.      Initiates a simulation from a list of models.
845      """      """
846          Model.__init__(self, **kwargs)          super(Simulation, self).__init__(**kwargs)
847          self.__models=[]          self.__models=[]
848                    
849          for i in range(len(models)):          for i in range(len(models)):
# Line 745  class Simulation(Model): Line 890  class Simulation(Model):
890      """      """
891          return len(self.__models)          return len(self.__models)
892    
     def toDom(self, document, node):  
         """  
     C{toDom} method of Simulation class.  
     """  
         simulation = document.createElement('Simulation')  
         simulation.setAttribute('type', self.__class__.__name__)  
   
         for rank, sim in enumerate(self.iterModels()):  
             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)  
         targetsList = document.getElementsByTagName('Target')  
           
         for element in targetsList:  
             targetId = int(element.firstChild.nodeValue.strip())  
             if document.getElementById(str(targetId)):  
                 continue  
             targetObj = LinkableObjectRegistry[targetId]  
             targetObj.toDom(document, rootnode)  
         ostream.write(document.toprettyxml())  
893            
894      def getSafeTimeStepSize(self,dt):      def getSafeTimeStepSize(self,dt):
895          """          """
# Line 785  class Simulation(Model): Line 898  class Simulation(Model):
898          This is the minimum over the time step sizes of all models.          This is the minimum over the time step sizes of all models.
899      """      """
900          out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])          out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
         #print "%s: safe step size is %e."%(str(self),out)  
901          return out          return out
902            
903      def doInitialization(self):      def doInitialization(self):
# Line 795  class Simulation(Model): Line 907  class Simulation(Model):
907          self.n=0          self.n=0
908          self.tn=0.          self.tn=0.
909          for o in self.iterModels():          for o in self.iterModels():
910              o.doInitialization()               o.doInitialization()
911            def doInitialStep(self):
912            """
913        performs an iteration step in the initialization step for all models
914        """
915            iter=0
916            while not self.terminateInitialIteration():
917                if iter==0: self.trace("iteration for initialization starts")
918                iter+=1
919                self.trace("iteration step %d"%(iter))
920                for o in self.iterModels():
921                     o.doInitialStep()
922                if iter>self.MAX_ITER_STEPS:
923                     raise IterationDivergenceError("initial iteration did not converge after %s steps."%iter)
924            self.trace("Initialization finalized after %s iteration steps."%iter)
925    
926        def doInitialPostprocessing(self):
927            """
928        finalises the initialization iteration process for all models.
929        """
930            for o in self.iterModels():
931                o.doInitialPostprocessing()
932      def finalize(self):      def finalize(self):
933          """          """
934      Returns True if any of the models is to be finalized.      Returns True if any of the models is to be finalized.
# Line 805  class Simulation(Model): Line 937  class Simulation(Model):
937                
938      def doFinalization(self):      def doFinalization(self):
939          """          """
940      Finalalizes the time stepping for all models.      finalises the time stepping for all models.
941      """      """
942          for i in self.iterModels(): i.doFinalization()          for i in self.iterModels(): i.doFinalization()
943          self.trace("end of time integation.")          self.trace("end of time integation.")
# Line 823  class Simulation(Model): Line 955  class Simulation(Model):
955      """      """
956          out=all([o.terminateIteration() for o in self.iterModels()])          out=all([o.terminateIteration() for o in self.iterModels()])
957          return out          return out
958    
959        def terminateInitialIteration(self):
960            """
961        Returns True if all initial iterations for all models are terminated.
962        """
963            out=all([o.terminateInitialIteration() for o in self.iterModels()])
964            return out
965                
966      def doStepPostprocessing(self,dt):      def doStepPostprocessing(self,dt):
967          """          """
968      Finalalizes the iteration process for all models.      finalises the iteration process for all models.
969      """      """
970          for o in self.iterModels():          for o in self.iterModels():
971              o.doStepPostprocessing(dt)              o.doStepPostprocessing(dt)
# Line 857  class Simulation(Model): Line 996  class Simulation(Model):
996      Run the simulation by performing essentially::      Run the simulation by performing essentially::
997            
998          self.doInitialization()          self.doInitialization()
999                while not self.terminateInitialIteration(): self.doInitialStep()
1000                self.doInitialPostprocessing()
1001          while not self.finalize():          while not self.finalize():
1002              dt=self.getSafeTimeStepSize()              dt=self.getSafeTimeStepSize()
1003              self.doStep(dt)              self.doStep(dt)
# Line 874  class Simulation(Model): Line 1015  class Simulation(Model):
1015          In both cases the time integration is given up after          In both cases the time integration is given up after
1016      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
1017          """          """
         dt=self.UNDEF_DT  
1018          self.doInitialization()          self.doInitialization()
1019            self.doInitialStep()
1020            self.doInitialPostprocessing()
1021            dt=self.UNDEF_DT
1022          while not self.finalize():          while not self.finalize():
1023              step_fail_counter=0              step_fail_counter=0
1024              iteration_fail_counter=0              iteration_fail_counter=0
1025              dt_new=self.getSafeTimeStepSize(dt)              if self.n==0:
1026                    dt_new=self.getSafeTimeStepSize(dt)
1027                else:
1028                    dt_new=min(max(self.getSafeTimeStepSize(dt),dt/self.MAX_CHANGE_OF_DT),dt*self.MAX_CHANGE_OF_DT)
1029              self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))              self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))
1030              end_of_step=False              end_of_step=False
1031              while not end_of_step:              while not end_of_step:
1032                 end_of_step=True                 end_of_step=True
1033                 if not dt_new>0:                 if not dt_new>0:
1034                    raise NonPositiveStepSizeError("non-positive step size in step %d",self.n+1)                    raise NonPositiveStepSizeError("non-positive step size in step %d"%(self.n+1))
1035                 try:                 try:
1036                    self.doStepPreprocessing(dt_new)                    self.doStepPreprocessing(dt_new)
1037                    self.doStep(dt_new)                    self.doStep(dt_new)
# Line 895  class Simulation(Model): Line 1041  class Simulation(Model):
1041                    end_of_step=False                    end_of_step=False
1042                    iteration_fail_counter+=1                    iteration_fail_counter+=1
1043                    if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:                    if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
1044                             raise SimulationBreakDownError("reduction of time step to achieve convergence failed.")                             raise SimulationBreakDownError("reduction of time step to achieve convergence failed after %s steps."%self.FAILED_TIME_STEPS_MAX)
1045                    self.trace("iteration fails. time step is repeated with new step size.")                    self.trace("Iteration failed. Time step is repeated with new step size %s."%dt_new)
1046                 except FailedTimeStepError:                 except FailedTimeStepError:
1047                    dt_new=self.getSafeTimeStepSize(dt)                    dt_new=self.getSafeTimeStepSize(dt)
1048                    end_of_step=False                    end_of_step=False
1049                    step_fail_counter+=1                    step_fail_counter+=1
1050                    self.trace("time step is repeated.")                    self.trace("Time step is repeated with new time step size %s."%dt_new)
1051                    if step_fail_counter>self.FAILED_TIME_STEPS_MAX:                    if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
1052                          raise SimulationBreakDownError("time integration is given up after %d attempts."%step_fail_counter)                          raise SimulationBreakDownError("Time integration is given up after %d attempts."%step_fail_counter)
1053              dt=dt_new              dt=dt_new
1054              if not check_point==None:              if not check_point==None:
1055                  if n%check_point==0:                  if n%check_point==0:
# Line 911  class Simulation(Model): Line 1057  class Simulation(Model):
1057                      self.writeXML()                      self.writeXML()
1058          self.doFinalization()          self.doFinalization()
1059    
     def fromDom(cls, doc):  
         sims = []  
         for node in doc.childNodes:  
             if isinstance(node, minidom.Text):  
                 continue  
1060    
1061              sims.append(getComponent(node))      def toDom(self, esysxml, node):
1062            """
1063        C{toDom} method of Simulation class.
1064        """
1065            simulation = esysxml.createElement('Simulation')
1066            esysxml.registerLinkableObject(self, simulation)
1067            for rank, sim in enumerate(self.iterModels()):
1068                component = esysxml.createElement('Component')
1069                component.setAttribute('rank', str(rank))
1070                sim.toDom(esysxml, component)
1071                simulation.appendChild(component)
1072            node.appendChild(simulation)
1073    
1074          return cls(sims)  
1075        def fromDom(cls, esysxml, node):
1076            sims = []
1077            for n in node.childNodes:
1078                if isinstance(n, minidom.Text):
1079                    continue
1080                sims.append(esysxml.getComponent(n))
1081            sims.sort(cmp=_comp)
1082            sim=cls([s[1] for s in sims], debug=esysxml.debug)
1083            esysxml.registerLinkableObject(sim, node)
1084            return sim
1085    
1086      fromDom = classmethod(fromDom)      fromDom = classmethod(fromDom)
1087    
1088    def _comp(a,b):
1089        if a[0]<a[1]:
1090          return 1
1091        elif a[0]>a[1]:
1092          return -1
1093        else:
1094          return 0
1095    
1096  class IterationDivergenceError(Exception):  class IterationDivergenceError(Exception):
1097      """      """
# Line 953  class NonPositiveStepSizeError(Exception Line 1122  class NonPositiveStepSizeError(Exception
1122      """      """
1123      pass      pass
1124    
1125    class DataSource(object):
1126        """
1127        Class for handling data sources, including local and remote files. This class is under development.
1128        """
1129    
1130        def __init__(self, uri="file.ext", fileformat="unknown"):
1131            self.uri = uri
1132            self.fileformat = fileformat
1133    
1134        def toDom(self, esysxml, node):
1135            """
1136            C{toDom} method of DataSource. Creates a DataSource node and appends it to the
1137        current XML esysxml.
1138            """
1139            ds = esysxml.createElement('DataSource')
1140            ds.appendChild(esysxml.createDataNode('URI', self.uri))
1141            ds.appendChild(esysxml.createDataNode('FileFormat', self.fileformat))
1142            node.appendChild(ds)
1143    
1144        def fromDom(cls, esysxml, node):
1145            uri= str(node.getElementsByTagName("URI")[0].firstChild.nodeValue.strip())
1146            fileformat= str(node.getElementsByTagName("FileFormat")[0].firstChild.nodeValue.strip())
1147            ds = cls(uri, fileformat)
1148            return ds
1149    
1150        def getLocalFileName(self):
1151            return self.uri
1152    
1153        fromDom = classmethod(fromDom)
1154        
1155  # vim: expandtab shiftwidth=4:  # vim: expandtab shiftwidth=4:

Legend:
Removed from v.728  
changed lines
  Added in v.926

  ViewVC Help
Powered by ViewVC 1.1.26