添加 Family#

接下来添加一组处理 NCEP GFS 预报数据的任务,为 CMA-TYM 生成背景场数据。 下面将创建 Family 节点 get_ncep,为 0 到 120 小时每隔 3 小时创建一个数据预处理任务。

修改工作流定义#

更新 ${TUTORIAL_HOME}/def 中的工作流定义文件 cma_tym.py

 1import os
 2
 3import ecflow
 4
 5
 6def slurm_serial(class_name="serial"):
 7    variables = {
 8        "ECF_JOB_CMD": "slsubmit6 %ECF_JOB% %ECF_NAME% %ECF_TRIES% %ECF_TRYNO% %ECF_HOST% %ECF_PORT%",
 9        "ECF_KILL_CMD": "slcancel4 %ECF_RID% %ECF_NAME% %ECF_HOST% %ECF_PORT%",
10        "CLASS": class_name,
11    }
12    return variables
13
14
15current_path = os.path.dirname(__file__)
16tutorial_base = os.path.abspath(os.path.join(current_path, "../"))
17def_path = os.path.join(tutorial_base, "def")
18ecfout_path = os.path.join(tutorial_base, "ecfout")
19program_base_dir = os.path.join(tutorial_base, "program/grapes-tym-program")
20run_base_dir = os.path.join(tutorial_base, "workdir")
21
22defs = ecflow.Defs()
23
24with defs.add_suite("cma_tym") as suite:
25    suite.add_variable("PROGRAM_BASE_DIR", program_base_dir)
26    suite.add_variable("RUN_BASE_DIR", run_base_dir)
27
28    suite.add_variable("ECF_INCLUDE", os.path.join(def_path, "include"))
29    suite.add_variable("ECF_FILES", os.path.join(def_path, "ecffiles"))
30
31    suite.add_variable("USE_GRAPES", ".false.")
32    suite.add_variable("FORECAST_LENGTH", 120)
33    suite.add_variable("GMF_TINV", 3)
34    suite.add_variable("RMF_TINV", 3)
35    suite.add_variable("USE_GFS", 12)
36
37    suite.add_variable("ECF_DATE", "20220704")
38    suite.add_variable("HH", "00")
39
40    suite.add_limit("total_tasks", 10)
41    suite.add_inlimit("total_tasks")
42
43    with suite.add_task("copy_dir") as tk_copy_dir:
44        pass
45
46    with suite.add_task("get_message") as tk_get_message:
47        tk_get_message.add_trigger("./copy_dir == complete")
48        tk_get_message.add_variable(slurm_serial("serial"))
49        tk_get_message.add_event("arrived")
50        tk_get_message.add_event("peaceful")
51
52    with suite.add_family("get_ncep") as fm_get_ncep:
53        fm_get_ncep.add_trigger("./get_message == complete")
54        fm_get_ncep.add_variable(slurm_serial("serial"))
55        for hour in range(0, 120 + 1, 3):
56            hour_string = "{hour:03}".format(hour=hour)
57            with fm_get_ncep.add_task(hour_string) as tk_hour:
58                tk_hour.add_variable("FFF", hour_string)
59                tk_hour.add_variable(
60                    "ECF_SCRIPT_CMD",
61                    "cat {def_path}/ecffiles/getgmf_ncep.ecf".format(def_path=def_path)
62                )
63
64
65print(defs)
66def_output_path = str(os.path.join(def_path, "cma_tym.def"))
67defs.save_as_defs(def_output_path)

40-41 行创建一个 Limit,并将该 Limit 应用到 cma_tym 节点上,限制同时运行的任务不能超过 10 个。

备注

对于需要运行大量任务的工作流,一定要限制同时运行的任务数,避免同一时间大量提交作业导致 ecFlow 服务卡死。

52-62 行创建 Family 节点 get_ncep,逐三小时创建以三位时效数字作为名称的任务。

任务通过 ECF_SCRIPT_CMD 变量设置任务对应的 ecf 脚本,ecFlow 会将 ECF_SCRIPT_CMD 命令的输出作为该任务的 ecf 脚本。

更新工作流#

与前一节一样,需要重新生成 def 文件并更新到 ecFlow 服务中。 在更新之前,我们先在 ecFlowUI 中将 cma_tym 节点挂起,避免更新后系统提交大量作业。

更新工作流:

cd ${TUTORIAL_HOME}/def
python cma_tym.py
ecflow_client --port 43083 --replace /cma_tym cma_tym.def

为了节省时间,我们可以将之前已跑过的任务强制设为完成状态 (complete),也可以手动设置事件。 比如,右键单击 copy_dir 任务,选择 Set complete,会将 get_message 任务强制设为 complete 状态。

../_images/ecflow-ui-set-complete.png

创建任务脚本#

${TUTORIAL_HOME}/def/ecffiles 目录下创建 ecf 脚本 getgmf_ncep.ecf

#!/bin/ksh
%include <slurm_serial.h>
%include <head.h>
%include <configure.h>
#--------------------------------------
# common variables
endian="little_endian"
res=0p50

# ecflow variables
TTT=%FFF%

# time
BDYTIME=${START_TIME}
BDYDATE=$(echo $BDYTIME |cut -c1-8)
BDYYYYY=$(echo $BDYTIME |cut -c1-4)
BDYHH=$(echo $BDYTIME |cut -c9-10)
REALTIME=$(smsdate $BDYTIME +${TTT})

# directory
NCEP_GFS_SRC_DIR=/g1/COMMONDATA/glob/gfs/${BDYYYYY}/gfs.$BDYTIME

NCEP_GFS_LOCAL_DIR=${CYCLE_GMF_DIR}/${START_TIME}
dataproc_dir=${CYCLE_GMF_DIR}/data_proc
bckg_dir=${CYCLE_RUN_DIR}/bckg_data

#----------------------------
RUN_DIR=${CYCLE_GMF_DIR}
cd ${RUN_DIR}

test -d ${NCEP_GFS_LOCAL_DIR} || mkdir -p ${NCEP_GFS_LOCAL_DIR}
test -d ${dataproc_dir}/$TTT || mkdir -p ${dataproc_dir}/$TTT

gfsfile=${NCEP_GFS_LOCAL_DIR}/${TTT}/gfs.t${BDYHH}z.pgrb2.${res}.f${TTT}
gfsprefix=gfs.t${BDYHH}z.pgrb2.${res}
gfsfhour=${TTT}

# check NCEP data
if [ ! -f ${NCEP_GFS_SRC_DIR}/gfs.t${BDYHH}z.pgrb2.${res}.f${TTT} ]; then
    echo "NO NCEP GFS data"
    this_is_an_error
fi

mkdir -p ${NCEP_GFS_LOCAL_DIR}/${TTT}
cd ${NCEP_GFS_LOCAL_DIR}/${TTT}
cp ${NCEP_GFS_SRC_DIR}/gfs.t${BDYHH}z.pgrb2.${res}.f${TTT} .

#------------------------------------
# preprocess gfs data
cd ${dataproc_dir}/$TTT

wgrib2  -s $gfsfile \
    | egrep -v ":TMP:0.4 mb:|:HGT:0.4 mb:|:TMP:15 mb:|:HGT:15 mb:|:TMP:40 mb:|:HGT:40 mb:" \
    | wgrib2 -i $gfsfile -GRIB ./$( basename ${gfsfile} )

ln -sf ${PROGRAM_BIN_DIR}/newdate .
ln -sf ${PROGRAM_BIN_DIR}/read_for_grapes.exe .
ln -sf ${PROGRAM_SCRIPT_DIR}/grib2bin.sh.meso grib2bin.sh

./grib2bin.sh $(pwd)/${gfsprefix}.f*[FF] ${endian} ${gfsfhour} 3 ${gfsfhour}

mv ${dataproc_dir}/$TTT/bckg_$REALTIME ${bckg_dir}

# copy namelist
if [ `expr $TTT` -eq 0 ];then
    cp namelist.grib ${dataproc_dir}
fi

if [ ${TTT} = "000" ]; then
  cd ${bckg_dir}
  cp ModelName_gfs.txt ModelName.txt
fi

#---------------------------------------
%include <tail.h>

该脚本从当前预报时次的 NCEP GFS GRIB2 数据文件中提取背景场信息,生成 bckg_YYYYMMDDHH 文件,存放到 bckg 目录中。

运行任务#

创建脚本后,可以恢复 cma_tym 自动运行。 右键单击 cma_tym,选择 Resume,恢复工作流运行。可以看到 get_ncep 下面前 10 个作业开始运行:

../_images/ecflow-ui-run-limit.png

因为我们创建的 Limit (total_tasks) 限制最多运行 10 个任务,所以有 1 个任务运行结束后第 11 个任务才会自动运行。

查看 bckg 目录,检查背景场文件是否生成:

cd ${TUTORIAL_HOME}/workdir/2022070400/run/bckg_data
ls -l bckg_2022*
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:44 bckg_2022070400
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070403
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:44 bckg_2022070406
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:44 bckg_2022070409
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:44 bckg_2022070412
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070415
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070418
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070421
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070500
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070503
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070506
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070509
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070512
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070515
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070518
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070521
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070600
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070603
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070606
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070609
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070612
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070615
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070618
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070621
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070700
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070703
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070706
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070709
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070712
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070715
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070718
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070721
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070800
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070803
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070806
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070809
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070812
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070815
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070818
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070821
-rw-r--r-- 1 wangdp nop 150754760 Jul 25 05:45 bckg_2022070900