/[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 874 by elspeth, Tue Oct 17 12:06:11 2006 UTC revision 964 by gross, Tue Feb 13 05:10:26 2007 UTC
# Line 27  from sys import stdout Line 27  from sys import stdout
27  import numarray  import numarray
28  import operator  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 37  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 72  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 112  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.getElementsByTagName('ESys')[0]
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 161  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 getTarget(self):
218            """
219            returns the target
220            """
221            return self.target
222        def getAttributeName(self):
223            """
224            returns the name of the attribute the link is pointing to
225            """
226            return self.attribute
227            
228      def setAttributeName(self,attribute):      def setAttributeName(self,attribute):
229          """          """
# Line 206  class Link: Line 269  class Link:
269          else:          else:
270              return out              return out
271    
272      def toDom(self, document, node):      def toDom(self, esysxml, node):
273          """          """
274          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
275      current XML document.      current XML esysxml.
276          """          """
277          link = document.createElement('Link')          link = esysxml.createElement('Link')
278          assert (self.target != None), ("Target was none, name was %r" % self.attribute)          assert (self.target != None), ("Target was none, name was %r" % self.attribute)
279          link.appendChild(dataNode(document, 'Target', self.target.id))          link.appendChild(esysxml.createDataNode('Target', esysxml.getLinkableObjectId(self.target)))
280          # 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
281          # target from the xml later. I need a better unique identifier.          # target from the xml later. I need a better unique identifier.
282          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"
283          link.appendChild(dataNode(document, 'Attribute', self.attribute))          link.appendChild(esysxml.createDataNode('Attribute', self.attribute))
284          node.appendChild(link)          node.appendChild(link)
285    
286      def fromDom(cls, doc):      def fromDom(cls, esysxml, node):
287          targetid = doc.getElementsByTagName("Target")[0].firstChild.nodeValue.strip()          targetid = int(node.getElementsByTagName("Target")[0].firstChild.nodeValue.strip())
288          attribute = doc.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip()          attribute =str(node.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip())
289          l = cls(None, attribute)          l = cls(None, attribute)
290          registerLink(targetid, l)          esysxml.registerLink(targetid, l)
291          return l          return l
292    
293      fromDom = classmethod(fromDom)      fromDom = classmethod(fromDom)
294            
     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())  
   
295  class LinkableObject(object):  class LinkableObject(object):
296      """      """
297      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 259  class LinkableObject(object): Line 310  class LinkableObject(object):
310      the return value of the call.      the return value of the call.
311      """      """
312        
     number_sequence = itertools.count(100)  
313            
314      def __init__(self, debug=False):      def __init__(self, id = None, debug=False):
315          """          """
316      Initializes LinkableObject so that we can operate on Links      Initializes LinkableObject so that we can operate on Links
317      """      """
318          self.debug = debug          self.debug = debug
319          self.__linked_attributes={}          self.__linked_attributes={}
320          self.id = self.number_sequence.next()          
         registerLinkableObject(self.id, self)  
   
321      def trace(self, msg):      def trace(self, msg):
322          """          """
323      If debugging is on, print the message, otherwise do nothing      If debugging is on, print the message, otherwise do nothing
# Line 397  class ParameterSet(LinkableObject): Line 445  class ParameterSet(LinkableObject):
445          self.declareParameters(parameters)          self.declareParameters(parameters)
446    
447      def __repr__(self):      def __repr__(self):
448          return "<%s %r>" % (self.__class__.__name__,          return "<%s %d>"%(self.__class__.__name__,id(self))
                             [(p, getattr(self, p, None)) for p in self.parameters])  
449            
450      def declareParameter(self,**parameters):      def declareParameter(self,**parameters):
451          """          """
# Line 420  class ParameterSet(LinkableObject): Line 467  class ParameterSet(LinkableObject):
467              setattr(self,prm,value)              setattr(self,prm,value)
468              self.parameters.add(prm)              self.parameters.add(prm)
469    
             self.trace("parameter %s has been declared."%prm)  
   
470      def releaseParameters(self,name):      def releaseParameters(self,name):
471          """          """
472      Removes parameter name from the paramameters.      Removes parameter name from the paramameters.
# Line 429  class ParameterSet(LinkableObject): Line 474  class ParameterSet(LinkableObject):
474          if self.isParameter(name):          if self.isParameter(name):
475              self.parameters.remove(name)              self.parameters.remove(name)
476              self.trace("parameter %s has been removed."%name)              self.trace("parameter %s has been removed."%name)
477    
478        def checkLinkTargets(self, models, hash):
479            """
480            returns a set of tuples ("<self>(<name>)", <target model>) if the parameter <name> is linked to model <target model>
481            but <target model> is not in the list models. If the a parameter is linked to another parameter set which is not in the hash list
482            the parameter set is checked for its models. hash gives the call history.
483            """
484            out=set()
485            for name, value in self:
486                if isinstance(value, Link):
487                   m=value.getTarget()
488                   if isinstance(m, Model):
489                       if not m in models: out.add( (str(self)+"("+name+")",m) )
490                   elif isinstance(m, ParameterSet) and not m in hash:
491                         out|=set( [ (str(self)+"("+name+")."+f[0],f[1]) for f in m.checkLinkTargets(models, hash+[ self ] ) ] )
492            return out
493            
494      def __iter__(self):      def __iter__(self):
495          """          """
# Line 461  class ParameterSet(LinkableObject): Line 522  class ParameterSet(LinkableObject):
522          except:          except:
523              pass              pass
524    
525      def toDom(self, document, node):      def toDom(self, esysxml, node):
526          """          """
527      C{toDom} method of ParameterSet class.      C{toDom} method of Model class
528      """      """
529          pset = document.createElement('ParameterSet')          pset = esysxml.createElement('ParameterSet')
530            pset.setAttribute('type', self.__class__.__name__)
531            pset.setAttribute('module', self.__class__.__module__)
532            esysxml.registerLinkableObject(self, pset)
533            self._parametersToDom(esysxml, pset)
534          node.appendChild(pset)          node.appendChild(pset)
         self._parametersToDom(document, pset)  
535    
536      def _parametersToDom(self, document, node):      def _parametersToDom(self, esysxml, node):
         node.setAttribute('id', str(self.id))  
         node.setIdAttribute("id")  
537          for name,value in self:          for name,value in self:
538              param = document.createElement('Parameter')              # convert list to numarray when possible:
539              param.setAttribute('type', value.__class__.__name__)              if isinstance (value, list):
540                    elem_type=-1
541                    for i in value:
542                        if isinstance(i, bool):
543                            elem_type = max(elem_type,0)
544                        elif isinstance(i, int):
545                            elem_type = max(elem_type,1)
546                        elif isinstance(i, float):
547                            elem_type = max(elem_type,2)
548                    if elem_type == 0: value = numarray.array(value,numarray.Bool)
549                    if elem_type == 1: value = numarray.array(value,numarray.Int)
550                    if elem_type == 2: value = numarray.array(value,numarray.Float)
551    
552              param.appendChild(dataNode(document, 'Name', name))              param = esysxml.createElement('Parameter')
553                param.setAttribute('type', value.__class__.__name__)
554    
555              val = document.createElement('Value')              param.appendChild(esysxml.createDataNode('Name', name))
556    
557              if isinstance(value,(ParameterSet,Link)):              val = esysxml.createElement('Value')
558                  value.toDom(document, val)              if isinstance(value,(ParameterSet,Link,DataSource)):
559                    value.toDom(esysxml, val)
560                  param.appendChild(val)                  param.appendChild(val)
561              elif isinstance(value, numarray.NumArray):              elif isinstance(value, numarray.NumArray):
562                  shape = value.getshape()                  shape = value.getshape()
# Line 493  class ParameterSet(LinkableObject): Line 568  class ParameterSet(LinkableObject):
568                      shape = str(shape)                      shape = str(shape)
569    
570                  arraytype = value.type()                  arraytype = value.type()
571                  numarrayElement = document.createElement('NumArray')                  if isinstance(arraytype, numarray.BooleanType):
572                  numarrayElement.appendChild(dataNode(document, 'ArrayType', str(arraytype)))                        arraytype_str="Bool"
573                  numarrayElement.appendChild(dataNode(document, 'Shape', shape))                  elif isinstance(arraytype, numarray.IntegralType):
574                  numarrayElement.appendChild(dataNode(document, 'Data', ' '.join(                        arraytype_str="Int"
575                    elif isinstance(arraytype, numarray.FloatingType):
576                          arraytype_str="Float"
577                    elif isinstance(arraytype, numarray.ComplexType):
578                          arraytype_str="Complex"
579                    else:
580                          arraytype_str=str(arraytype)
581                    numarrayElement = esysxml.createElement('NumArray')
582                    numarrayElement.appendChild(esysxml.createDataNode('ArrayType', arraytype_str))
583                    numarrayElement.appendChild(esysxml.createDataNode('Shape', shape))
584                    numarrayElement.appendChild(esysxml.createDataNode('Data', ' '.join(
585                      [str(x) for x in numarray.reshape(value, size)])))                      [str(x) for x in numarray.reshape(value, size)])))
586                  val.appendChild(numarrayElement)                  val.appendChild(numarrayElement)
587                  param.appendChild(val)                  param.appendChild(val)
588              elif isinstance (value, list):              elif isinstance(value, list):
589                  param.appendChild(dataNode(document, 'Value', ' '.join(                  param.appendChild(esysxml.createDataNode('Value', ' '.join([str(x) for x in value]) ))
590                      [str(x) for x in value])              elif isinstance(value, (str, bool, int, float, type(None))):
591                  ))                  param.appendChild(esysxml.createDataNode('Value', str(value)))
592                elif isinstance(value, dict):
593                     dic = esysxml.createElement('dictionary')
594                     if len(value.keys())>0:
595                         dic.setAttribute('key_type', value.keys()[0].__class__.__name__)
596                         dic.setAttribute('value_type', value[value.keys()[0]].__class__.__name__)
597                     for k,v in value.items():
598                        i=esysxml.createElement('item')
599                        i.appendChild(esysxml.createDataNode('key', k))
600                        i.appendChild(esysxml.createDataNode('value', v))
601                        dic.appendChild(i)
602                     param.appendChild(dic)
603              else:              else:
604                  param.appendChild(dataNode(document, 'Value', str(value)))                  raise ValueError("cannot serialize %s type to XML."%str(value.__class__))
605    
606              node.appendChild(param)              node.appendChild(param)
607    
608      def fromDom(cls, doc):      def fromDom(cls, esysxml, node):
   
609          # Define a host of helper functions to assist us.          # Define a host of helper functions to assist us.
610          def _children(node):          def _children(node):
611              """              """
# Line 525  class ParameterSet(LinkableObject): Line 620  class ParameterSet(LinkableObject):
620                      ret.append(x)                      ret.append(x)
621              return ret              return ret
622    
623          def _floatfromValue(doc):          def _floatfromValue(esysxml, node):
624              return float(doc.nodeValue.strip())              return float(node.nodeValue.strip())
625    
626          def _stringfromValue(doc):          def _stringfromValue(esysxml, node):
627              return str(doc.nodeValue.strip())              return str(node.nodeValue.strip())
628                
629          def _intfromValue(doc):          def _intfromValue(esysxml, node):
630              return int(doc.nodeValue.strip())              return int(node.nodeValue.strip())
631    
632          def _boolfromValue(doc):          def _boolfromValue(esysxml, node):
633              return _boolfromstring(doc.nodeValue.strip())              return _boolfromstring(node.nodeValue.strip())
634    
635          def _nonefromValue(doc):          def _nonefromValue(esysxml, node):
636              return None              return None
637    
638          def _numarrayfromValue(doc):          def _numarrayfromValue(esysxml, node):
639              for node in _children(doc):              for node in _children(node):
640                  if node.tagName == 'ArrayType':                  if node.tagName == 'ArrayType':
641                      arraytype = node.firstChild.nodeValue.strip()                      arraytype = node.firstChild.nodeValue.strip()
642                  if node.tagName == 'Shape':                  if node.tagName == 'Shape':
# Line 553  class ParameterSet(LinkableObject): Line 648  class ParameterSet(LinkableObject):
648              return numarray.reshape(numarray.array(data, type=getattr(numarray, arraytype)),              return numarray.reshape(numarray.array(data, type=getattr(numarray, arraytype)),
649                                      shape)                                      shape)
650                
651          def _listfromValue(doc):          def _listfromValue(esysxml, node):
652              return [_boolfromstring(x) for x in doc.nodeValue.split()]              return [x for x in node.nodeValue.split()]
   
653    
654          def _boolfromstring(s):          def _boolfromstring(s):
655              if s == 'True':              if s == 'True':
# Line 567  class ParameterSet(LinkableObject): Line 661  class ParameterSet(LinkableObject):
661                      "Model":Model.fromDom,                      "Model":Model.fromDom,
662                      "ParameterSet":ParameterSet.fromDom,                      "ParameterSet":ParameterSet.fromDom,
663                      "Link":Link.fromDom,                      "Link":Link.fromDom,
664                        "DataSource":DataSource.fromDom,
665                      "float":_floatfromValue,                      "float":_floatfromValue,
666                      "int":_intfromValue,                      "int":_intfromValue,
667                      "str":_stringfromValue,                      "str":_stringfromValue,
# Line 576  class ParameterSet(LinkableObject): Line 671  class ParameterSet(LinkableObject):
671                      "NoneType":_nonefromValue,                      "NoneType":_nonefromValue,
672                      }                      }
673    
 #        print doc.toxml()  
   
674          parameters = {}          parameters = {}
675          for node in _children(doc):          for n in _children(node):
676              ptype = node.getAttribute("type")              ptype = n.getAttribute("type")
677                if not ptypemap.has_key(ptype):
678                   raise KeyError("cannot handle parameter type %s."%ptype)
679    
680              pname = pvalue = None              pname = pvalue = None
681              for childnode in _children(node):              for childnode in _children(n):
   
682                  if childnode.tagName == "Name":                  if childnode.tagName == "Name":
683                      pname = childnode.firstChild.nodeValue.strip()                      pname = childnode.firstChild.nodeValue.strip()
684    
685                  if childnode.tagName == "Value":                  if childnode.tagName == "Value":
686                      nodes = _children(childnode)                      nodes = _children(childnode)
687                  #    if ptype == 'NumArray':                      pvalue = ptypemap[ptype](esysxml, nodes[0])
                  #       pvalue = _numarrayfromValue(nodes)  
                  #   else:  
                     pvalue = ptypemap[ptype](nodes[0])  
688    
689              parameters[pname] = pvalue              parameters[pname] = pvalue
690    
691          # Create the instance of ParameterSet          # Create the instance of ParameterSet
692          o = cls()          o = cls(debug=esysxml.debug)
693          o.declareParameters(parameters)          o.declareParameters(parameters)
694          registerLinkableObject(doc.getAttribute("id"), o)          esysxml.registerLinkableObject(o, node)
695          return o          return o
696            
697      fromDom = classmethod(fromDom)      fromDom = classmethod(fromDom)
698        
699      def writeXML(self,ostream=stdout):      def writeXML(self,ostream=stdout):
700          """          """
701      Writes the object as an XML object into an output stream.      Writes the object as an XML object into an output stream.
702      """      """
703          # ParameterSet(d) with d[Name]=Value          esysxml=ESySXMLCreator()
704          document, node = esysDoc()          self.toDom(esysxml, esysxml.getRoot())
705          self.toDom(document, node)          ostream.write(esysxml.toprettyxml())
706          ostream.write(document.toprettyxml())      
   
707  class Model(ParameterSet):  class Model(ParameterSet):
708      """      """
709      A Model object represents a processess marching over time until a      A Model object represents a processess marching over time until a
710      finalizing condition is fullfilled. At each time step an iterative      finalizing condition is fullfilled. At each time step an iterative
711      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
712      Model has the following work flow::      Model has the following work flow::
713              
714            doInitialization()            doInitialization()
715              while not terminateInitialIteration(): doInitializationiStep()
716              doInitialPostprocessing()
717            while not finalize():            while not finalize():
718                 dt=getSafeTimeStepSize(dt)                 dt=getSafeTimeStepSize(dt)
719                 doStepPreprocessing(dt)                 doStepPreprocessing(dt)
# Line 638  class Model(ParameterSet): Line 730  class Model(ParameterSet):
730    
731      UNDEF_DT=1.e300      UNDEF_DT=1.e300
732    
733      def __init__(self,parameters=[],**kwarg):      def __init__(self,parameters=[],**kwargs):
734          """          """
735      Creates a model.      Creates a model.
736    
737          Just calls the parent constructor.          Just calls the parent constructor.
738          """          """
739          ParameterSet.__init__(self, parameters=parameters,**kwarg)          ParameterSet.__init__(self, parameters=parameters,**kwargs)
740    
741      def __str__(self):      def __str__(self):
742         return "<%s %d>"%(self.__class__,id(self))         return "<%s %d>"%(self.__class__.__name__,id(self))
743    
     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)  
744    
745      def doInitialization(self):      def doInitialization(self):
746          """          """
# Line 667  class Model(ParameterSet): Line 749  class Model(ParameterSet):
749      This function may be overwritten.      This function may be overwritten.
750      """      """
751          pass          pass
752        def doInitialStep(self):
753            """
754        performs an iteration step in the initialization phase
755    
756        This function may be overwritten.
757        """
758            pass
759    
760        def terminateInitialIteration(self):
761            """
762        Returns True if iteration at the inital phase is terminated.
763        """
764            return True
765    
766        def doInitialPostprocessing(self):
767            """
768        finalises the initialization iteration process
769    
770        This function may be overwritten.
771        """
772            pass
773            
774      def getSafeTimeStepSize(self,dt):      def getSafeTimeStepSize(self,dt):
775          """          """
# Line 717  class Model(ParameterSet): Line 820  class Model(ParameterSet):
820      Returns True if iteration on a time step is terminated.      Returns True if iteration on a time step is terminated.
821      """      """
822          return True          return True
823    
824                
825      def doStepPostprocessing(self,dt):      def doStepPostprocessing(self,dt):
826          """          """
827      Finalalizes the time step.      finalises the time step.
828    
829          dt is the currently used time step size.          dt is the currently used time step size.
830    
831          This function may be overwritten.          This function may be overwritten.
832      """      """
833          pass          pass
       
     def writeXML(self, ostream=stdout):  
         document, node = esysDoc()  
         self.toDom(document, node)  
         ostream.write(document.toprettyxml())  
       
834    
835        def toDom(self, esysxml, node):
836            """
837        C{toDom} method of Model class
838        """
839            pset = esysxml.createElement('Model')
840            pset.setAttribute('type', self.__class__.__name__)
841            pset.setAttribute('module', self.__class__.__module__)
842            esysxml.registerLinkableObject(self, pset)
843            node.appendChild(pset)
844            self._parametersToDom(esysxml, pset)
845        
846  class Simulation(Model):  class Simulation(Model):
847      """      """
848      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 752  class Simulation(Model): Line 861  class Simulation(Model):
861          """          """
862      Initiates a simulation from a list of models.      Initiates a simulation from a list of models.
863      """      """
864          Model.__init__(self, **kwargs)          super(Simulation, self).__init__(**kwargs)
865            for m in models:
866                if not isinstance(m, Model):
867                     raise TypeError("%s is not a subclass of Model."%m)
868          self.__models=[]          self.__models=[]
           
869          for i in range(len(models)):          for i in range(len(models)):
870              self[i] = models[i]              self[i] = models[i]
871                            
# Line 799  class Simulation(Model): Line 910  class Simulation(Model):
910      """      """
911          return len(self.__models)          return len(self.__models)
912    
913      def toDom(self, document, node):      def getAllModels(self):
914          """          """
915      C{toDom} method of Simulation class.          returns a list of all models used in the Simulation including subsimulations
916      """          """
917          simulation = document.createElement('Simulation')          out=[]
918          simulation.setAttribute('type', self.__class__.__name__)          for m in self.iterModels():
919                if isinstance(m, Simulation):
920          for rank, sim in enumerate(self.iterModels()):                 out+=m.getAllModels()
921              component = document.createElement('Component')              else:
922              component.setAttribute('rank', str(rank))                 out.append(m)
923            return list(set(out))
             sim.toDom(document, component)  
   
             simulation.appendChild(component)  
   
         node.appendChild(simulation)  
924    
925      def writeXML(self,ostream=stdout):      def checkModels(self, models, hash):
926          """          """
927      Writes the object as an XML object into an output stream.          returns a list of (model,parameter, target model ) if the the parameter of model
928      """          is linking to the target_model which is not in list of models.
929          document, rootnode = esysDoc()          """
930          self.toDom(document, rootnode)          out=self.checkLinkTargets(models, hash + [self])
931          targetsList = document.getElementsByTagName('Target')          for m in self.iterModels():
932                        if isinstance(m, Simulation):
933          for element in targetsList:                   out|=m.checkModels(models, hash)
934              targetId = int(element.firstChild.nodeValue.strip())              else:
935              if document.getElementById(str(targetId)):                   out|=m.checkLinkTargets(models, hash + [self])
936                  continue          return set( [ (str(self)+"."+f[0],f[1]) for f in out ] )
937              targetObj = LinkableObjectRegistry[targetId]  
             targetObj.toDom(document, rootnode)  
         ostream.write(document.toprettyxml())  
938            
939      def getSafeTimeStepSize(self,dt):      def getSafeTimeStepSize(self,dt):
940          """          """
# Line 839  class Simulation(Model): Line 943  class Simulation(Model):
943          This is the minimum over the time step sizes of all models.          This is the minimum over the time step sizes of all models.
944      """      """
945          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)  
946          return out          return out
947            
948      def doInitialization(self):      def doInitialization(self):
# Line 849  class Simulation(Model): Line 952  class Simulation(Model):
952          self.n=0          self.n=0
953          self.tn=0.          self.tn=0.
954          for o in self.iterModels():          for o in self.iterModels():
955              o.doInitialization()               o.doInitialization()
956            def doInitialStep(self):
957            """
958        performs an iteration step in the initialization step for all models
959        """
960            iter=0
961            while not self.terminateInitialIteration():
962                if iter==0: self.trace("iteration for initialization starts")
963                iter+=1
964                self.trace("iteration step %d"%(iter))
965                for o in self.iterModels():
966                     o.doInitialStep()
967                if iter>self.MAX_ITER_STEPS:
968                     raise IterationDivergenceError("initial iteration did not converge after %s steps."%iter)
969            self.trace("Initialization finalized after %s iteration steps."%iter)
970    
971        def doInitialPostprocessing(self):
972            """
973        finalises the initialization iteration process for all models.
974        """
975            for o in self.iterModels():
976                o.doInitialPostprocessing()
977      def finalize(self):      def finalize(self):
978          """          """
979      Returns True if any of the models is to be finalized.      Returns True if any of the models is to be finalized.
# Line 859  class Simulation(Model): Line 982  class Simulation(Model):
982                
983      def doFinalization(self):      def doFinalization(self):
984          """          """
985      Finalalizes the time stepping for all models.      finalises the time stepping for all models.
986      """      """
987          for i in self.iterModels(): i.doFinalization()          for i in self.iterModels(): i.doFinalization()
988          self.trace("end of time integation.")          self.trace("end of time integation.")
# Line 877  class Simulation(Model): Line 1000  class Simulation(Model):
1000      """      """
1001          out=all([o.terminateIteration() for o in self.iterModels()])          out=all([o.terminateIteration() for o in self.iterModels()])
1002          return out          return out
1003    
1004        def terminateInitialIteration(self):
1005            """
1006        Returns True if all initial iterations for all models are terminated.
1007        """
1008            out=all([o.terminateInitialIteration() for o in self.iterModels()])
1009            return out
1010                
1011      def doStepPostprocessing(self,dt):      def doStepPostprocessing(self,dt):
1012          """          """
1013      Finalalizes the iteration process for all models.      finalises the iteration process for all models.
1014      """      """
1015          for o in self.iterModels():          for o in self.iterModels():
1016              o.doStepPostprocessing(dt)              o.doStepPostprocessing(dt)
# Line 911  class Simulation(Model): Line 1041  class Simulation(Model):
1041      Run the simulation by performing essentially::      Run the simulation by performing essentially::
1042            
1043          self.doInitialization()          self.doInitialization()
1044                while not self.terminateInitialIteration(): self.doInitialStep()
1045                self.doInitialPostprocessing()
1046          while not self.finalize():          while not self.finalize():
1047              dt=self.getSafeTimeStepSize()              dt=self.getSafeTimeStepSize()
1048              self.doStep(dt)              self.doStep(dt)
# Line 928  class Simulation(Model): Line 1060  class Simulation(Model):
1060          In both cases the time integration is given up after          In both cases the time integration is given up after
1061      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
1062          """          """
1063          dt=self.UNDEF_DT          # check the completness of the models:
1064            # first a list of all the models involved in the simulation including subsimulations:
1065            #
1066            missing=self.checkModels(self.getAllModels(), [])
1067            if len(missing)>0:
1068                msg=""
1069                for l in missing:
1070                     msg+="\n\t"+str(l[1])+" at "+l[0]
1071                raise MissingLink("link targets missing in the Simulation: %s"%msg)
1072            #==============================
1073          self.doInitialization()          self.doInitialization()
1074            self.doInitialStep()
1075            self.doInitialPostprocessing()
1076            dt=self.UNDEF_DT
1077          while not self.finalize():          while not self.finalize():
1078              step_fail_counter=0              step_fail_counter=0
1079              iteration_fail_counter=0              iteration_fail_counter=0
# Line 968  class Simulation(Model): Line 1112  class Simulation(Model):
1112                      self.writeXML()                      self.writeXML()
1113          self.doFinalization()          self.doFinalization()
1114    
     def fromDom(cls, doc):  
         sims = []  
         for node in doc.childNodes:  
             if isinstance(node, minidom.Text):  
                 continue  
1115    
1116              sims.append(getComponent(node))      def toDom(self, esysxml, node):
1117            """
1118        C{toDom} method of Simulation class.
1119        """
1120            simulation = esysxml.createElement('Simulation')
1121            esysxml.registerLinkableObject(self, simulation)
1122            for rank, sim in enumerate(self.iterModels()):
1123                component = esysxml.createElement('Component')
1124                component.setAttribute('rank', str(rank))
1125                sim.toDom(esysxml, component)
1126                simulation.appendChild(component)
1127            node.appendChild(simulation)
1128    
1129    
1130          return cls(sims)      def fromDom(cls, esysxml, node):
1131            sims = []
1132            for n in node.childNodes:
1133                if isinstance(n, minidom.Text):
1134                    continue
1135                sims.append(esysxml.getComponent(n))
1136            sims.sort(cmp=_comp)
1137            sim=cls([s[1] for s in sims], debug=esysxml.debug)
1138            esysxml.registerLinkableObject(sim, node)
1139            return sim
1140    
1141      fromDom = classmethod(fromDom)      fromDom = classmethod(fromDom)
1142    
1143    def _comp(a,b):
1144        if a[0]<a[1]:
1145          return 1
1146        elif a[0]>a[1]:
1147          return -1
1148        else:
1149          return 0
1150    
1151  class IterationDivergenceError(Exception):  class IterationDivergenceError(Exception):
1152      """      """
# Line 1010  class NonPositiveStepSizeError(Exception Line 1177  class NonPositiveStepSizeError(Exception
1177      """      """
1178      pass      pass
1179    
1180    class MissingLink(Exception):
1181        """
1182        Exception thrown when a link is missing
1183        """
1184        pass
1185    
1186    class DataSource(object):
1187        """
1188        Class for handling data sources, including local and remote files. This class is under development.
1189        """
1190    
1191        def __init__(self, uri="file.ext", fileformat="unknown"):
1192            self.uri = uri
1193            self.fileformat = fileformat
1194    
1195        def toDom(self, esysxml, node):
1196            """
1197            C{toDom} method of DataSource. Creates a DataSource node and appends it to the
1198        current XML esysxml.
1199            """
1200            ds = esysxml.createElement('DataSource')
1201            ds.appendChild(esysxml.createDataNode('URI', self.uri))
1202            ds.appendChild(esysxml.createDataNode('FileFormat', self.fileformat))
1203            node.appendChild(ds)
1204    
1205        def fromDom(cls, esysxml, node):
1206            uri= str(node.getElementsByTagName("URI")[0].firstChild.nodeValue.strip())
1207            fileformat= str(node.getElementsByTagName("FileFormat")[0].firstChild.nodeValue.strip())
1208            ds = cls(uri, fileformat)
1209            return ds
1210    
1211        def getLocalFileName(self):
1212            return self.uri
1213    
1214        fromDom = classmethod(fromDom)
1215        
1216  # vim: expandtab shiftwidth=4:  # vim: expandtab shiftwidth=4:

Legend:
Removed from v.874  
changed lines
  Added in v.964

  ViewVC Help
Powered by ViewVC 1.1.26