Пример #1
0
 def download_gdas(time):
     dir_name = f'gdas.{time.format("YYYYMMDD")}/{time.format("HH")}'
     res = requests.head(f'{root_url}/{dir_name}/')
     if res.status_code != 200 and res.status_code != 302:
         cli.error(f'Remote GDAS data at {time} do not exist!')
     file_name = 'gdas.t{:02d}z.prepbufr.nr'.format(time.hour)
     url = f'{root_url}/{dir_name}/{file_name}'
     if not os.path.isdir(f'{output_root}/{dir_name}'):
         os.makedirs(f'{output_root}/{dir_name}')
         cli.notice(f'Create directory {output_root}/{dir_name}.')
     cli.notice(f'Downloading {url}.')
     local_file_path = f'{output_root}/{dir_name}/{file_name}'
     if is_downloading(local_file_path):
         cli.warning(f'Skip downloading {local_file_path}.')
         return
     if os.path.isfile(local_file_path):
         if check_file_size(url, local_file_path):
             cli.notice(f'File {local_file_path} exists.')
             return
         else:
             # File is not downloaded completely.
             os.remove(local_file_path)
     try:
         subprocess.call(['curl', '-C', '-', '-o', local_file_path, url])
     except Exception as e:
         cli.error(f'Encounter exception {e}!')
     if not check_file_size(url, local_file_path):
         os.remove(local_file_path)
         cli.error(f'Failed to download {file_name}!')
Пример #2
0
	def download_gfs(start_time, forecast_hour):
		dir_name = f'{prefix}.{start_time.format("YYYYMMDD")}/{start_time.format("HH")}'
		file_name = '{}.t{:02d}z.pgrb2.{}.f{:03d}'.format(prefix, start_time.hour, resolution, forecast_hour)
		url = f'{root_url}/{dir_name}/{file_name}'
		if not os.path.isdir(f'{output_root}/{dir_name}'):
			os.makedirs(f'{output_root}/{dir_name}')
			cli.notice(f'Create directory {output_root}/{dir_name}.')
		cli.notice(f'Downloading {url}.')
		local_file_path = f'{output_root}/{dir_name}/{file_name}'
		if is_downloading(local_file_path):
			cli.warning(f'Skip downloading {local_file_path}.')
			return
		if os.path.isfile(local_file_path):
			if check_file_size(url, local_file_path):
				cli.notice(f'File {local_file_path} exists.')
				return
			else:
				# File is not downloaded completely.
				os.remove(local_file_path)
		try:
			subprocess.call(['curl', '-C', '-', '-o', local_file_path, url])
		except Exception as e:
			cli.error('Encounter exception {e}!')
		if not check_file_size(url, local_file_path):
			os.remove(local_file_path)
			cli.error(f'Failed to download {file_name}!')
Пример #3
0
def run_wrfplus_ad(work_root, wrfplus_root, config, args):
	start_time = config['custom']['start_time']
	end_time = config['custom']['end_time']
	datetime_fmt = 'YYYY-MM-DD_HH:mm:ss'
	start_time_str = start_time.format(datetime_fmt)
	max_dom = config['domains']['max_dom']

	wrf_work_dir = os.path.abspath(work_root) + '/wrf'
	if not os.path.isdir(wrf_work_dir):
		cli.error(f'WRF work directory {wrf_work_dir} does not exist!')

	wrfplus_work_dir = os.path.abspath(work_root) + '/wrfplus'
	if not os.path.isdir(wrfplus_work_dir):
		cli.error(f'WRFPLUS has not been configured! Run config_wrfplus.py first.')
	os.chdir(wrfplus_work_dir)

	if os.path.isfile(f'{wrf_work_dir}/wrfinput_d01_{start_time_str}'):
		run(f'ln -sf {wrf_work_dir}/wrfinput_d01 .')
	elif os.path.isfile(f'{wrf_work_dir}/wrfout_d01_{start_time_str}'):
		run(f'ln -sf {wrf_work_dir}/wrfout_d01_{start_time_str} wrfinput_d01')
	run(f'ln -sf {wrf_work_dir}/wrfbdy_d01 .')
	if not os.path.isfile('final_sens_d01'):
		cli.error('There is no final_sens_d01 file!')

	version = wrf_version(wrfplus_root)

	cli.stage(f'Run WRFPLUS at {wrfplus_work_dir} ...')
	expected_files = ['wrfout_d{:02d}_{}'.format(i + 1, start_time_str) for i in range(max_dom)]
	expected_files.append(f'init_sens_d01_{start_time_str}')
	if not check_files(expected_files) or args.force:
		run('rm -f wrfout_*')
		run(f'ln -sf {wrfplus_root}/run/LANDUSE.TBL .')
		run(f'ln -sf {wrfplus_root}/run/VEGPARM.TBL .')
		run(f'ln -sf {wrfplus_root}/run/SOILPARM.TBL .')
		run(f'ln -sf {wrfplus_root}/run/GENPARM.TBL .')
		run(f'ln -sf {wrfplus_root}/run/RRTM_DATA_DBL RRTM_DATA')
		run(f'ln -sf {wrfplus_root}/run/ETAMPNEW_DATA_DBL ETAMPNEW_DATA')
		if version >= Version('4.0'):
			cmd = f'{wrfplus_root}/run/wrfplus.exe'
		else:
			cmd = f'{wrfplus_root}/run/wrf.exe'
		retries = 0
		while True:
			submit_job(cmd, args.np, config, args, wait=True)
			if os.path.isfile(f'gradient_wrfplus_d01_{start_time_str}'):
				run(f'mv gradient_wrfplus_d01_{start_time_str} init_sens_d01_{start_time_str}')
			if not check_files(expected_files):
				if retries == 10:
					cli.error(f'Failed! Check output {os.path.abspath(wrfplus_work_dir)}/rsl.error.0000.')
				retries = retries + 1
				cli.warning('Failed to run wrfplus, retry it!')
			else:
				break
		cli.notice('Succeeded.')
	else:
		cli.notice('File wrfout_* already exist.')
	run(f'ls -l {wrfplus_work_dir}/wrfout_*')
Пример #4
0
def run_wrfda_3dvar(work_root,
                    wrfda_root,
                    config,
                    args,
                    wrf_work_dir=None,
                    force=False,
                    tag=None,
                    fg=None):
    start_time = config['custom']['start_time']
    datetime_fmt = 'YYYY-MM-DD_HH:mm:ss'
    start_time_str = start_time.format(datetime_fmt)
    max_dom = config['domains']['max_dom']

    if not wrf_work_dir:
        if tag != None:
            wrf_work_dir = f'{work_root}/wrf_{tag}'
        else:
            wrf_work_dir = f'{work_root}/wrf'

    if tag != None:
        obsproc_work_dir = f'{work_root}/wrfda_{tag}/obsproc'
    else:
        obsproc_work_dir = f'{work_root}/wrfda/obsproc'

    if max_dom > 1:
        dom_str = 'd' + str(config['custom']['wrfda']['dom'] + 1).zfill(2)
        if tag != None:
            wrfda_work_dir = f'{work_root}/wrfda_{tag}/{dom_str}'
        else:
            wrfda_work_dir = f'{work_root}/wrfda/{dom_str}'
    else:
        dom_str = 'd01'
        if tag != None:
            wrfda_work_dir = f'{work_root}/wrfda_{tag}'
        else:
            wrfda_work_dir = f'{work_root}/wrfda'
    if not os.path.isdir(wrfda_work_dir): os.mkdir(wrfda_work_dir)
    os.chdir(wrfda_work_dir)

    cli.stage(f'Run da_wrfvar.exe at {wrfda_work_dir} ...')

    if os.path.isfile(f'wrfvar_output_{start_time_str}'
                      ) and not args.force and not force:
        run(f'ls -l wrfvar_output_{start_time_str}')
        cli.notice(f'wrfvar_output_{start_time_str} already exist.')
        return

    run(f'ln -sf {wrfda_root}/run/LANDUSE.TBL {wrfda_work_dir}')

    if not os.path.isfile('namelist.input'):
        cli.error(
            'namelist.input has not been generated! Run config_wrfda.py.')

    # BE matrix
    if 'cv_options' in config['wrfvar7']:
        be_work_dir = os.path.dirname(
            os.path.abspath(work_root)) + '/be/' + dom_str
        if not os.path.isdir(be_work_dir):
            be_work_dir = os.path.dirname(
                os.path.abspath(work_root)) + '/../be/' + dom_str

        if config['wrfvar7']['cv_options'] == 5:
            if not os.path.isfile(f'{be_work_dir}/be.dat.cv5'):
                cli.error(
                    f'BE matrix {be_work_dir}/be.dat.cv5 does not exist!')
            run(f'ln -sf {be_work_dir}/be.dat.cv5 be.dat')
        elif config['wrfvar7']['cv_options'] == 6:
            if not os.path.isfile(f'{be_work_dir}/be.dat.cv6'):
                cli.error(
                    f'BE matrix {be_work_dir}/be.dat.cv6 does not exist!')
            run(f'ln -sf {be_work_dir}/be.dat.cv6 be.dat')
        elif config['wrfvar7']['cv_options'] == 7:
            if not os.path.isfile(f'{be_work_dir}/be.dat.cv7'):
                cli.error(
                    f'BE matrix {be_work_dir}/be.dat.cv7 does not exist!')
            run(f'ln -sf {be_work_dir}/be.dat.cv7 be.dat')
    if not os.path.exists('./be.dat'):
        run(f'ln -sf {wrfda_root}/var/run/be.dat.cv3 be.dat')

    # First guess
    # TODO: Assume there is only one domain to be assimilated.
    if fg != None:
        run(f'ln -sf {fg} {wrfda_work_dir}/fg')
    else:
        expected_files = [
            '{}/wrfout_d{:02d}_{}'.format(wrf_work_dir, i + 1, start_time_str)
            for i in range(max_dom)
        ]
        if check_files(expected_files):
            run(f'ln -sf {wrf_work_dir}/wrfout_{dom_str}_{start_time_str} {wrfda_work_dir}/fg'
                )
        else:
            expected_files = [
                '{}/wrfinput_d{:02d}_{}'.format(wrf_work_dir, i + 1,
                                                start_time_str)
                for i in range(max_dom)
            ]
            if not check_files(expected_files):
                cli.error(
                    'real.exe or da_update_bc.exe wasn\'t executed successfully!'
                )
            run(f'ln -sf {wrf_work_dir}/wrfinput_{dom_str}_{start_time_str} {wrfda_work_dir}/fg'
                )

    # Observation data
    if config['custom']['wrfda']['type'] == '3dvar':
        if 'use_radarobs' in config['wrfvar4'] and config['wrfvar4'][
                'use_radarobs']:
            # Radar data
            run(f'rm -f ob.*')
            for obs_radar_file in glob(
                    f'{args.littler_root}/{start_time.format("YYYYMMDD")}/obs.radar.*'
            ):
                radar_time = pendulum.from_format(
                    os.path.basename(obs_radar_file).split('.')[2],
                    'YYYYMMDDHHmm')
                if radar_time == start_time:
                    run(f'ln -sf {obs_radar_file} ob.radar')
            if os.path.isfile(f'wrfvar_output_{start_time_str}'):
                cli.notice('Use previous analysis data as the background.')
                run(f'mv wrfvar_output_{start_time_str} wrfvar_output_conv_{start_time_str}'
                    )
                run(f'ln -sf wrfvar_output_conv_{start_time_str} fg')
        elif 'conv_obs' in config['custom']:
            if 'dir_pattern' in config['custom']['conv_obs']:
                obs_dir = Template(
                    config['custom']['conv_obs']['dir_pattern']).render(
                        obs_time=start_time)
            if 'file_pattern' in config['custom']['conv_obs']:
                obs_file = Template(
                    config['custom']['conv_obs']['file_pattern']).render(
                        obs_time=start_time)
            if config['wrfvar3']['ob_format'] == 1:
                run(f'ln -sf {args.prepbufr_root}/{obs_dir}/{obs_file} ob.bufr'
                    )
            elif config['wrfvar3']['ob_format'] == 2:
                run(f'ln -sf {args.prepbufr_root}/{obs_dir}/{obs_file} ob.ascii'
                    )
        elif config['wrfvar3']['ob_format'] == 2 and os.path.isfile(
                f'{obsproc_work_dir}/obs_gts_{start_time.format(datetime_fmt)}.3DVAR'
        ):
            # LITTLE_R conventional data
            run(f'ln -sf {obsproc_work_dir}/obs_gts_{start_time.format(datetime_fmt)}.3DVAR ob.ascii'
                )
        elif config['wrfvar3']['ob_format'] == 1 and config['custom']['wrfda'][
                'prepbufr_source'] == 'gdas':
            # PREPBUFR conventional data
            gdas_file_path = f'{args.prepbufr_root}/gdas.{start_time.format("YYYYMMDD")}/gdas.t{start_time.hour:02}z.prepbufr.nr'
            if not os.path.isfile(gdas_file_path):
                cli.error(f'{gdas_file_path} does not exist!')
            run(f'ln -sf {gdas_file_path} ob.bufr')

    if os.path.isfile(f'{wrfda_work_dir}/wrfvar_output_{start_time_str}'
                      ) and not args.force:
        cli.notice(
            f'{wrfda_work_dir}/wrfvar_output_{start_time_str} already exists.')
        return

    submit_job(f'{wrfda_root}/var/build/da_wrfvar.exe',
               min(20, args.np),
               config,
               args,
               wait=True)

    expected_files = [f'wrfvar_output', 'statistics']
    if not check_files(expected_files):
        # Check if the failure is caused by parallel computing? Such as cv_options is zero in some process.
        if search_files('rsl.error.*',
                        'Invalid CV option chosen:  cv_options =    0'):
            cli.warning(
                'Failed to run da_wrfvar.exe in parallel. Try to run in serial.'
            )
            submit_job(f'{wrfda_root}/var/build/da_wrfvar.exe',
                       1,
                       config,
                       args,
                       wait=True)
            if not check_files(expected_files):
                cli.error(
                    f'Still failed! See {wrfda_work_dir}/rsl.error.0000.')
        else:
            cli.error(f'Failed! See {wrfda_work_dir}/rsl.error.0000.')
    else:
        print(open('statistics').read())
        run(f'ncl -Q {scripts_root}/../plots/plot_cost_grad_fn.ncl')
        run(f'cp wrfvar_output wrfvar_output_{start_time_str}')
        cli.notice('Succeeded.')
Пример #5
0
def build_nceplibs(nceplibs_root, args):
    if not 'HDF5' in os.environ:
        res = subprocess.run(['which', 'h5dump'], stdout=subprocess.PIPE)
        if res.returncode == 0:
            os.environ['HDF5'] = os.path.dirname(
                os.path.dirname(res.stdout.decode('utf-8')))
            cli.notice(f'Set HDF5 to {os.environ["HDF5"]}')
    if not 'HDF5' in os.environ:
        cli.warning('HDF5 environment variable is not set')

    if not 'NETCDF' in os.environ:
        res = subprocess.run(['which', 'ncdump'], stdout=subprocess.PIPE)
        if res.returncode == 0:
            os.environ['NETCDF'] = os.path.dirname(
                os.path.dirname(res.stdout.decode('utf-8')))
            cli.notice(f'Set NETCDF to {os.environ["NETCDF"]}')
    if not 'NETCDF' in os.environ:
        cli.warning('NETCDF environment variable is not set!')

    if not 'JASPER_INC' in os.environ or not 'JASPER_LIB' in os.environ:
        if 'JASPER_ROOT' in os.environ:
            os.environ['JASPER_INC'] = os.environ['JASPER_ROOT'] + '/include'
            os.environ['JASPER_LIB'] = os.environ['JASPER_ROOT'] + '/lib'
            cli.notice(f'Set JASPER_INC to {os.environ["JASPER_INC"]}.')
            cli.notice(f'Set JASPER_LIB to {os.environ["JASPER_LIB"]}.')
        else:
            cli.error(
                'JASPERINC and JASPERLIB environment variables are not set!')

    if not 'PNG_INC' in os.environ or not 'PNG_LIB' in os.environ:
        if 'LIBPNG_ROOT' in os.environ:
            os.environ['PNG_INC'] = os.environ['LIBPNG_ROOT'] + '/include'
            os.environ['PNG_LIB'] = os.environ['LIBPNG_ROOT'] + '/lib'
        else:
            os.environ['PNG_INC'] = '/usr/include'
            os.environ['PNG_LIB'] = '/usr/lib64'
        cli.notice(f'Set PNG_INC to {os.environ["PNG_INC"]}.')
        cli.notice(f'Set PNG_LIB to {os.environ["PNG_LIB"]}.')

    os.chdir(nceplibs_root)

    if args.compiler_suite == 'gnu':
        # Fix for gfortran 9.1.0.
        edit_file('src/g2/v3.1.0/src/intmath.f',
                  [['iand\(i,i-1\)/=0', 'iand(i,i-1_8)/=0']],
                  return_on_first_match=True)
        edit_file('src/g2/v3.1.0/src/intmath.f',
                  [['iand\(i,i-1\)/=0', 'iand(i,i-1_4)/=0']],
                  return_on_first_match=True)
        edit_file('src/g2/v3.1.0/src/intmath.f',
                  [['iand\(i,i-1\)/=0', 'iand(i,i-1_2)/=0']],
                  return_on_first_match=True)
        edit_file('src/g2/v3.1.0/src/intmath.f',
                  [['iand\(i,i-1\)/=0', 'iand(i,i-1_1)/=0']],
                  return_on_first_match=True)

    edit_file('make_ncep_libs.sh',
              [['read -p "Proceed\? \(y/n\) " yn', 'yn=y']])

    run(f'./make_ncep_libs.sh -s linux -c {args.compiler_suite} -d {args.nceplibs_root} -o 0 -a upp'
        )
Пример #6
0
def build_gsi(wrf_root, gsi_root, args):
    # Check environment.
    if not 'HDF5' in os.environ:
        res = subprocess.run(['which', 'h5dump'], stdout=subprocess.PIPE)
        if res.returncode == 0:
            os.environ['HDF5'] = os.path.dirname(
                os.path.dirname(res.stdout.decode('utf-8')))
            cli.notice(f'Set HDF5 to {os.environ["HDF5"]}')
    if not 'HDF5' in os.environ:
        cli.warning('HDF5 environment variable is not set')

    if not 'NETCDF' in os.environ:
        res = subprocess.run(['which', 'ncdump'], stdout=subprocess.PIPE)
        if res.returncode == 0:
            os.environ['NETCDF'] = os.path.dirname(
                os.path.dirname(res.stdout.decode('utf-8')))
            cli.notice(f'Set NETCDF to {os.environ["NETCDF"]}')
    if not 'NETCDF' in os.environ:
        cli.warning('NETCDF environment variable is not set!')

    if not os.getenv('LAPACK_PATH') and args.compiler_suite != 'intel':
        cli.error('Shell variable LAPACK_PATH is not set!')

    version = gsi_version(args.gsi_root)

    if version <= Version('3.6'):
        # 3.7 changes: Added wrf interface as a library (wrflib). No need to compile WRF with GSI and EnKF.
        if not os.path.isdir(args.wrf_root):
            cli.error(f'WRF directory {args.wrf_root} does not exist!')
        os.chdir(args.wrf_root)
        expected_exe_files = ('main/wrf.exe')
        if not check_files(expected_exe_files):
            cli.error('WRF has not been built! Build it first.')

    os.chdir(args.gsi_root)

    if args.force: run('rm -rf build')
    if not os.path.isdir('build'): os.mkdir('build')
    os.chdir('build')
    if version == Version('3.6'):
        expected_exe_files = ('bin/gsi.x', 'lib/libbacio_v2.0.1.a',
                              'lib/libbufr_v10.2.5.a', 'lib/libcrtm_v2.2.3.a',
                              'lib/libenkfdeplib.a', 'lib/libenkflib.a',
                              'lib/libgsilib_shrd.a', 'lib/libgsilib_wrf.a',
                              'lib/libnemsio_v2.2.1.a',
                              'lib/libsfcio_v1.1.0.a', 'lib/libsigio_v2.0.1.a',
                              'lib/libsp_v2.0.2.a', 'lib/libw3emc_v2.2.0.a',
                              'lib/libw3nco_v2.0.6.a')
    elif version == Version('3.7'):
        expected_exe_files = ('bin/enkf_wrf.x', 'bin/gsi.x',
                              'lib/libbacio_v2.0.1.a', 'lib/libbufr_v10.2.5.a',
                              'lib/libcrtm_v2.2.3.a', 'lib/libenkfdeplib.a',
                              'lib/libenkflib.a', 'lib/libgsilib_shrd.a',
                              'lib/libgsilib_wrf.a', 'lib/libnemsio_v2.2.1.a',
                              'lib/libsfcio_v1.1.0.a', 'lib/libsigio_v2.0.1.a',
                              'lib/libsp_v2.0.2.a', 'lib/libw3emc_v2.2.0.a',
                              'lib/libw3nco_v2.0.6.a')
    if not check_files(expected_exe_files):
        cmake_args = f'-DBUILD_ENKF=ON -DBUILD_CORELIBS=ON -DUSE_WRF=ON -DBUILD_WRF=ON -DBUILD_GFS=OFF '
        if version == Version('3.6'):
            cli.notice('Fix GSI 3.6!')
            edit_file('../cmake/Modules/FindCORELIBS.cmake', [[
                '\${CMAKE_SOURCE_DIR}/libsrc', '${CMAKE_SOURCE_DIR}/lib/libsrc'
            ]])
            if args.compiler_suite == 'gnu':
                edit_file('../cmake/Modules/setCompilerFlags.cmake', [[
                    'set\(BACIO_Fortran_FLAGS " -O3 -fconvert=big-endian -ffree-form',
                    'set(BACIO_Fortran_FLAGS " -O3 -fconvert=big-endian'
                ]])
            elif args.compiler_suite == 'intel':
                edit_file('../cmake/Modules/setCompilerFlags.cmake', [[
                    'set \(BACIO_Fortran_FLAGS "-O3 -free -assume nocc_omp',
                    'set(BACIO_Fortran_FLAGS " -O3 -assume nocc_omp'
                ]])
            edit_file('../core-libs/sigio/CMakeLists.txt',
                      [['\*\.f\)', '*.f90)']])
            edit_file('../src/hybrid_ensemble_isotropic.F90',
                      [['stop\(123\)', 'stop 123']])
            edit_file('../src/setupoz.f90', [[
                'my_head%ij\(1\),my_head%wij\(1\)\)', 'my_head%ij,my_head%wij)'
            ]])
            cmake_args += f'-DWRFPATH={args.wrf_root}'
        if version == Version('3.7'):
            cli.notice('Fix GSI 3.7!')
            edit_file('../src/setuplight.f90',
                      [['my_head%wij\(1\)\)', 'my_head%wij)']])
            cli.warning(
                'GSI 3.7 has bug when rerun cmake, so clean all build files.')
            run('rm -rf ../build/*')
            cmake_args += '-DBUILD_UTIL_COM=ON'

        # Fix not-found -lnetcdf -lnetcdff.
        edit_file('../cmake/Modules/setCompilerFlags.cmake',
                  [['-lnetcdf -lnetcdff', '']])

        cli.notice('Configure GSI ...')
        if args.compiler_suite == 'gnu':
            cc = 'gcc'
            cxx = 'g++'
            fc = 'gfortran'
        elif args.compiler_suite == 'intel':
            cc = 'mpiicc'
            cxx = 'mpiicpc'
            fc = 'mpiifort'
        if args.verbose:
            run(f'CC={cc} CXX={cxx} FC={fc} cmake .. {cmake_args}')
        else:
            run(f'CC={cc} CXX={cxx} FC={fc} cmake .. {cmake_args} &> cmake.out'
                )

        cli.notice('Compile GSI ...')
        if args.verbose:
            run('make')
        else:
            run('make &> make.out')

        if check_files(expected_exe_files):
            cli.notice('Succeeded.')
        else:
            if args.verbose:
                cli.error('Failed')
            else:
                cli.error(f'Failed! Check {args.gsi_root}/build/make.out')
    else:
        cli.notice('GSI has already been built.')

    if version == Version('3.6'):
        os.chdir(f'{args.gsi_root}/util/bufr_tools')
        if args.force: run('make clean')
        expected_exe_files = (
            'bufr_append_sample.exe', 'bufr_decode_radiance.exe',
            'bufr_decode_sample.exe', 'bufr_encode_sample.exe',
            'prepbufr_append_retrieve.exe', 'prepbufr_append_surface.exe',
            'prepbufr_append_upperair.exe', 'prepbufr_decode_all.exe',
            'prepbufr_encode_surface.exe', 'prepbufr_encode_upperair.exe',
            'prepbufr_inventory.exe')
        if not check_files(expected_exe_files):
            edit_file('makefile', [['^\s*FC\s*=.*$', f'FC = {fc}'],
                                   ['-I\.\./\.\./dtc', '-I../../build'],
                                   ['-L\.\./\.\./dtc', '-L../../build'],
                                   ['-lbufr_i4r8', '-lbufr_v10.2.5']])

            cli.notice('Compile bufr_tools ...')
            if args.verbose:
                run('make')
            else:
                run('make &> make.out')

            if check_files(expected_exe_files):
                cli.notice('Succeeded.')
            else:
                if args.verbose:
                    cli.error('Failed!')
                else:
                    cli.error(
                        f'Failed! Check {args.gsi_root}/util/bufr_tools/make.out'
                    )
        else:
            cli.notice('GSI bufr_tools has been built.')

        os.chdir(f'{args.gsi_root}/util/Analysis_Utilities/read_diag/')
        expected_exe_files = ('read_diag_conv.exe', 'read_diag_conv_ens.exe',
                              'read_diag_rad.exe')
        if not check_files(expected_exe_files):
            edit_file('makefile', [[
                'include \.\./\.\./\.\./dtc/configure.gsi', ''
            ], ['\$\(SFC\)', fc], ['-I\.\./\.\./\.\./dtc', '-I../../../build'],
                                   [
                                       '-L\.\./\.\./\.\./src -lgsi',
                                       '-L../../../build/lib -lgsilib_shrd'
                                   ],
                                   [
                                       'FLAGS= \$\(FFLAGS_DEFAULT\)',
                                       'FLAGS = -fconvert=big-endian'
                                   ]])

            cli.notice('Compile read_diag ...')
            if args.verbose:
                run('make')
            else:
                run('make &> make.out')

            if check_files(expected_exe_files):
                cli.notice('Succeeded.')
            else:
                if args.verbose:
                    cli.error('Failed')
                else:
                    cli.error(
                        f'Failed! Check {args.gsi_root}/util/Analysis_Utilities/read_diag/make.out'
                    )
        else:
            cli.notice('GSI read_diag has been built.')
Пример #7
0
def config_wrf(work_root, wrf_root, wrfda_root, config, args, tag=None):
    phys_config = config['physics'] if 'physics' in config else {}

    start_time = config['custom']['start_time']
    end_time = config['custom']['end_time']
    max_dom = config['domains']['max_dom']

    start_time_str = start_time.format('YYYY-MM-DD_HH:mm:ss')
    end_time_str = end_time.format('YYYY-MM-DD_HH:mm:ss')

    if tag != None:
        wrf_work_dir = f'{work_root}/wrf_{tag}'
    else:
        wrf_work_dir = f'{work_root}/wrf'
    if not os.path.isdir(wrf_work_dir): os.mkdir(wrf_work_dir)
    os.chdir(wrf_work_dir)

    version = wrf_version(wrf_root)

    if os.path.isfile(f'{wrf_work_dir}/wrfinput_d01_{start_time_str}'):
        num_land_cat = get_num_land_cat(
            f'{wrf_work_dir}/wrfinput_d01_{start_time_str}')
    elif os.path.isfile(f'{wrf_work_dir}/wrfinput_d01'):
        num_land_cat = get_num_land_cat(f'{wrf_work_dir}/wrfinput_d01')
    elif os.path.isfile(f'{wrf_work_dir}/wrfout_d01_{start_time_str}'):
        num_land_cat = get_num_land_cat(
            f'{wrf_work_dir}/wrfout_d01_{start_time_str}')
    else:
        cli.warning(
            f'Cannot get num_land_cat parameter from an existing wrfinput_d01 file in {wrf_work_dir}!'
        )
        num_land_cat = None

    cli.notice('Edit namelist.input for WRF.')
    copy(f'{wrf_root}/run/namelist.input', 'namelist.input')
    namelist_input = f90nml.read('namelist.input')
    namelist_input['time_control']['run_hours'] = config['custom'][
        'forecast_hours']
    namelist_input['time_control']['start_year'] = [
        int(start_time.format("Y")) for i in range(max_dom)
    ]
    namelist_input['time_control']['start_month'] = [
        int(start_time.format("M")) for i in range(max_dom)
    ]
    namelist_input['time_control']['start_day'] = [
        int(start_time.format("D")) for i in range(max_dom)
    ]
    namelist_input['time_control']['start_hour'] = [
        int(start_time.format("H")) for i in range(max_dom)
    ]
    namelist_input['time_control']['end_year'] = [
        int(end_time.format("Y")) for i in range(max_dom)
    ]
    namelist_input['time_control']['end_month'] = [
        int(end_time.format("M")) for i in range(max_dom)
    ]
    namelist_input['time_control']['end_day'] = [
        int(end_time.format("D")) for i in range(max_dom)
    ]
    namelist_input['time_control']['end_hour'] = [
        int(end_time.format("H")) for i in range(max_dom)
    ]
    namelist_input['time_control']['frames_per_outfile'] = [
        1 for i in range(max_dom)
    ]
    if 'background' in config['custom'] and 'interval_seconds' in config[
            'custom']['background']:
        namelist_input['time_control']['interval_seconds'] = config['custom'][
            'background']['interval_seconds']
    if 'time_control' in config:
        for key, value in config['time_control'].items():
            namelist_input['time_control'][key] = value
    for key, value in config['domains'].items():
        namelist_input['domains'][key] = value
    if 'physics_suite' in namelist_input['physics']:
        del namelist_input['physics']['physics_suite']
    for key, value in phys_config.items():
        namelist_input['physics'][key] = value
    if num_land_cat != None:
        namelist_input['physics']['num_land_cat'] = num_land_cat
    if 'dynamics' in config:
        for key, value in config['dynamics'].items():
            namelist_input['dynamics'][key] = value
    if version == Version('3.9.1'):
        namelist_input['dynamics']['gwd_opt'] = 0
    namelist_input.write('./namelist.input', force=True)

    cli.notice('Succeeded.')
Пример #8
0
def build_upp(wrf_root, upp_root, args):
    if wrf_root != None: os.environ['WRF_DIR'] = wrf_root

    if not 'HDF5' in os.environ:
        res = subprocess.run(['which', 'h5dump'], stdout=subprocess.PIPE)
        if res.returncode == 0:
            os.environ['HDF5'] = os.path.dirname(
                os.path.dirname(res.stdout.decode('utf-8')))
            cli.notice(f'Set HDF5 to {os.environ["HDF5"]}')
    if not 'HDF5' in os.environ:
        cli.warning('HDF5 environment variable is not set')

    if not 'NETCDF' in os.environ:
        res = subprocess.run(['which', 'ncdump'], stdout=subprocess.PIPE)
        if res.returncode == 0:
            os.environ['NETCDF'] = os.path.dirname(
                os.path.dirname(res.stdout.decode('utf-8')))
            cli.notice(f'Set NETCDF to {os.environ["NETCDF"]}')
    if not 'NETCDF' in os.environ:
        cli.warning('NETCDF environment variable is not set!')

    if not 'JASPERINC' in os.environ or not 'JASPERLIB' in os.environ:
        if 'JASPER_ROOT' in os.environ:
            os.environ['JASPERINC'] = os.environ['JASPER_ROOT'] + '/include'
            os.environ['JASPERLIB'] = os.environ['JASPER_ROOT'] + '/lib'
            cli.notice(f'Set JASPERINC to {os.environ["JASPERINC"]}.')
            cli.notice(f'Set JASPERLIB to {os.environ["JASPERLIB"]}.')
        else:
            cli.error(
                'JASPERINC and JASPERLIB environment variables are not set!')

    version = upp_version(args.upp_root)

    if version < Version('4.1'):
        expected_exe_files = ('bin/copygb.exe', 'bin/ndate.exe',
                              'bin/unipost.exe')
    else:
        expected_exe_files = ('exec/unipost.exe')
        if not check_files(expected_exe_files):
            if not args.nceplibs_root:
                args.nceplibs_root = f'{os.path.dirname(args.upp_root)}/NCEPLIBS'
            if not os.path.isdir(args.nceplibs_root):
                cli.error('NCEPLIBS is not ready!')
        os.environ['NCEPLIBS_DIR'] = args.nceplibs_root

    if not check_files(expected_exe_files):
        os.chdir(upp_root)
        if args.force: run('./clean -a &> /dev/null')
        cli.notice('Configure UPP ...')
        child = pexpect.spawn('./configure')
        child.expect('Enter selection.*')
        if args.compiler_suite == 'intel':
            child.sendline('4')  # Linux x86_64, Intel compiler (dmpar)
        elif args.compiler_suite == 'gnu':
            child.sendline('8')  # Linux x86_64, gfortran compiler (dmpar)
        elif args.compiler_suite == 'pgi':
            child.sendline(
                '14')  # Linux x86_64, PGI compiler: -f90=pgf90  (dmpar)
        child.wait()

        if args.compiler_suite == 'intel':
            edit_file('./configure.upp',
                      [['mpif90', 'mpiifort'], ['mpicc', 'mpiicc']])

        if 'LIBPNG_ROOT' in os.environ:
            edit_file('./configure.upp', [
                ['-lpng', f'-L{os.environ["LIBPNG_ROOT"]}/lib -lpng'],
                [
                    'GRIB2SUPT_INC\s*=\s*(.*)',
                    f'GRIB2SUPT_INC = \\1 -I{os.environ["LIBPNG_ROOT"]}/include'
                ]
            ])

        cli.notice('Compile UPP ...')
        run('./compile &> compile.out')

        if check_files(expected_exe_files):
            cli.notice('Succeeded.')
        else:
            cli.error(f'Failed! Check {upp_root}/compile.out')
    else:
        cli.notice('UPP is already built.')
Пример #9
0
def build_wrf(wrf_root, wps_root, wrfplus_root, wrfda_root, args):
	if not 'HDF5' in os.environ:
		res = subprocess.run(['which', 'h5dump'], stdout=subprocess.PIPE)
		if res.returncode == 0:
			os.environ['HDF5'] = os.path.dirname(os.path.dirname(res.stdout.decode('utf-8')))
			cli.notice(f'Set HDF5 to {os.environ["HDF5"]}')
	if not 'HDF5' in os.environ:
		cli.warning('HDF5 environment variable is not set')

	if not 'NETCDF' in os.environ:
		res = subprocess.run(['which', 'nf-config'], stdout=subprocess.PIPE)
		if res.returncode == 0:
			os.environ['NETCDF'] = os.path.dirname(os.path.dirname(res.stdout.decode('utf-8')))
			res = subprocess.run(['nf-config', '--includedir'], stdout=subprocess.PIPE)
			os.environ['NETCDF_INC'] = res.stdout.decode('utf-8').strip()
			res = subprocess.run(['nf-config', '--flibs'], stdout=subprocess.PIPE)
			os.environ['NETCDF_LIB'] = re.search(r'-L([^ ]*)', res.stdout.decode('utf-8'))[1]
			cli.notice(f'Set NETCDF_INC to {os.environ["NETCDF_INC"]}')
			cli.notice(f'Set NETCDF_LIB to {os.environ["NETCDF_LIB"]}')
	if not 'NETCDF' in os.environ:
		cli.warning('NETCDF environment variable is not set!')

	if not 'JASPERINC' in os.environ or not 'JASPERLIB' in os.environ:
		if 'JASPER_ROOT' in os.environ:
			os.environ['JASPERINC'] = os.environ['JASPER_ROOT'] + '/include'
			os.environ['JASPERLIB'] = os.environ['JASPER_ROOT'] + '/lib'
			cli.notice(f'Set JASPERINC to {os.environ["JASPERINC"]}.')
			cli.notice(f'Set JASPERLIB to {os.environ["JASPERLIB"]}.')
		else:
			cli.error('JASPERINC and JASPERLIB environment variables are not set!')

	if not 'LIBPNG_ROOT' in os.environ:
		cli.warning('LIBPNG_ROOT environment variable is not set. Library PNG may not be found!')

	if not 'WRFIO_NCD_LARGE_FILE_SUPPORT' in os.environ:
		os.environ['WRFIO_NCD_LARGE_FILE_SUPPORT'] = '1'
		cli.notice('Set WRFIO_NCD_LARGE_FILE_SUPPORT to 1.')

	if args.rttov:
		os.environ['RTTOV'] = args.rttov
		cli.notice(f'Use RTTOV in {args.rttov}.')

	# ---------------------------------------------------------------------------------
	#                                    WRF
	os.chdir(wrf_root)
	version = wrf_version(wrf_root)
	if version <= Version('3.6.1'):
		os.environ['BUFR'] = '1'
	# Fix possible code bugs.
	if Version('3.6.1') <= version <= Version('3.8.1'):
		edit_file('phys/module_cu_g3.F', [['integer,  dimension \(12\) :: seed', 'integer,  dimension (33) :: seed']])
	if args.force: run('./clean -a 1> /dev/null 2>&1')
	expected_exe_files = ('main/wrf.exe', 'main/real.exe', 'main/ndown.exe', 'main/tc.exe')
	if not check_files(expected_exe_files):
		cli.notice('Configure WRF ...')
		if args.use_grib:
			cli.notice('Set GRIB2 flag.')
			edit_file('./arch/Config.pl', [
				['\$I_really_want_to_output_grib2_from_WRF = "FALSE"', '$I_really_want_to_output_grib2_from_WRF = "TRUE"']
			])
		if args.use_hyb:
			child = pexpect.spawn('./configure -hyb', encoding='utf-8')
		else:
			child = pexpect.spawn('./configure', encoding='utf-8')
		child.expect('Enter selection.*')
		if platform.system() == 'Darwin':
			if args.compiler_suite == 'gnu':
				child.sendline('15')
		else:
			if args.compiler_suite == 'intel':
				if args.openmp:
					child.sendline('16') # INTEL (ifort/icc) dm+sm
				else:
					child.sendline('15') # INTEL (ifort/icc) dmpar
			elif args.compiler_suite == 'gnu':
				if args.openmp:
					child.sendline('35') # GNU (gfortran/gcc) dm+sm
				else:
					child.sendline('34') # GNU (gfortran/gcc) dmpar
			elif args.compiler_suite == 'pgi':
				if args.openmp:
					child.sendline('55') # PGI (pgf90/pgcc) dm+sm
				else:
					child.sendline('54') # PGI (pgf90/pgcc) dmpar
		child.expect('Compile for nesting.*:')
		child.sendline('1')
		if platform.system() == 'Darwin': child.expect('This build of WRF will use NETCDF4 with HDF5 compression')
		child.wait()

		if args.compiler_suite == 'intel':
			edit_file('./configure.wrf', [
				['mpif90', 'mpiifort'],
				['mpicc', 'mpiicc']
			])
		elif args.compiler_suite == 'pgi':
			edit_file('./configure.wrf', [
				['pgf90', 'pgfortran'],
				['mpif90', 'mpifort']
			])

		# Fix for OpenMPI.
		edit_file('./configure.wrf', [
			['DM_CC\s*=\s*mpicc\s*$', 'DM_CC = mpicc -DMPI2_SUPPORT\n']
		])

		cli.notice('Compile WRF ...')
		if args.debug:
			if args.compiler_suite == 'intel':
				debug_options = '-O0 -g -traceback'
			elif args.compiler_suite == 'gnu':
				debug_options = '-O0 -g -fbacktrace'
			edit_file('configure.wrf', [
				['FCFLAGS\s*=\s*\$\(FCOPTIM\)\s*\$\(FCBASEOPTS\)', f'FCFLAGS = {debug_options} $(FCBASEOPTS)']
			])
		if args.verbose:
			run(f'./compile em_real')
		else:
			run(f'./compile em_real 1> compile.out 2>&1')
		
		if check_files(expected_exe_files):
			cli.notice('Succeeded.')
		else:
			if args.verbose:
				cli.error('Failed!')
			else:
				cli.error(f'Failed! Check {wrf_root}/compile.out')
	else:
		cli.notice('WRF is already built.')

	# ---------------------------------------------------------------------------------
	#                                    WPS
	os.chdir(wps_root)
	if args.force: run('./clean -a 1> /dev/null 2>&1')
	expected_exe_files = ('geogrid/src/geogrid.exe', 'metgrid/src/metgrid.exe', 'ungrib/src/ungrib.exe')
	if not check_files(expected_exe_files):
		cli.notice('Configure WPS ...')
		child = pexpect.spawn('./configure')
		child.expect('Enter selection.*')
		if args.compiler_suite == 'intel':
			child.sendline('19') # Linux x86_64, Intel compiler    (dmpar)
		elif args.compiler_suite == 'gnu':
			child.sendline('3')  # Linux x86_64, gfortran    (dmpar)
		elif args.compiler_suite == 'pgi':
			child.sendline('7')
		child.wait()

		if args.compiler_suite == 'intel':
			edit_file('./configure.wps', [
				['mpif90', 'mpiifort'],
				['mpicc', 'mpiicc']
			])
		elif args.compiler_suite == 'pgi':
			edit_file('./configure.wps', [
				['pgf90', 'pgfortran'],
				['mpif90', 'mpifort']
			])
		else:
			run('sed -i "s/mpicc -cc=.*/mpicc/" configure.wps')
			run('sed -i "s/mpif90 -f90=.*/mpif90/" configure.wps')

		run('sed -i "s/WRF_DIR\s*=.*/WRF_DIR = ..\/WRF/" configure.wps')
		if 'LIBPNG_ROOT' in os.environ:
			run(f'sed -i "s@COMPRESSION_LIBS\s*=\(.*\)@COMPRESSION_LIBS = \\1 -L{os.environ["LIBPNG_ROOT"]}/lib@" configure.wps')
			run(f'sed -i "s@COMPRESSION_INC\s*=\(.*\)@COMPRESSION_INC = \\1 -I{os.environ["LIBPNG_ROOT"]}/include@" configure.wps')

		if args.compiler_suite == 'gnu':
			# Fix for gfortran 9.1.0.
			edit_file('ungrib/src/ngl/g2/intmath.f', [['iand\(i,i-1\)/=0', 'iand(i,i-1_8)/=0']], return_on_first_match=True)
			edit_file('ungrib/src/ngl/g2/intmath.f', [['iand\(i,i-1\)/=0', 'iand(i,i-1_4)/=0']], return_on_first_match=True)
			edit_file('ungrib/src/ngl/g2/intmath.f', [['iand\(i,i-1\)/=0', 'iand(i,i-1_2)/=0']], return_on_first_match=True)
			edit_file('ungrib/src/ngl/g2/intmath.f', [['iand\(i,i-1\)/=0', 'iand(i,i-1_1)/=0']], return_on_first_match=True)

		# Fix for OpenMPI.
		edit_file('./configure.wps', [
			['DM_CC\s*=\s*mpicc\s*$', 'DM_CC = mpicc -DMPI2_SUPPORT\n']
		])

		cli.notice('Compile WPS ...')
		if args.verbose:
			run('./compile')
		else:
			run('./compile 1> compile.out 2>&1')

		if check_files(expected_exe_files):
			cli.notice('Succeeded.')
		else:
			if args.verbose:
				cli.error('Failed!')
			else:
				cli.error(f'Failed! Check {wps_root}/compile.out')
	else:
		cli.notice('WPS is already built.')

	# ---------------------------------------------------------------------------------
	#                                    WRFPLUS
	os.chdir(wrfplus_root)
	if args.force: run('./clean -a 1> /dev/null 2>&1')
	if Version('3.6.1') <= version <= Version('3.9.1'):
		edit_file('phys/module_cu_g3.F', [['integer,  dimension \(12\) :: seed', 'integer,  dimension (33) :: seed']])
		if version == Version('3.6.1'):
			line_number = 841
		elif version == Version('3.8.1'):
			line_number = 855
		elif version == Version('3.9.1'):
			line_number = 856
		else:
			error('Find out the wrong OpenMP directive in WRFPLUS/main/module_wrf_top.F!')
		edit_file('main/module_wrf_top.F', [[line_number, '   !$OMP DEFAULT (SHARED) PRIVATE ( ij )\n']])
	if version >= Version('4.0'):
		expected_exe_files = ('main/wrfplus.exe')
	else:
		expected_exe_files = ('main/wrf.exe')
	if not check_files(expected_exe_files):
		cli.notice('Configure WRFPLUS ...')
		if args.use_grib:
			cli.notice('Set GRIB2 flag.')
			edit_file('./arch/Config.pl', [
				['\$I_really_want_to_output_grib2_from_WRF = "FALSE"', '$I_really_want_to_output_grib2_from_WRF = "TRUE"']
			])
		child = pexpect.spawn('./configure wrfplus')
		child.expect('Enter selection.*')
		if args.compiler_suite == 'intel':
			if version <= Version('3.6.1'):
				child.sendline('8')
			else:
				child.sendline('34')
		elif args.compiler_suite == 'gnu':
			child.sendline('18')
		elif args.compiler_suite == 'pgi':
			child.sendline('28')
		child.wait()

		if args.compiler_suite == 'intel':
			edit_file('./configure.wrf', [
				['mpif90', 'mpiifort'],
				['mpicc', 'mpiicc'],
				['override-limits', 'qoverride-limits']
			])

		# Fix for OpenMPI.
		edit_file('./configure.wrf', [
			['DM_CC\s*=\s*mpicc\s*$', 'DM_CC = mpicc -DMPI2_SUPPORT\n']
		])

		cli.notice('Compile WRFPLUS ...')
		if args.debug:
			if args.compiler_suite == 'intel':
				debug_options = '-O0 -g -traceback'
			elif args.compiler_suite == 'gnu':
				debug_options = '-O0 -g -fbacktrace'
			edit_file('configure.wrf', [
				['FCFLAGS\s*=\s*\$\(FCOPTIM\)\s*\$\(FCBASEOPTS\)', f'FCFLAGS = {debug_options} $(FCBASEOPTS)']
			])
		if version >= Version('4.0'):
			build_target = 'wrfplus'
		else:
			build_target = 'wrf'
		if args.verbose:
			run(f'./compile {build_target}')
		else:
			run(f'./compile {build_target} 1> compile.out 2>&1')

		if check_files(expected_exe_files):
			cli.notice('Succeeded.')
		else:
			if args.verbose:
				cli.error('Failed!')
			else:
				cli.error(f'Failed! Check {wrfplus_root}/compile.out')
	else:
		cli.notice('WRFPLUS is already built.')

	# ---------------------------------------------------------------------------------
	#                                    WRFDA
	os.chdir(wrfda_root)
	os.environ['WRFPLUS_DIR'] = wrfplus_root
	if args.force: run('./clean -a 1> /dev/null 2>&1')
	if Version('3.6.1') <= version <= Version('3.9.1'):
		cli.warning(f'Fix {wrfda_root}/var/da/da_define_structures/da_zero_y.inc')
		edit_file('var/da/da_define_structures/da_zero_y.inc', [
			[', value \)', ', value_ )'],
			[':: value$', ':: value_\nreal value'],
			['if \(.not.\(present\(value\)\)\) value = 0.0', '''
   if (.not.(present(value_))) then
      value = 0.0
   else
      value = value_
   end if
''']
		])
	if version == Version('4.1.1'):
		cli.warning(f'Fix {wrfda_root}/share/input_wrf.F')
		edit_file('share/input_wrf.F', [
			['FUNCTION check_which_switch', 'FUNCTION check_which_switch1']
		])
	expected_exe_files = [
		'var/build/da_advance_time.exe',
		'var/build/da_bias_airmass.exe',
		'var/build/da_bias_scan.exe',
		'var/build/da_bias_sele.exe',
		'var/build/da_bias_verif.exe',
		'var/build/da_rad_diags.exe',
		'var/build/da_tune_obs_desroziers.exe',
		'var/build/da_tune_obs_hollingsworth1.exe',
		'var/build/da_tune_obs_hollingsworth2.exe',
		'var/build/da_update_bc_ad.exe',
		'var/build/da_update_bc.exe',
		'var/build/da_verif_grid.exe',
		'var/build/da_verif_obs.exe',
		'var/build/da_wrfvar.exe',
		'var/build/gen_be_addmean.exe',
		'var/build/gen_be_cov2d3d_contrib.exe',
		'var/build/gen_be_cov2d.exe',
		'var/build/gen_be_cov3d2d_contrib.exe',
		'var/build/gen_be_cov3d3d_bin3d_contrib.exe',
		'var/build/gen_be_cov3d3d_contrib.exe',
		'var/build/gen_be_cov3d.exe',
		'var/build/gen_be_diags.exe',
		'var/build/gen_be_diags_read.exe',
		'var/build/gen_be_ensmean.exe',
		'var/build/gen_be_ensrf.exe',
		'var/build/gen_be_ep1.exe',
		'var/build/gen_be_ep2.exe',
		'var/build/gen_be_etkf.exe',
		'var/build/gen_be_hist.exe',
		'var/build/gen_be_stage0_gsi.exe',
		'var/build/gen_be_stage0_wrf.exe',
		'var/build/gen_be_stage1_1dvar.exe',
		'var/build/gen_be_stage1.exe',
		'var/build/gen_be_stage1_gsi.exe',
		'var/build/gen_be_stage2_1dvar.exe',
		'var/build/gen_be_stage2a.exe',
		'var/build/gen_be_stage2.exe',
		'var/build/gen_be_stage2_gsi.exe',
		'var/build/gen_be_stage3.exe',
		'var/build/gen_be_stage4_global.exe',
		'var/build/gen_be_stage4_regional.exe',
		'var/build/gen_be_vertloc.exe',
		'var/build/gen_mbe_stage2.exe',
		'var/obsproc/src/obsproc.exe']
	if not check_files(expected_exe_files):
		cli.notice('Configure WRFDA ...')
		if args.use_grib:
			cli.notice('Set GRIB2 flag.')
			edit_file('./arch/Config.pl', [
				['\$I_really_want_to_output_grib2_from_WRF = "FALSE"', '$I_really_want_to_output_grib2_from_WRF = "TRUE"']
			])
		child = pexpect.spawn('./configure 4dvar')
		child.expect('Enter selection.*')
		if args.compiler_suite == 'intel':
			child.sendline('8')
		elif args.compiler_suite == 'gnu':
			child.sendline('18')
		elif args.compiler_suite == 'pgi':
			child.sendline('28')
		child.wait()

		if args.compiler_suite == 'intel':
			edit_file('./configure.wrf', [
				['mpif90', 'mpiifort'],
				['mpicc', 'mpiicc']
			])

		# Fix for OpenMPI.
		edit_file('./configure.wrf', [
			['DM_CC\s*=\s*mpicc\s*$', 'DM_CC = mpicc -DMPI2_SUPPORT\n']
		])

		cli.notice('Compile WRFDA ...')
		if args.debug:
			if args.compiler_suite == 'intel':
				debug_options = '-O0 -g -traceback'
			elif args.compiler_suite == 'gnu':
				debug_options = '-O0 -g -fbacktrace'
			edit_file('configure.wrf', [
				['FCFLAGS\s*=\s*\$\(FCOPTIM\)\s*\$\(FCBASEOPTS\)', f'FCFLAGS = {debug_options} $(FCBASEOPTS)']
			])
		if args.verbose:
			run(f'./compile all_wrfvar')
		else:
			run(f'./compile all_wrfvar 1> compile.out 2>&1')

		if check_files(expected_exe_files, fatal=True):
			cli.notice('Succeeded.')
		else:
			if args.verbose:
				cli.error('Failed!')
			else:
				cli.error(f'Failed! Check {wrfda_root}/compile.out')
	else:
		cli.notice('WRFDA is already built.')
Пример #10
0
                    args.wrfda_root,
                    config,
                    args,
                    fg=fg)
wrf.run_wrfda_update_bc(args.work_root + '/fa', args.wrfda_root, False, config,
                        args)
wrf.config_wrf(args.work_root + '/fa', args.wrf_root, args.wrfda_root, config,
               args)
wrf.run_wrf(args.work_root + '/fa', args.wrf_root, config, args)

# Interpolate reference at valid time.
cli.banner('                   Interpolate reference at valid time')
ref_config = copy.deepcopy(config)
ref_config['custom']['start_time'] = config['custom']['end_time']
if not args.ref_root:
    cli.warning('Use background as reference.')
    args.ref_root = args.bkg_root
else:
    ref_config['custom']['background'] = {
        'type':
        'gfs',
        'file_pattern':
        'gdas.t{{ bkg_start_time.format("HH") }}z.pgrb2.*.f{{ "%03d" % bkg_forecast_hour }}',
        'dir_pattern':
        'gdas.{{ bkg_start_time.format("YYYYMMDD") }}/{{ bkg_start_time.format("HH") }}'
    }
wrf.config_wps(args.work_root + '/ref', args.wps_root, args.geog_root,
               ref_config, args)
run(f'ln -sf {args.work_root}/wps/geo_em.d01.nc {args.work_root}/ref/wps')
wrf.run_wps_ungrib_metgrid(args.work_root + '/ref', args.wps_root,
                           args.ref_root, ref_config, args)
Пример #11
0
def run_real(work_root, wps_work_dir, wrf_root, config, args, tag=None):
    start_time = config['custom']['start_time']
    datetime_fmt = 'YYYY-MM-DD_HH:mm:ss'
    start_time_str = start_time.format(datetime_fmt)
    max_dom = config['domains']['max_dom']

    if not os.path.isdir(wps_work_dir):
        cli.error(f'WPS work directory {wps_work_dir} does not exist!')
    if tag != None:
        wrf_work_dir = f'{work_root}/wrf_{tag}'
    else:
        wrf_work_dir = f'{work_root}/wrf'
    if not os.path.isdir(wrf_work_dir): os.mkdir(wrf_work_dir)
    os.chdir(wrf_work_dir)

    cli.stage(f'Run real.exe at {wrf_work_dir} ...')
    expected_files = [
        'wrfinput_d{:02d}_{}'.format(i + 1, start_time_str)
        for i in range(max_dom)
    ]
    expected_files.append('wrfbdy_d01')
    if not check_files(expected_files) or args.force:
        run('rm -f wrfinput_* met_em.*.nc')
        run(f'ln -sf {wps_work_dir}/met_em.*.nc .')
        try:
            dataset = Dataset(glob('met_em.*.nc')[0])
        except:
            cli.error('Failed to open one of met_em.*.nc file!')
        # Check met_em file.
        if not 'num_st_layers' in dataset.dimensions or dataset.dimensions[
                'num_st_layers'].size == 0:
            cli.error(
                'Failed to run ungrib and metgrid due to num_metgrid_soil_levels is zero!'
            )
        namelist_input = f90nml.read('./namelist.input')
        namelist_input['domains']['num_metgrid_levels'] = dataset.dimensions[
            'num_metgrid_levels'].size
        namelist_input['physics']['num_land_cat'] = dataset.getncattr(
            'NUM_LAND_CAT')
        if 'num_st_layers' in dataset.dimensions:
            namelist_input['domains'][
                'num_metgrid_soil_levels'] = dataset.dimensions[
                    'num_st_layers'].size
        else:
            cli.warning(
                f'Dimension num_st_layers is not in {dataset.filepath()}! Set num_metgrid_soil_levels to 0.'
            )
            namelist_input['domains']['num_metgrid_soil_levels'] = 0
        dataset.close()
        namelist_input.write('./namelist.input', force=True)
        submit_job(f'{wrf_root}/run/real.exe',
                   args.np,
                   config,
                   args,
                   wait=True)
        for i in range(max_dom):
            if not os.path.isfile('wrfinput_d{0:02d}'.format(i + 1)):
                # Check if the failure is caused by parallel computing?
                cli.warning(
                    'Failed to run real.exe in parallel. Try to run in serial.'
                )
                submit_job(f'{wrf_root}/run/real.exe',
                           1,
                           config,
                           args,
                           wait=True)
                if not os.path.isfile('wrfinput_d{0:02d}'.format(i + 1)):
                    cli.error(
                        f'Still failed to generate wrfinput_d{0:02d}! See {wrf_work_dir}/rsl.error.0000.'
                        .format(i + 1))
            run('ln -sf wrfinput_d{0:02d} wrfinput_d{0:02d}_{1}'.format(
                i + 1, start_time_str))
        if os.path.isfile('wrfbdy_d01'):
            run(f'ln -sf wrfbdy_d01 wrfbdy_d01_{start_time_str}')
        cli.notice('Succeeded.')
    else:
        run('ls -l wrfinput_* wrfbdy_*')
        cli.notice('File wrfinput_* already exist.')
Пример #12
0
def run_wrf(work_root, wrf_root, config, args, wrfda_work_dir=None, tag=None):
	start_time = config['custom']['start_time']
	end_time = config['custom']['end_time']
	datetime_fmt = 'YYYY-MM-DD_HH:mm:ss'
	start_time_str = start_time.format(datetime_fmt)
	end_time_str = end_time.format(datetime_fmt)
	max_dom = config['domains']['max_dom']

	if not wrfda_work_dir:
		if tag != None:
			wrfda_work_dir = f'{work_root}/wrfda_{tag}'
		else:
			wrfda_work_dir = f'{work_root}/wrfda'
	elif not os.path.isdir(wrfda_work_dir):
		cli.error(f'run_wrf: {wrfda_work_dir} does not exist!')

	if tag != None:
		wrf_work_dir = f'{work_root}/wrf_{tag}'
	else:
		wrf_work_dir = f'{work_root}/wrf'
	if not os.path.isdir(wrf_work_dir): cli.error(f'run_wrf: {wrf_work_dir} does not exist!')
	os.chdir(wrf_work_dir)

	all_wrfda_ok = True
	for dom_idx in range(max_dom):
		dom_str = 'd' + str(dom_idx + 1).zfill(2)
		if not copy_wrfda_output(dom_str, start_time_str, wrfda_work_dir):
			all_wrfda_ok = False
			break
	if not all_wrfda_ok:
		cli.warning('Do not use data assimilation.')
		expected_files = ['wrfinput_d{:02d}_{}'.format(i + 1, start_time_str) for i in range(max_dom)]
		expected_files.append(f'wrfbdy_d01_{start_time_str}')
		if not check_files(expected_files):
			cli.error('real.exe wasn\'t executed successfully!')
		for i in range(max_dom):
			run('ln -sf wrfinput_d{0:02d}_{1} wrfinput_d{0:02d}'.format(i + 1, start_time_str))
		run(f'ln -sf wrfbdy_d01_{start_time_str} wrfbdy_d01')

	cli.stage(f'Run wrf.exe at {wrf_work_dir} ...')
	expected_files = ['wrfout_d{:02d}_{}'.format(i + 1, end_time_str) for i in range(max_dom)]
	if not check_files(expected_files) or args.force:
		run('rm -f wrfout_*')
		run(f'ln -sf {wrf_root}/run/LANDUSE.TBL .')
		run(f'ln -sf {wrf_root}/run/ozone_plev.formatted .')
		run(f'ln -sf {wrf_root}/run/ozone_lat.formatted .')
		run(f'ln -sf {wrf_root}/run/ozone.formatted .')
		run(f'ln -sf {wrf_root}/run/RRTM_DATA_DBL RRTM_DATA')
		run(f'ln -sf {wrf_root}/run/RRTMG_LW_DATA .')
		run(f'ln -sf {wrf_root}/run/RRTMG_SW_DATA .')
		run(f'ln -sf {wrf_root}/run/VEGPARM.TBL .')
		run(f'ln -sf {wrf_root}/run/SOILPARM.TBL .')
		run(f'ln -sf {wrf_root}/run/GENPARM.TBL .')
		retries = 0
		while True:
			submit_job(f'{wrf_root}/run/wrf.exe', args.np, config, args, wait=True)
			if not check_files(expected_files):
				if retries == 0:
					cli.error(f'Failed! Check output {os.path.abspath(wrf_work_dir)}/rsl.error.0000.')
				retries = retries + 1
				cli.warning(f'Failed to run wrf, retry it! {retries}')
			else:
				break
		cli.notice('Succeeded.')
	else:
		cli.notice('File wrfout_* already exist.')
	run(f'ls -l {wrf_work_dir}/wrfout_*')