source: flex_extract.git/Source/Python/submit.py @ c62bec0

dev
Last change on this file since c62bec0 was c62bec0, checked in by Anne Tipka <anne.tipka@…>, 19 months ago

corrected setting of operational time parameter setting in case forecast is >24

  • Property mode set to 100755
File size: 9.0 KB
RevLine 
[c62bec0]1ls
[8463d78]2#!/usr/bin/env python3
[64cf353]3# -*- coding: utf-8 -*-
[991df6a]4#*******************************************************************************
5# @Author: Anne Fouilloux (University of Oslo)
6#
7# @Date: October 2014
8#
9# @Change History:
10#
11#    November 2015 - Leopold Haimberger (University of Vienna):
12#        - job submission on ecgate and cca
13#        - job templates suitable for twice daily operational dissemination
14#
15#    February 2018 - Anne Philipp (University of Vienna):
16#        - applied PEP8 style guide
17#        - added documentation
18#        - minor changes in programming style (for consistence)
[2fb99de]19#        - changed path names to variables from config file
20#        - added option for writing mars requests to extra file
[6f951ca]21#          additionally, as option without submitting the mars jobs
22#        - splitted submit function to use genshi templates for the
23#          job script and avoid code duplication
[a916e8f]24#    June 2020 - Anne Philipp
25#        - changed finale job_file to filename from config file
26#          instead of generating from the template filename
[991df6a]27#
28# @License:
[026b359]29#    (C) Copyright 2014-2020.
[6f951ca]30#    Anne Philipp, Leopold Haimberger
[991df6a]31#
[44174de]32#    SPDX-License-Identifier: CC-BY-4.0
33#
[6f951ca]34#    This work is licensed under the Creative Commons Attribution 4.0
35#    International License. To view a copy of this license, visit
36#    http://creativecommons.org/licenses/by/4.0/ or send a letter to
37#    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
[991df6a]38#*******************************************************************************
[6f951ca]39'''This script allows the user to extract meteorological fields from the ECMWF.
40
41It prepares the settings for retrieving the data from ECMWF servers and
42process the resulting files to prepare them for the use with FLEXPART or
43FLEXTRA.
44
45If it is supposed to work locally then it works through the necessary
46functions get_mars_data and prepare_flexpart. Otherwise it prepares
47a job script (korn shell) which will do the necessary work on the
48ECMWF server. This script will de submitted via the ecaccess command
49ecaccess-job-submit.
50
51This file can also be imported as a module which then contains the following
52functions:
53
54    * main - the main function of the script
55    * submit - calls mk_jobscript depending on operation mode and submits its
56    * mk_jobscript - creates the job script from a template
57
58Type: submit.py --help
59to get information about command line parameters.
60Read the documentation for usage instructions.
61'''
[efdb01a]62
[64cf353]63# ------------------------------------------------------------------------------
64# MODULES
65# ------------------------------------------------------------------------------
[a1011e7]66from __future__ import print_function
67
[efdb01a]68import os
69import sys
[f2616a3]70from datetime import datetime, timedelta
[efdb01a]71
72# software specific classes and modules from flex_extract
[54a8a01]73import _config
[0f89116]74from Mods.tools import (setup_controldata, normal_exit,
[6e16c9d]75                        submit_job_to_ecserver,
76                        submit_eventjob_to_ecserver)
[ba99230]77from Mods.get_mars_data import get_mars_data
78from Mods.prepare_flexpart import prepare_flexpart
[d727af2]79
[64cf353]80# ------------------------------------------------------------------------------
[6f951ca]81# METHODS
[64cf353]82# ------------------------------------------------------------------------------
[991df6a]83
[d69b677]84def main():
[274f9ef]85    '''Get the arguments from script call and from CONTROL file.
86    Decides from the argument "queue" if the local version
87    is done "queue=None" or the gateway version with "queue=ecgate"
88    or "queue=cca".
89
90    Parameters
91    ----------
[d69b677]92
[d727af2]93
[274f9ef]94    Return
95    ------
[64cf353]96
97    '''
[ff99eae]98
[f20af73]99    c, ppid, queue, job_template = setup_controldata()
[ff99eae]100
[efdb01a]101    # on local side
[f20af73]102    # starting from an ECMWF server this would also be the local side
[2fb99de]103    called_from_dir = os.getcwd()
[f20af73]104    if queue is None:
[64cf353]105        if c.inputdir[0] != '/':
[ff99eae]106            c.inputdir = os.path.join(called_from_dir, c.inputdir)
[64cf353]107        if c.outputdir[0] != '/':
[ff99eae]108            c.outputdir = os.path.join(called_from_dir, c.outputdir)
[54a8a01]109        get_mars_data(c)
[2fb99de]110        if c.request == 0 or c.request == 2:
[f20af73]111            prepare_flexpart(ppid, c)
[96e1533]112            exit_message = 'FLEX_EXTRACT IS DONE!'
[2fb99de]113        else:
[96e1533]114            exit_message = 'PRINTING MARS_REQUESTS DONE!'
115    # send files to ECMWF server
[d69b677]116    else:
[f20af73]117        submit(job_template, c, queue)
[47be2684]118        exit_message = 'FLEX_EXTRACT JOB SCRIPT IS SUBMITTED!'
[64cf353]119
[403cbf1]120    normal_exit(exit_message)
[96e1533]121
[64cf353]122    return
123
124def submit(jtemplate, c, queue):
[ff2a11c]125    '''Prepares the job script and submits it to the specified queue.
[274f9ef]126
127    Parameters
128    ----------
[6f951ca]129    jtemplate : str
[274f9ef]130        Job template file from sub-directory "_templates" for
131        submission to ECMWF. It contains all necessary
132        module and variable settings for the ECMWF environment as well as
133        the job call and mail report instructions.
[5f67883]134        Default is _config.TEMPFILE_JOB.
[274f9ef]135
[6f951ca]136    c : ControlFile
[274f9ef]137        Contains all the parameters of CONTROL file and
138        command line.
139
[6f951ca]140    queue : str
[274f9ef]141        Name of queue for submission to ECMWF (e.g. ecgate or cca )
142
143    Return
144    ------
145
[64cf353]146    '''
147
[d4696e0]148    if not c.oper:
[54a8a01]149    # --------- create on demand job script ------------------------------------
[a4531f1]150        if c.purefc:
[2fb99de]151            print('---- Pure forecast mode! ----')
[54a8a01]152        else:
[2fb99de]153            print('---- On-demand mode! ----')
[54a8a01]154
[ff2a11c]155        job_file = os.path.join(_config.PATH_JOBSCRIPTS,
[a916e8f]156                                _config.FILE_JOB_OD)
[54a8a01]157
[f2616a3]158        # divide time periode into specified number of job chunks
159        # to have multiple job scripts
160        if c.job_chunk:
161            start = datetime.strptime(c.start_date, '%Y%m%d')
162            end = datetime.strptime(c.end_date, '%Y%m%d')
163            chunk = timedelta(days=c.job_chunk)
[fc05fbd]164            oneday = timedelta(days=1)
[54a8a01]165
[f2616a3]166            while start <= end:
167                if (start + chunk) <= end:
[fc05fbd]168                    c.end_date = (start + chunk - oneday).strftime("%Y%m%d")
[f2616a3]169                else:
170                    c.end_date = end.strftime("%Y%m%d")
171
172                clist = c.to_list()
173                mk_jobscript(jtemplate, job_file, clist)
174
175                job_id = submit_job_to_ecserver(queue, job_file)
176                print('The job id is: ' + str(job_id.strip()))
177
178                start = start + chunk
179                c.start_date = start.strftime("%Y%m%d")
180        # submit a single job script
181        else:
182            clist = c.to_list()
183
184            mk_jobscript(jtemplate, job_file, clist)
185
186            job_id = submit_job_to_ecserver(queue, job_file)
187            print('The job id is: ' + str(job_id.strip()))
[54a8a01]188
189    else:
190    # --------- create operational job script ----------------------------------
[2fb99de]191        print('---- Operational mode! ----')
[ff2a11c]192
[2fb99de]193        job_file = os.path.join(_config.PATH_JOBSCRIPTS,
[a916e8f]194                                _config.FILE_JOB_OP)
[54a8a01]195
196        c.start_date = '${MSJ_YEAR}${MSJ_MONTH}${MSJ_DAY}'
197        c.end_date = '${MSJ_YEAR}${MSJ_MONTH}${MSJ_DAY}'
[d4696e0]198        c.basetime = '${MSJ_BASETIME}'
[54a8a01]199
[ff2a11c]200        clist = c.to_list()
[54a8a01]201
[ff2a11c]202        mk_jobscript(jtemplate, job_file, clist)
[d69b677]203
[b8037ed]204        if not c.eventid:
205            job_id = submit_job_to_ecserver(queue, job_file)
206        else:
207            job_id = submit_eventjob_to_ecserver(queue, job_file, c.eventid,
208                                                 c.eventjobname, c.ecuid)
[0540bd0]209
[f2616a3]210        print('The job id is: ' + str(job_id.strip()))
211
212    print('You should get an email per job with subject flex.hostname.pid')
[d69b677]213
[64cf353]214    return
[d69b677]215
[ff2a11c]216def mk_jobscript(jtemplate, job_file, clist):
217    '''Creates the job script from template.
218
219    Parameters
220    ----------
[6f951ca]221    jtemplate : str
[a916e8f]222        Job template file from sub-directory "Templates" for
[ff2a11c]223        submission to ECMWF. It contains all necessary
224        module and variable settings for the ECMWF environment as well as
225        the job call and mail report instructions.
[5f67883]226        Default is _config.TEMPFILE_JOB.
[ff2a11c]227
[6f951ca]228    job_file : str
[ff2a11c]229        Path to the job script file.
230
[6f951ca]231    clist : list of str
[ff2a11c]232        Contains all necessary parameters for ECMWF CONTROL file.
233
234    Return
235    ------
236
237    '''
238    from genshi.template.text import NewTextTemplate
239    from genshi.template import  TemplateLoader
240    from genshi.template.eval import UndefinedError
241
242    # load template and insert control content as list
243    try:
244        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
245        control_template = loader.load(jtemplate,
246                                       cls=NewTextTemplate)
247
248        stream = control_template.generate(control_content=clist)
249    except UndefinedError as e:
250        print('... ERROR ' + str(e))
251
252        sys.exit('\n... error occured while trying to generate jobscript')
253    except OSError as e:
254        print('... ERROR CODE: ' + str(e.errno))
255        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
256
257        sys.exit('\n... error occured while trying to generate jobscript')
258
259    # create jobscript file
260    try:
261        with open(job_file, 'w') as f:
262            f.write(stream.render('text'))
263    except OSError as e:
264        print('... ERROR CODE: ' + str(e.errno))
265        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
266
267        sys.exit('\n... error occured while trying to write ' + job_file)
268
269    return
270
[f2616a3]271
[d69b677]272if __name__ == "__main__":
273    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG