From 8574e5466f444145ef5d60eb9600e92ed38bf91f Mon Sep 17 00:00:00 2001
From: Wouter Peters <wouter.peters@wur.nl>
Date: Mon, 23 Jul 2012 15:50:05 +0000
Subject: [PATCH] TM5 now compiled before run

---
 da/tm5/observationoperator.py | 91 +++++++++++++++++++++++++++++++++--
 da/tools/pipeline.py          |  4 +-
 2 files changed, 89 insertions(+), 6 deletions(-)

diff --git a/da/tm5/observationoperator.py b/da/tm5/observationoperator.py
index ecabd520..6c110b33 100755
--- a/da/tm5/observationoperator.py
+++ b/da/tm5/observationoperator.py
@@ -26,6 +26,7 @@ import logging
 import shutil
 
 sys.path.append(os.getcwd())
+sys.path.append("../../")
 
 identifier      = 'TM5'
 version         = 'release 3.0'
@@ -79,13 +80,77 @@ class TM5ObservationOperator(ObservationOperator):
 
         msg                 = 'Observation Operator initialized: %s (%s)'%(self.Identifier, self.Version,) ; logging.info(msg)
 
+    def Initialize(self ):
+        """ 
+           Execute all steps needed to prepare the ObsOperator for use inside CTDAS, only done at the very first cycle normally
+    
+        """
+        from da.tools.general import CreateDirs
+
+
+        if self.DaCycle['time.restart'] == False :
+
+            msg                 = 'First time step, setting up and compiling the TM5 model before proceeding!' ; logging.info(msg)
+            # Modify the rc-file to reflect directory structure defined by CTDAS
+            NewItems = {
+                        'my.basedir'     : self.DaCycle['dir.exec']    ,
+                        }
+
+            self.ModifyRC(NewItems)
+
+            # Create the TM5 run directory to hold a copy of the modified rc-file
+
+            tm5compiledir  = self.tm_settings[self.rundirkey]
+            dummy          = CreateDirs(tm5compiledir)
+
+            self.RcFileName = self.WriteRc()
+
+            # Compile TM5 in the new directory, but only if this is a fresh start
+
+            self.CompileTM5()
+
+        return 0
+
+    def CompileTM5(self):
+        """
+            Compile TM5 model using setup_tm5 and the modified rc-file
+        """
+        import subprocess
+        from string import join
+
+        try:
+            os.chdir(self.DaCycle['da.obsoperator.home'])
+        except:
+
+            tm5_dir = os.path.split(self.DaCycle['da.obsoperator.rc'])[0]
+            msg                 = 'Guessing your TM5 root dir from the rc filename' ; logging.warning(msg)
+            msg                 = 'Try adding a key da.obsoperator.home to your da.rc' ; logging.warning(msg)
+            msg                 = 'Proceeding from guessed TM5 root dir (%s) '%tm5_dir ; logging.warning(msg)
+
+            os.chdir(tm5_dir)
+
+        cmd = ['python','setup_tm5','-q',self.RcFileName]
+
+        msg = 'Starting the external TM5 setup script' ; logging.info(msg)
+        msg = 'using command ... %s'% join(cmd) ; logging.info(msg)
+
+        retcode = subprocess.call(cmd)
+        os.chdir(self.DaCycle['dir.da_submit'])
+
+        if retcode != 0:
+            msg                 = 'Compilation failed, quitting CTDAS' ; logging.error(msg)
+            raise IOError
+            sys.exit(2)
+        else:
+            msg                 = 'Compilation successful, continuing' ; logging.info(msg)
+
     def getid(self):
         return identifier
 
     def getversion(self):
         return version
 
-    def Initialize(self ):
+    def PrepareRun(self ):
         """ 
         Prepare a forward model TM5 run, this consists of:
 
@@ -103,6 +168,7 @@ class TM5ObservationOperator(ObservationOperator):
         dummy               = self.LoadRc(self.RcFileName)   # load the specified rc-file
         dummy               = self.ValidateRc()         # validate the contents
 
+
 # Create a link from TM5 to the rundirectory of the das system
 
         sourcedir           = self.tm_settings[self.rundirkey]
@@ -133,7 +199,7 @@ class TM5ObservationOperator(ObservationOperator):
 
         self.ModifyRC(NewItems)
 
-        self.WriteRc()
+        newrcfile = self.WriteRc()
 
         #self.WriteRunRc() No longer needed with pycasso !
 
@@ -146,7 +212,8 @@ class TM5ObservationOperator(ObservationOperator):
         """
         import da.tools.rcn as rc
 
-        self.tm_settings    = rc.read(RcFileName)
+        self.rcfile         = rc.RcFile(RcFileName)
+        self.tm_settings    = self.rcfile.values
         self.RcFileName     = RcFileName
         self.Tm5RcLoaded    = True
 
@@ -263,11 +330,13 @@ class TM5ObservationOperator(ObservationOperator):
         """
         import da.tools.rc as rc
 
-        tm5rcfilename   = os.path.join(self.tm_settings[self.rundirkey],'tm5.rc')
+        tm5rcfilename   = os.path.join(self.tm_settings[self.rundirkey],'tm5_ctdas_setup.rc')
 
         dummy           = rc.write(tm5rcfilename,self.tm_settings)
 
-        msg             = "Modified tm5.rc written (%s)" % tm5rcfilename      ;logging.debug(msg)
+        msg             = "Modified rc file for TM5 written (%s)" % tm5rcfilename      ;logging.debug(msg)
+
+        return tm5rcfilename
 
     def WriteRunRc(self):
         """ 
@@ -510,6 +579,15 @@ class TM5ObservationOperator(ObservationOperator):
         if os.path.exists(okfile): 
             dummy               = os.remove(okfile)
 
+        # Prepare a job for the current platform, this job needs to account for all job parameters such as
+        # runtime, queue request, number of processors, and other platform specific parameters
+
+        # It is easiest if all of these options are 'pre-configured' through the tm5.rc file that is used, then
+        # running the ObsOperator on all platforms simply becomes a matter of running the ./setup_tm5 script
+        # that was also used to compile TM5 when not actually running CTDAS. The first run of CTDAS
+        # then could be one where TM5 is actually compiled and run, the rest of the jobs would then *not* re-compile.
+        # An option would need to be added to force a re-compile of the TM5 code, for debugging purposes.
+
         # file ID and names
         jobid                   = 'tm5'
         jobfile                 = os.path.join(targetdir,'jb.%s.jb'%jobid)
@@ -625,6 +703,8 @@ class TM5ObservationOperator(ObservationOperator):
 
 if __name__ == "__main__":
 
+    sys.path.append('../../')
+
     from da.tools.initexit import StartLogger
     from da.tools.pipeline import JobStart
     import datetime as dtm
@@ -641,6 +721,7 @@ if __name__ == "__main__":
     DaCycle['time.sample.window'] = 0
 
     tm=TM5ObservationOperator()
+    tm.Setup()
     tm.Initialize()
     tm.Run()
     tm.SaveData()
diff --git a/da/tools/pipeline.py b/da/tools/pipeline.py
index 63da0bb4..a62f8e1c 100755
--- a/da/tools/pipeline.py
+++ b/da/tools/pipeline.py
@@ -79,6 +79,8 @@ def JobStart(DaCycle, DaSystem, DaPlatForm, StateVector, Samples, ObsOperator):
 
     ObsOperator.DaCycle = DaCycle # also embed object in ObsOperator object so it can access cycle information for I/O etc
 
+    status              = ObsOperator.Initialize()  # Setup Observation Operator 
+
     return None
 
 
@@ -340,7 +342,7 @@ def RunForecastModel(DaCycle,ObsOperator):
                                        submitting a string of jobs to the queue, or simply spawning a subprocess, or ...
        """
 
-    status = ObsOperator.Initialize()
+    status = ObsOperator.PrepareRun()
 
     status = ObsOperator.ValidateInput()
 
-- 
GitLab