/[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 926 by gross, Fri Jan 12 06:31:37 2007 UTC revision 1312 by ksteube, Mon Sep 24 06:18:44 2007 UTC
# Line 1  Line 1 
1    #
2  # $Id$  # $Id$
3    #
4    #######################################################
5    #
6    #           Copyright 2003-2007 by ACceSS MNRF
7    #       Copyright 2007 by University of Queensland
8    #
9    #                http://esscc.uq.edu.au
10    #        Primary Business: Queensland, Australia
11    #  Licensed under the Open Software License version 3.0
12    #     http://www.opensource.org/licenses/osl-3.0.php
13    #
14    #######################################################
15    #
16    
17  """  """
18  Environment for implementing models in escript  Environment for implementing models in escript
# Line 27  from sys import stdout Line 41  from sys import stdout
41  import numarray  import numarray
42  import operator  import operator
43  import itertools  import itertools
44    import time
45    import os
46    
47  # 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)
48  try:  try:
# Line 71  class ESySXMLParser(object): Line 87  class ESySXMLParser(object):
87        self.__dom = minidom.parseString(xml)        self.__dom = minidom.parseString(xml)
88        self.__linkable_object_registry= {}        self.__linkable_object_registry= {}
89        self.__link_registry=  []        self.__link_registry=  []
90        self.__esys=self.__dom.firstChild        self.__esys=self.__dom.getElementsByTagName('ESys')[0]
91        self.debug=debug        self.debug=debug
92        
93      def getClassPath(self, node):      def getClassPath(self, node):
# Line 214  class Link: Line 230  class Link:
230          self.attribute = None          self.attribute = None
231          self.setAttributeName(attribute)          self.setAttributeName(attribute)
232    
233        def getTarget(self):
234            """
235            returns the target
236            """
237            return self.target
238      def getAttributeName(self):      def getAttributeName(self):
239          """          """
240          returns the name of the attribute the link is pointing to          returns the name of the attribute the link is pointing to
# Line 462  class ParameterSet(LinkableObject): Line 483  class ParameterSet(LinkableObject):
483              setattr(self,prm,value)              setattr(self,prm,value)
484              self.parameters.add(prm)              self.parameters.add(prm)
485    
             self.trace("parameter %s has been declared."%prm)  
   
486      def releaseParameters(self,name):      def releaseParameters(self,name):
487          """          """
488      Removes parameter name from the paramameters.      Removes parameter name from the paramameters.
# Line 471  class ParameterSet(LinkableObject): Line 490  class ParameterSet(LinkableObject):
490          if self.isParameter(name):          if self.isParameter(name):
491              self.parameters.remove(name)              self.parameters.remove(name)
492              self.trace("parameter %s has been removed."%name)              self.trace("parameter %s has been removed."%name)
493    
494        def checkLinkTargets(self, models, hash):
495            """
496            returns a set of tuples ("<self>(<name>)", <target model>) if the parameter <name> is linked to model <target model>
497            but <target model> is not in the list models. If the a parameter is linked to another parameter set which is not in the hash list
498            the parameter set is checked for its models. hash gives the call history.
499            """
500            out=set()
501            for name, value in self:
502                if isinstance(value, Link):
503                   m=value.getTarget()
504                   if isinstance(m, Model):
505                       if not m in models: out.add( (str(self)+"("+name+")",m) )
506                   elif isinstance(m, ParameterSet) and not m in hash:
507                         out|=set( [ (str(self)+"("+name+")."+f[0],f[1]) for f in m.checkLinkTargets(models, hash+[ self ] ) ] )
508            return out
509            
510      def __iter__(self):      def __iter__(self):
511          """          """
# Line 522  class ParameterSet(LinkableObject): Line 557  class ParameterSet(LinkableObject):
557                  for i in value:                  for i in value:
558                      if isinstance(i, bool):                      if isinstance(i, bool):
559                          elem_type = max(elem_type,0)                          elem_type = max(elem_type,0)
560                      if isinstance(i, int) and not isinstance(i, bool):                      elif isinstance(i, int):
561                          elem_type = max(elem_type,1)                          elem_type = max(elem_type,1)
562                      if isinstance(i, float):                      elif isinstance(i, float):
563                          elem_type = max(elem_type,2)                          elem_type = max(elem_type,2)
564                  if elem_type == 0: value = numarray.array(value,numarray.Bool)                  if elem_type == 0: value = numarray.array(value,numarray.Bool)
565                  if elem_type == 1: value = numarray.array(value,numarray.Int)                  if elem_type == 1: value = numarray.array(value,numarray.Int)
# Line 582  class ParameterSet(LinkableObject): Line 617  class ParameterSet(LinkableObject):
617                      dic.appendChild(i)                      dic.appendChild(i)
618                   param.appendChild(dic)                   param.appendChild(dic)
619              else:              else:
                 print value  
620                  raise ValueError("cannot serialize %s type to XML."%str(value.__class__))                  raise ValueError("cannot serialize %s type to XML."%str(value.__class__))
621    
622              node.appendChild(param)              node.appendChild(param)
# Line 671  class ParameterSet(LinkableObject): Line 705  class ParameterSet(LinkableObject):
705              parameters[pname] = pvalue              parameters[pname] = pvalue
706    
707          # Create the instance of ParameterSet          # Create the instance of ParameterSet
708          o = cls(debug=esysxml.debug)          try:
709               o = cls(debug=esysxml.debug)
710            except TypeError, inst:
711               print inst.args[0]
712               if inst.args[0]=="__init__() got an unexpected keyword argument 'debug'":
713                  raise TypeError("The Model class %s __init__ needs to have argument 'debug'.")
714               else:
715                  raise inst
716          o.declareParameters(parameters)          o.declareParameters(parameters)
717          esysxml.registerLinkableObject(o, node)          esysxml.registerLinkableObject(o, node)
718          return o          return o
# Line 724  class Model(ParameterSet): Line 765  class Model(ParameterSet):
765         return "<%s %d>"%(self.__class__.__name__,id(self))         return "<%s %d>"%(self.__class__.__name__,id(self))
766    
767    
768        def setUp(self):
769            """
770            Sets up the model.
771    
772            This function may be overwritten.
773            """
774            pass
775    
776      def doInitialization(self):      def doInitialization(self):
777          """          """
778      Initializes the time stepping scheme.        Initializes the time stepping scheme. This method is not called in case of a restart.
779            
780      This function may be overwritten.      This function may be overwritten.
781      """      """
782          pass          pass
783      def doInitialStep(self):      def doInitialStep(self):
784          """          """
785      performs an iteration step in the initialization phase      performs an iteration step in the initialization phase. This method is not called in case of a restart.
786    
787      This function may be overwritten.      This function may be overwritten.
788      """      """
# Line 741  class Model(ParameterSet): Line 790  class Model(ParameterSet):
790    
791      def terminateInitialIteration(self):      def terminateInitialIteration(self):
792          """          """
793      Returns True if iteration at the inital phase is terminated.      Returns True if iteration at the inital phase is terminated.
794      """      """
795          return True          return True
796    
797      def doInitialPostprocessing(self):      def doInitialPostprocessing(self):
798          """          """
799      finalises the initialization iteration process      finalises the initialization iteration process. This method is not called in case of a restart.
800    
801      This function may be overwritten.      This function may be overwritten.
802      """      """
# Line 844  class Simulation(Model): Line 893  class Simulation(Model):
893      Initiates a simulation from a list of models.      Initiates a simulation from a list of models.
894      """      """
895          super(Simulation, self).__init__(**kwargs)          super(Simulation, self).__init__(**kwargs)
896            self.declareParameter(time=0.,
897                                  time_step=0,
898                                  dt = self.UNDEF_DT)
899            for m in models:
900                if not isinstance(m, Model):
901                     raise TypeError("%s is not a subclass of Model."%m)
902          self.__models=[]          self.__models=[]
           
903          for i in range(len(models)):          for i in range(len(models)):
904              self[i] = models[i]              self[i] = models[i]
905                            
# Line 890  class Simulation(Model): Line 944  class Simulation(Model):
944      """      """
945          return len(self.__models)          return len(self.__models)
946    
947        def getAllModels(self):
948            """
949            returns a list of all models used in the Simulation including subsimulations
950            """
951            out=[]
952            for m in self.iterModels():
953                if isinstance(m, Simulation):
954                   out+=m.getAllModels()
955                else:
956                   out.append(m)
957            return list(set(out))
958    
959        def checkModels(self, models, hash):
960            """
961            returns a list of (model,parameter, target model ) if the the parameter of model
962            is linking to the target_model which is not in list of models.
963            """
964            out=self.checkLinkTargets(models, hash + [self])
965            for m in self.iterModels():
966                if isinstance(m, Simulation):
967                     out|=m.checkModels(models, hash)
968                else:
969                     out|=m.checkLinkTargets(models, hash + [self])
970            return set( [ (str(self)+"."+f[0],f[1]) for f in out ] )
971    
972            
973      def getSafeTimeStepSize(self,dt):      def getSafeTimeStepSize(self,dt):
974          """          """
# Line 899  class Simulation(Model): Line 978  class Simulation(Model):
978      """      """
979          out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])          out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
980          return out          return out
981    
982        def setUp(self):
983            """
984            performs the setup for all models
985            """
986            for o in self.iterModels():
987                 o.setUp()
988            
989      def doInitialization(self):      def doInitialization(self):
990          """          """
991      Initializes all models.      Initializes all models.
992      """      """
         self.n=0  
         self.tn=0.  
993          for o in self.iterModels():          for o in self.iterModels():
994               o.doInitialization()               o.doInitialization()
995      def doInitialStep(self):      def doInitialStep(self):
# Line 969  class Simulation(Model): Line 1053  class Simulation(Model):
1053      """      """
1054          for o in self.iterModels():          for o in self.iterModels():
1055              o.doStepPostprocessing(dt)              o.doStepPostprocessing(dt)
1056          self.n+=1          self.time_step+=1
1057          self.tn+=dt          self.time+=dt
1058            self.dt=dt
1059            
1060      def doStep(self,dt):      def doStep(self,dt):
1061          """          """
# Line 984  class Simulation(Model): Line 1069  class Simulation(Model):
1069          """          """
1070          self.iter=0          self.iter=0
1071          while not self.terminateIteration():          while not self.terminateIteration():
1072              if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt))              if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.time_step+1,self.time+dt))
1073              self.iter+=1              self.iter+=1
1074              self.trace("iteration step %d"%(self.iter))              self.trace("iteration step %d"%(self.iter))
1075              for o in self.iterModels():              for o in self.iterModels():
1076                    o.doStep(dt)                    o.doStep(dt)
1077          if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.n+1,self.tn+dt))          if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.time_step+1,self.time+dt))
1078    
1079      def run(self,check_point=None):      def run(self,check_pointing=None):
1080          """          """
1081      Run the simulation by performing essentially::      Run the simulation by performing essentially::
1082            
1083          self.doInitialization()              self.setUp()
1084              while not self.terminateInitialIteration(): self.doInitialStep()              if not restart:
1085              self.doInitialPostprocessing()              self.doInitialization()
1086                    while not self.terminateInitialIteration(): self.doInitialStep()
1087                    self.doInitialPostprocessing()
1088          while not self.finalize():          while not self.finalize():
1089              dt=self.getSafeTimeStepSize()              dt=self.getSafeTimeStepSize()
1090              self.doStep(dt)                  self.doStepPreprocessing(dt_new)
1091              if n%check_point==0:                  self.doStep(dt_new)
1092              self.writeXML()                  self.doStepPostprocessing(dt_new)
1093          self.doFinalization()          self.doFinalization()
1094    
1095          If one of the models in throws a C{FailedTimeStepError} exception a          If one of the models in throws a C{FailedTimeStepError} exception a
# Line 1015  class Simulation(Model): Line 1102  class Simulation(Model):
1102          In both cases the time integration is given up after          In both cases the time integration is given up after
1103      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.      C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
1104          """          """
1105          self.doInitialization()          # check the completness of the models:
1106          self.doInitialStep()          # first a list of all the models involved in the simulation including subsimulations:
1107          self.doInitialPostprocessing()          #
1108          dt=self.UNDEF_DT          missing=self.checkModels(self.getAllModels(), [])
1109            if len(missing)>0:
1110                msg=""
1111                for l in missing:
1112                     msg+="\n\t"+str(l[1])+" at "+l[0]
1113                raise MissingLink("link targets missing in the Simulation: %s"%msg)
1114            #==============================
1115            self.setUp()
1116            if self.time_step < 1:
1117               self.doInitialization()
1118               self.doInitialStep()
1119               self.doInitialPostprocessing()
1120          while not self.finalize():          while not self.finalize():
1121              step_fail_counter=0              step_fail_counter=0
1122              iteration_fail_counter=0              iteration_fail_counter=0
1123              if self.n==0:              if self.time_step==0:
1124                  dt_new=self.getSafeTimeStepSize(dt)                  dt_new=self.getSafeTimeStepSize(self.dt)
1125              else:              else:
1126                  dt_new=min(max(self.getSafeTimeStepSize(dt),dt/self.MAX_CHANGE_OF_DT),dt*self.MAX_CHANGE_OF_DT)                  dt_new=min(max(self.getSafeTimeStepSize(self.dt),self.dt/self.MAX_CHANGE_OF_DT),self.dt*self.MAX_CHANGE_OF_DT)
1127              self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))              self.trace("%d. time step %e (step size %e.)" % (self.time_step+1,self.time+dt_new,dt_new))
1128              end_of_step=False              end_of_step=False
1129              while not end_of_step:              while not end_of_step:
1130                 end_of_step=True                 end_of_step=True
1131                 if not dt_new>0:                 if not dt_new>0:
1132                    raise NonPositiveStepSizeError("non-positive step size in step %d"%(self.n+1))                    raise NonPositiveStepSizeError("non-positive step size in step %d"%(self.time_step+1))
1133                 try:                 try:
1134                    self.doStepPreprocessing(dt_new)                    self.doStepPreprocessing(dt_new)
1135                    self.doStep(dt_new)                    self.doStep(dt_new)
# Line 1044  class Simulation(Model): Line 1142  class Simulation(Model):
1142                             raise SimulationBreakDownError("reduction of time step to achieve convergence failed after %s steps."%self.FAILED_TIME_STEPS_MAX)                             raise SimulationBreakDownError("reduction of time step to achieve convergence failed after %s steps."%self.FAILED_TIME_STEPS_MAX)
1143                    self.trace("Iteration failed. Time step is repeated with new step size %s."%dt_new)                    self.trace("Iteration failed. Time step is repeated with new step size %s."%dt_new)
1144                 except FailedTimeStepError:                 except FailedTimeStepError:
1145                    dt_new=self.getSafeTimeStepSize(dt)                    dt_new=self.getSafeTimeStepSize(self.dt)
1146                    end_of_step=False                    end_of_step=False
1147                    step_fail_counter+=1                    step_fail_counter+=1
1148                    self.trace("Time step is repeated with new time step size %s."%dt_new)                    self.trace("Time step is repeated with new time step size %s."%dt_new)
1149                    if step_fail_counter>self.FAILED_TIME_STEPS_MAX:                    if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
1150                          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)
1151              dt=dt_new              if not check_pointing==None:
1152              if not check_point==None:                 if check_pointing.doDump():
                 if n%check_point==0:  
1153                      self.trace("check point is created.")                      self.trace("check point is created.")
1154                      self.writeXML()                      self.writeXML()
1155          self.doFinalization()          self.doFinalization()
# Line 1078  class Simulation(Model): Line 1175  class Simulation(Model):
1175              if isinstance(n, minidom.Text):              if isinstance(n, minidom.Text):
1176                  continue                  continue
1177              sims.append(esysxml.getComponent(n))              sims.append(esysxml.getComponent(n))
1178          sims.sort(cmp=_comp)          sims.sort(_comp)
1179          sim=cls([s[1] for s in sims], debug=esysxml.debug)          sim=cls([s[1] for s in sims], debug=esysxml.debug)
1180          esysxml.registerLinkableObject(sim, node)          esysxml.registerLinkableObject(sim, node)
1181          return sim          return sim
# Line 1122  class NonPositiveStepSizeError(Exception Line 1219  class NonPositiveStepSizeError(Exception
1219      """      """
1220      pass      pass
1221    
1222    class MissingLink(Exception):
1223        """
1224        Exception thrown when a link is missing
1225        """
1226        pass
1227    
1228  class DataSource(object):  class DataSource(object):
1229      """      """
1230      Class for handling data sources, including local and remote files. This class is under development.      Class for handling data sources, including local and remote files. This class is under development.
# Line 1151  class DataSource(object): Line 1254  class DataSource(object):
1254          return self.uri          return self.uri
1255    
1256      fromDom = classmethod(fromDom)      fromDom = classmethod(fromDom)
1257        
1258    class RestartManager(object):
1259         """
1260         A restart manager which does two things: it decides when restart files have created (when doDump returns true) and
1261         manages directories for restart files. The method getNewDumper creates a new directory and returns its name.
1262        
1263         This restart manager will decide to dump restart files if every dump_step calls of doDump or
1264         if more than dump_time since the last dump has elapsed. The restart manager controls two directories for dumping restart data, namely
1265         for the current and previous dump. This way the previous dump can be used for restart in the case the current dump failed.
1266    
1267         @cvar SEC: unit of seconds, for instance for 5*RestartManager.SEC to define 5 seconds.
1268         @cvar MIN: unit of minutes, for instance for 5*RestartManager.MIN to define 5 minutes.
1269         @cvar H: unit of hours, for instance for 5*RestartManager.H to define 5 hours.
1270         @cvar D: unit of days, for instance for 5*RestartManager.D to define 5 days.
1271         """
1272         SEC=1.
1273         MIN=60.
1274         H=360.
1275         D=8640.
1276         def __init__(self,dump_time=1080., dump_step=None, dumper=None):
1277             """
1278             initializes the RestartManager.
1279    
1280             @param dump_time: defines the minimum time interval in SEC between to dumps. If None, time is not used as criterion.
1281             @param dump_step: defines the number of calls of doDump between to dump events. If None, the call counter is not used as criterion.
1282             @param dumper: defines the directory for dumping restart files. Additionally the directories dumper+"_bkp" and dumper+"_bkp2" are used.
1283                            if the directory does not exist it is created. If dumper is not present a unique directory within the current
1284                            working directory is used.
1285             """
1286             self.__dump_step=dump_time
1287             self.__dump_time=dump_step
1288             self.__counter=0
1289             self.__saveMarker()
1290             if dumper == None:
1291                self.__dumper="restart"+str(os.getpid())
1292             else:
1293                self.__dumper=dumper
1294             self.__dumper_bkp=self.__dumper+"_bkp"
1295             self.__dumper_bkp2=self.__dumper+"_bkp2"
1296             self.__current_dumper=None
1297         def __saveMarker(self):
1298             self.__last_restart_time=time.time()
1299             self.__last_restart_counter=self.__counter
1300         def getCurrentDumper(self):
1301             """
1302             returns the name of the currently used dumper
1303             """
1304             return self.__current_dumper
1305         def doDump(self):
1306            """
1307            returns true the restart should be dumped. use C{getNewDumper} to get the directory name to be used.
1308            """
1309            if self.__dump_step == None:
1310               if self.__dump_step == None:
1311                  out = False
1312               else:
1313                  out = (self.__dump_step + self.__last_restart_counter) <= self.__counter
1314            else:
1315               if dump_step == None:
1316                  out = (self.__last_restart_time + self.__dump_time) <= time.time()
1317               else:
1318                  out =    ( (self.__dump_step + self.__last_restart_counter) <= self.__counter)  \
1319                        or ( (self.__last_restart_time + self.__dump_time) <= time.time() )
1320            if out: self.__saveMarker()
1321            self__counter+=1
1322         def getNewDumper(self):
1323           """
1324           creates a new directory to be used for dumping and returns its name.
1325           """
1326           if os.access(self.__dumper_bkp,os.F_OK):
1327              if os.access(self.__dumper_bkp2, os.F_OK):
1328                 raise RunTimeError("please remove %s."%self.__dumper_bkp2)
1329              try:
1330                 os.rename(self.__dumper_bkp, self.__dumper_bkp2)
1331              except:
1332                 self.__current_dumper=self.__dumper
1333                 raise RunTimeError("renaming back-up directory %s failed. Use %s for restart."%(self.__dumper_bkp,self.__dumper))
1334           if os.access(self.__dumper,os.F_OK):
1335              if os.access(self.__dumper_bkp, os.F_OK):
1336                 raise RunTimeError("please remove %s."%self.__dumper_bkp)
1337              try:
1338                 os.rename(self.__dumper, self.__dumper_bkp)
1339              except:
1340                 self.__current_dumper=self.__dumper_bkp2
1341                 raise RunTimeError("moving directory %s to back-up failed. Use %s for restart."%(self.__dumper,self.__dumper_bkp2))
1342           try:
1343              os.mkdir(self.__dumper)
1344           except:
1345              self.__current_dumper=self.__dumper_bkp
1346              raise RunTimeError("creating a new restart directory %s failed. Use %s for restart."%(self.__dumper,self.__dumper_bkp))
1347           if os.access(self.__dumper_bkp2, os.F_OK): os.rmdir(self.__dumper_bkp2)
1348           return self.getCurrentDumper()
1349            
1350        
1351  # vim: expandtab shiftwidth=4:  # vim: expandtab shiftwidth=4:

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

  ViewVC Help
Powered by ViewVC 1.1.26