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

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

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

trunk/esys2/escript/py_src/modelframe.py revision 149 by jgs, Thu Sep 1 03:31:39 2005 UTC trunk/escript/py_src/modelframe.py revision 908 by gross, Thu Nov 23 06:39:39 2006 UTC
# Line 1  Line 1 
1  # $Id$  # $Id$
2    
3    """
4    Environment for implementing models in escript
5    
6    @var __author__: name of author
7    @var __copyright__: copyrights
8    @var __license__: licence agreement
9    @var __url__: url entry point on documentation
10    @var __version__: version
11    @var __date__: date of the version
12    """
13    
14    __author__="Lutz Gross, l.gross@uq.edu.au"
15    __copyright__="""  Copyright (c) 2006 by ACcESS MNRF
16                        http://www.access.edu.au
17                    Primary Business: Queensland, Australia"""
18    __license__="""Licensed under the Open Software License version 3.0
19                 http://www.opensource.org/licenses/osl-3.0.php"""
20    __url__="http://www.iservo.edu.au/esys"
21    __version__="$Revision$"
22    __date__="$Date$"
23    
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
30  # import modellib  temporarily removed!!!  # import modellib  temporarily removed!!!
31    
# Line 73  def parse(xml): Line 97  def parse(xml):
97    
98      return sim      return sim
99    
100    def importName(modulename, name):
101        """ Import a named object from a module in the context of this function,
102            which means you should use fully qualified module paths.
103            
104            Return None on failure.
105    
106            This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241
107        """
108        module = __import__(modulename, globals(), locals(), [name])
109            
110        try:
111            return vars(module)[name]
112        except KeyError:
113            raise ImportError("Could not import %s from %s" % (name, modulename))
114    
115  def getComponent(doc):  def getComponent(doc):
116      """      """
117      Used to get components of Simualtions, Models.      Used to get components of Simualtions, Models.
# Line 84  def getComponent(doc): Line 123  def getComponent(doc):
123                  if node.getAttribute("type") == 'Simulation':                  if node.getAttribute("type") == 'Simulation':
124                      return Simulation.fromDom(node)                      return Simulation.fromDom(node)
125              if node.tagName == 'Model':              if node.tagName == 'Model':
126                  model_type = node.getAttribute("type")                  if (node.getAttribute("module")):
127                  model_subclasses = Model.__subclasses__()                      model_module = node.getAttribute("module")
128                  for model in model_subclasses:                      model_type = node.getAttribute("type")
129                      if model_type == model.__name__:                      return importName(model_module, model_type).fromDom(node)
130                          return Model.fromDom(node)                  else:
131                        model_type = node.getAttribute("type")
132                        model_subclasses = Model.__subclasses__()
133                        for model in model_subclasses:
134                            if model_type == model.__name__:
135                                return Model.fromDom(node)
136              if node.tagName == 'ParameterSet':              if node.tagName == 'ParameterSet':
137                  parameter_type = node.getAttribute("type")                  parameter_type = node.getAttribute("type")
138                  return ParameterSet.fromDom(node)                  return ParameterSet.fromDom(node)
# Line 322  class ParameterSet(LinkableObject): Line 366  class ParameterSet(LinkableObject):
366       - a ParameterSet object       - a ParameterSet object
367       - a Simulation object       - a Simulation object
368       - a Model object       - a Model object
369       - any other object (not considered by writeESySXML and writeXML)       - a numarray object
370             - a list of booleans
371            - any other object (not considered by writeESySXML and writeXML)
372            
373      Example how to create an ESySParameters object::      Example how to create an ESySParameters object::
374            
# Line 351  class ParameterSet(LinkableObject): Line 397  class ParameterSet(LinkableObject):
397          self.declareParameters(parameters)          self.declareParameters(parameters)
398    
399      def __repr__(self):      def __repr__(self):
400          return "<%s %r>" % (self.__class__.__name__,          return "<%s %d>"%(self.__class__.__name__,id(self))
                             [(p, getattr(self, p, None)) for p in self.parameters])  
401            
402      def declareParameter(self,**parameters):      def declareParameter(self,**parameters):
403          """          """
# Line 424  class ParameterSet(LinkableObject): Line 469  class ParameterSet(LinkableObject):
469          self._parametersToDom(document, pset)          self._parametersToDom(document, pset)
470    
471      def _parametersToDom(self, document, node):      def _parametersToDom(self, document, node):
472          node.setAttribute ('id', str(self.id))          node.setAttribute('id', str(self.id))
473            node.setIdAttribute("id")
474          for name,value in self:          for name,value in self:
475              param = document.createElement('Parameter')              param = document.createElement('Parameter')
476              param.setAttribute('type', value.__class__.__name__)              param.setAttribute('type', value.__class__.__name__)
# Line 433  class ParameterSet(LinkableObject): Line 479  class ParameterSet(LinkableObject):
479    
480              val = document.createElement('Value')              val = document.createElement('Value')
481    
482              if isinstance(value,ParameterSet):              if isinstance(value,(ParameterSet,Link,DataSource)):
483                  value.toDom(document, val)                  value.toDom(document, val)
484                  param.appendChild(val)                  param.appendChild(val)
485              elif isinstance(value, Link):              elif isinstance(value, numarray.NumArray):
486                  value.toDom(document, val)                  shape = value.getshape()
487                    if isinstance(shape, tuple):
488                        size = reduce(operator.mul, shape)
489                        shape = ' '.join(map(str, shape))
490                    else:
491                        size = shape
492                        shape = str(shape)
493    
494                    arraytype = value.type()
495                    numarrayElement = document.createElement('NumArray')
496                    numarrayElement.appendChild(dataNode(document, 'ArrayType', str(arraytype)))
497                    numarrayElement.appendChild(dataNode(document, 'Shape', shape))
498                    numarrayElement.appendChild(dataNode(document, 'Data', ' '.join(
499                        [str(x) for x in numarray.reshape(value, size)])))
500                    val.appendChild(numarrayElement)
501                  param.appendChild(val)                  param.appendChild(val)
502              elif isinstance(value,StringType):              elif isinstance (value, list):
503                  param.appendChild(dataNode(document, 'Value', value))                  param.appendChild(dataNode(document, 'Value', ' '.join(
504                        [str(x) for x in value])
505                    ))
506              else:              else:
507                  param.appendChild(dataNode(document, 'Value', str(value)))                  param.appendChild(dataNode(document, 'Value', str(value)))
508    
# Line 453  class ParameterSet(LinkableObject): Line 515  class ParameterSet(LinkableObject):
515              """              """
516              Remove the empty nodes from the children of this node.              Remove the empty nodes from the children of this node.
517              """              """
518              return [x for x in node.childNodes              ret = []
519                      if not isinstance(x, minidom.Text) or x.nodeValue.strip()]              for x in node.childNodes:
520                    if isinstance(x, minidom.Text):
521                        if x.nodeValue.strip():
522                            ret.append(x)
523                    else:
524                        ret.append(x)
525                return ret
526    
527          def _floatfromValue(doc):          def _floatfromValue(doc):
528              return float(doc.nodeValue.strip())              return float(doc.nodeValue.strip())
# Line 466  class ParameterSet(LinkableObject): Line 534  class ParameterSet(LinkableObject):
534              return int(doc.nodeValue.strip())              return int(doc.nodeValue.strip())
535    
536          def _boolfromValue(doc):          def _boolfromValue(doc):
537              return bool(doc.nodeValue.strip())              return _boolfromstring(doc.nodeValue.strip())
538          
539            def _nonefromValue(doc):
540                return None
541    
542            def _numarrayfromValue(doc):
543                for node in _children(doc):
544                    if node.tagName == 'ArrayType':
545                        arraytype = node.firstChild.nodeValue.strip()
546                    if node.tagName == 'Shape':
547                        shape = node.firstChild.nodeValue.strip()
548                        shape = [int(x) for x in shape.split()]
549                    if node.tagName == 'Data':
550                        data = node.firstChild.nodeValue.strip()
551                        data = [float(x) for x in data.split()]
552                return numarray.reshape(numarray.array(data, type=getattr(numarray, arraytype)),
553                                        shape)
554          
555            def _listfromValue(doc):
556                return [_boolfromstring(x) for x in doc.nodeValue.split()]
557    
558    
559            def _boolfromstring(s):
560                if s == 'True':
561                    return True
562                else:
563                    return False
564          # 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
565          ptypemap = {"Simulation": Simulation.fromDom,          ptypemap = {"Simulation": Simulation.fromDom,
566                      "Model":Model.fromDom,                      "Model":Model.fromDom,
567                      "ParameterSet":ParameterSet.fromDom,                      "ParameterSet":ParameterSet.fromDom,
568                      "Link":Link.fromDom,                      "Link":Link.fromDom,
569                        "DataSource":DataSource.fromDom,
570                      "float":_floatfromValue,                      "float":_floatfromValue,
571                      "int":_intfromValue,                      "int":_intfromValue,
572                      "str":_stringfromValue,                      "str":_stringfromValue,
573                      "bool":_boolfromValue                      "bool":_boolfromValue,
574                        "list":_listfromValue,
575                        "NumArray":_numarrayfromValue,
576                        "NoneType":_nonefromValue,
577                      }                      }
578    
579  #        print doc.toxml()  #        print doc.toxml()
# Line 493  class ParameterSet(LinkableObject): Line 590  class ParameterSet(LinkableObject):
590    
591                  if childnode.tagName == "Value":                  if childnode.tagName == "Value":
592                      nodes = _children(childnode)                      nodes = _children(childnode)
593                    #    if ptype == 'NumArray':
594                     #       pvalue = _numarrayfromValue(nodes)
595                     #   else:
596                      pvalue = ptypemap[ptype](nodes[0])                      pvalue = ptypemap[ptype](nodes[0])
597    
598              parameters[pname] = pvalue              parameters[pname] = pvalue
# Line 520  class Model(ParameterSet): Line 620  class Model(ParameterSet):
620      finalizing condition is fullfilled. At each time step an iterative      finalizing condition is fullfilled. At each time step an iterative
621      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
622      Model has the following work flow::      Model has the following work flow::
623              
624            doInitialization()            doInitialization()
625              while not terminateInitialIteration(): doInitializationiStep()
626              doInitialPostprocessing()
627            while not finalize():            while not finalize():
628                 dt=getSafeTimeStepSize(dt)                 dt=getSafeTimeStepSize(dt)
629                 doStepPreprocessing(dt)                 doStepPreprocessing(dt)
# Line 547  class Model(ParameterSet): Line 649  class Model(ParameterSet):
649          ParameterSet.__init__(self, parameters=parameters,**kwarg)          ParameterSet.__init__(self, parameters=parameters,**kwarg)
650    
651      def __str__(self):      def __str__(self):
652         return "<%s %d>"%(self.__class__,id(self))         return "<%s %d>"%(self.__class__.__name__,id(self))
653    
654      def toDom(self, document, node):      def toDom(self, document, node):
655          """          """
# Line 555  class Model(ParameterSet): Line 657  class Model(ParameterSet):
657      """      """
658          pset = document.createElement('Model')          pset = document.createElement('Model')
659          pset.setAttribute('type', self.__class__.__name__)          pset.setAttribute('type', self.__class__.__name__)
660            if not self.__class__.__module__.startswith('esys.escript'):
661                pset.setAttribute('module', self.__class__.__module__)
662          node.appendChild(pset)          node.appendChild(pset)
663          self._parametersToDom(document, pset)          self._parametersToDom(document, pset)
664    
# Line 565  class Model(ParameterSet): Line 669  class Model(ParameterSet):
669      This function may be overwritten.      This function may be overwritten.
670      """      """
671          pass          pass
672        def doInitialStep(self):
673            """
674        performs an iteration step in the initialization phase
675    
676        This function may be overwritten.
677        """
678            pass
679    
680        def terminateInitialIteration(self):
681            """
682        Returns True if iteration at the inital phase is terminated.
683        """
684            return True
685    
686        def doInitialPostprocessing(self):
687            """
688        finalises the initialization iteration process
689    
690        This function may be overwritten.
691        """
692            pass
693            
694      def getSafeTimeStepSize(self,dt):      def getSafeTimeStepSize(self,dt):
695          """          """
# Line 615  class Model(ParameterSet): Line 740  class Model(ParameterSet):
740      Returns True if iteration on a time step is terminated.      Returns True if iteration on a time step is terminated.
741      """      """
742          return True          return True
743    
744                
745      def doStepPostprocessing(self,dt):      def doStepPostprocessing(self,dt):
746          """          """
747      Finalalizes the time step.      finalises the time step.
748    
749          dt is the currently used time step size.          dt is the currently used time step size.
750    
# Line 644  class Simulation(Model): Line 770  class Simulation(Model):
770            
771      FAILED_TIME_STEPS_MAX=20      FAILED_TIME_STEPS_MAX=20
772      MAX_ITER_STEPS=50      MAX_ITER_STEPS=50
773        MAX_CHANGE_OF_DT=2.
774            
775      def __init__(self, models=[], **kwargs):      def __init__(self, models=[], **kwargs):
776          """          """
# Line 685  class Simulation(Model): Line 812  class Simulation(Model):
812      Sets the i-th model.      Sets the i-th model.
813      """      """
814          if not isinstance(value,Model):          if not isinstance(value,Model):
815              raise ValueError("assigned value is not a Model")              raise ValueError,"assigned value is not a Model but instance of %s"%(value.__class__.__name__,)
816          for j in range(max(i-len(self.__models)+1,0)):          for j in range(max(i-len(self.__models)+1,0)):
817              self.__models.append(None)              self.__models.append(None)
818          self.__models[i]=value          self.__models[i]=value
# Line 720  class Simulation(Model): Line 847  class Simulation(Model):
847          document, rootnode = esysDoc()          document, rootnode = esysDoc()
848          self.toDom(document, rootnode)          self.toDom(document, rootnode)
849          targetsList = document.getElementsByTagName('Target')          targetsList = document.getElementsByTagName('Target')
850          for i in targetsList:          
851              targetId = int(i.firstChild.nodeValue.strip())          for element in targetsList:
852                targetId = int(element.firstChild.nodeValue.strip())
853                if document.getElementById(str(targetId)):
854                    continue
855              targetObj = LinkableObjectRegistry[targetId]              targetObj = LinkableObjectRegistry[targetId]
856              targetObj.toDom(document, rootnode)              targetObj.toDom(document, rootnode)
857          ostream.write(document.toprettyxml())          ostream.write(document.toprettyxml())
# Line 733  class Simulation(Model): Line 863  class Simulation(Model):
863          This is the minimum over the time step sizes of all models.          This is the minimum over the time step sizes of all models.
864      """      """
865          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)  
866          return out          return out
867            
868      def doInitialization(self):      def doInitialization(self):
# Line 743  class Simulation(Model): Line 872  class Simulation(Model):
872          self.n=0          self.n=0
873          self.tn=0.          self.tn=0.
874          for o in self.iterModels():          for o in self.iterModels():
875              o.doInitialization()               o.doInitialization()
876            def doInitialStep(self):
877            """
878        performs an iteration step in the initialization step for all models
879        """
880            iter=0
881            while not self.terminateInitialIteration():
882                if iter==0: self.trace("iteration for initialization starts")
883                iter+=1
884                self.trace("iteration step %d"%(iter))
885                for o in self.iterModels():
886                     o.doInitialStep()
887                if iter>self.MAX_ITER_STEPS:
888                     raise IterationDivergenceError("initial iteration did not converge after %s steps."%iter)
889            self.trace("Initialization finalized after %s iteration steps."%iter)
890    
891        def doInitialPostprocessing(self):
892            """
893        finalises the initialization iteration process for all models.
894        """
895            for o in self.iterModels():
896                o.doInitialPostprocessing()
897      def finalize(self):      def finalize(self):
898          """          """
899      Returns True if any of the models is to be finalized.      Returns True if any of the models is to be finalized.
# Line 753  class Simulation(Model): Line 902  class Simulation(Model):
902                
903      def doFinalization(self):      def doFinalization(self):
904          """          """
905      Finalalizes the time stepping for all models.      finalises the time stepping for all models.
906      """      """
907          for i in self.iterModels(): i.doFinalization()          for i in self.iterModels(): i.doFinalization()
908          self.trace("end of time integation.")          self.trace("end of time integation.")
# Line 771  class Simulation(Model): Line 920  class Simulation(Model):
920      """      """
921          out=all([o.terminateIteration() for o in self.iterModels()])          out=all([o.terminateIteration() for o in self.iterModels()])
922          return out          return out
923    
924        def terminateInitialIteration(self):
925            """
926        Returns True if all initial iterations for all models are terminated.
927        """
928            out=all([o.terminateInitialIteration() for o in self.iterModels()])
929            return out
930                
931      def doStepPostprocessing(self,dt):      def doStepPostprocessing(self,dt):
932          """          """
933      Finalalizes the iteration process for all models.      finalises the iteration process for all models.
934      """      """
935          for o in self.iterModels():          for o in self.iterModels():
936              o.doStepPostprocessing(dt)              o.doStepPostprocessing(dt)
# Line 805  class Simulation(Model): Line 961  class Simulation(Model):
961      Run the simulation by performing essentially::      Run the simulation by performing essentially::
962            
963          self.doInitialization()          self.doInitialization()
964                while not self.terminateInitialIteration(): self.doInitialStep()
965                self.doInitialPostprocessing()
966          while not self.finalize():          while not self.finalize():
967              dt=self.getSafeTimeStepSize()              dt=self.getSafeTimeStepSize()
968              self.doStep(dt)              self.doStep(dt)
# Line 822  class Simulation(Model): Line 980  class Simulation(Model):
980          In both cases the time integration is given up after          In both cases the time integration is given up after
981      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
982          """          """
         dt=self.UNDEF_DT  
983          self.doInitialization()          self.doInitialization()
984            self.doInitialStep()
985            self.doInitialPostprocessing()
986            dt=self.UNDEF_DT
987          while not self.finalize():          while not self.finalize():
988              step_fail_counter=0              step_fail_counter=0
989              iteration_fail_counter=0              iteration_fail_counter=0
990              dt_new=self.getSafeTimeStepSize(dt)              if self.n==0:
991                    dt_new=self.getSafeTimeStepSize(dt)
992                else:
993                    dt_new=min(max(self.getSafeTimeStepSize(dt),dt/self.MAX_CHANGE_OF_DT),dt*self.MAX_CHANGE_OF_DT)
994              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))
995              end_of_step=False              end_of_step=False
996              while not end_of_step:              while not end_of_step:
997                 end_of_step=True                 end_of_step=True
998                 if not dt_new>0:                 if not dt_new>0:
999                    raise NonPositiveStepSizeError("non-positive step size in step %d",self.n+1)                    raise NonPositiveStepSizeError("non-positive step size in step %d"%(self.n+1))
1000                 try:                 try:
1001                    self.doStepPreprocessing(dt_new)                    self.doStepPreprocessing(dt_new)
1002                    self.doStep(dt_new)                    self.doStep(dt_new)
# Line 843  class Simulation(Model): Line 1006  class Simulation(Model):
1006                    end_of_step=False                    end_of_step=False
1007                    iteration_fail_counter+=1                    iteration_fail_counter+=1
1008                    if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:                    if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
1009                             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)
1010                    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)
1011                 except FailedTimeStepError:                 except FailedTimeStepError:
1012                    dt_new=self.getSafeTimeStepSize(dt)                    dt_new=self.getSafeTimeStepSize(dt)
1013                    end_of_step=False                    end_of_step=False
1014                    step_fail_counter+=1                    step_fail_counter+=1
1015                    self.trace("time step is repeated.")                    self.trace("Time step is repeated with new time step size %s."%dt_new)
1016                    if step_fail_counter>self.FAILED_TIME_STEPS_MAX:                    if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
1017                          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)
1018              dt=dt_new              dt=dt_new
1019              if not check_point==None:              if not check_point==None:
1020                  if n%check_point==0:                  if n%check_point==0:
# Line 901  class NonPositiveStepSizeError(Exception Line 1064  class NonPositiveStepSizeError(Exception
1064      """      """
1065      pass      pass
1066    
1067    class DataSource(object):
1068        """
1069        Class for handling data sources, including local and remote files. This class is under development.
1070        """
1071    
1072        def __init__(self, uri="file.ext", fileformat="unknown"):
1073            self.uri = uri
1074            self.fileformat = fileformat
1075    
1076        def toDom(self, document, node):
1077            """
1078            C{toDom} method of DataSource. Creates a DataSource node and appends it to the
1079        current XML document.
1080            """
1081            ds = document.createElement('DataSource')
1082            ds.appendChild(dataNode(document, 'URI', self.uri))
1083            ds.appendChild(dataNode(document, 'FileFormat', self.fileformat))
1084            node.appendChild(ds)
1085    
1086        def fromDom(cls, doc):
1087            uri= doc.getElementsByTagName("URI")[0].firstChild.nodeValue.strip()
1088            fileformat= doc.getElementsByTagName("FileFormat")[0].firstChild.nodeValue.strip()
1089            ds = cls(uri, fileformat)
1090            return ds
1091    
1092        def getLocalFileName(self):
1093            return self.uri
1094    
1095        fromDom = classmethod(fromDom)
1096        
1097  # vim: expandtab shiftwidth=4:  # vim: expandtab shiftwidth=4:

Legend:
Removed from v.149  
changed lines
  Added in v.908

  ViewVC Help
Powered by ViewVC 1.1.26