数据的准备
如果要使用 WRF 的模拟结果驱动 PALM,需要将 WRF 的结果处理成 PALM 可以读取的 dynamic driver,而要生成 dynamic driver 的话,还需要使用静态地理数据先生成 static driver 才可以。
static driver 的生成
static driver 的生成需要使用 PALM 仓库内附带的工具 palm_csd (PALM 团队还有一个新的工具 palmgem 也可使用)。其中的手册写的不是特别完善,总结下来就是需要以下几类数据:
地形高度
建筑物高度 (以及用于区分不同建筑物的建筑物 id)
道路分布和类型
地表分布和类型
植被分布和类型
水体分布和类型
但这些数据不是必须要有的,不提供的话 PALM 会使用内部设定好的默认值。大陆想要拿到比较高精度的数据很难,可以使用 OpenStreetMap 提供的数据,但是需要自己做转换,生成 Shape 文件 (所有的几何分布都要放到一个 Shape 文件中,并且以额外的数据标记出类型) 或 TIFF 文件。并且某些数据类型还需要自己做一下映射,因为 PALM 内部支持的类型没有 OpenStreetMap 支持的那么丰富。
palm_csd 的运行需要提供一个 YAML 配置文件,具体的 key 以及其含义可以看 palm_csd 的文档,下面是我用于生成 static driver 的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 input_root: columns: pvmt_type: pavement_type st_type: street_type vgta_type: vegetation_type wtr_type: water_type files: building_id: data/outputs/static_driver/buildings_id.tiff buildings_2d: data/outputs/static_driver/buildings_height.tiff zt: data/inputs/dem_32650_new.tiff surfaces: data/outputs/static_driver/shape_file/data.shp settings: epsg: 32650 downscaling_method: categorical: nearest continuous: cubic discontinuous: cubic discrete: cubic upscaling_method: categorical: nearest continuous: cubic discontinuous: cubic discrete: cubic season: summer domain_root: input: root pixel_size: 6 dz: 3 nx: 451 ny: 541 origin_x: 683414.4903300125 origin_y: 3554370.79593777 water_temperature: river: 283.15 attributes: author: Syize contact_person: Syize, [email protected] acronym: NJU comment: Created by Syize with palm_csd location: CN site: xxx institution: xxx output: path: ./data/outputs file_out: filename version: 1
需要注意的地方有:
TIFF 文件和 Shape 文件的投影系与 settings 中设置的 epsg 必须一致。
origin_x 和 origin_y 是模拟区域的起点 (左下角) 在相应投影系中的坐标 (当然你也可以设置 origin_lon 和 origin_lat)
水平分辨率由 pixel_size 决定,单位是米
此外,还应该详细的检查输出的 static driver:
vegetation_type,pavement_type 以及 water_type 中的无效值应被替换为 int8 类型的整型值,并且在属性 _FillValue 中记录该填充值
vegetation_type 或 pavement_type 不为无效值的格点必须具有有效的 soil_type。
在 vegetation_type,pavement_type 或 water_type 有值的格点上,surface_fraction 的总和必须为 1。
dynamic driver 的生成
有了 static driver 后,就可以进一步生成 dynamic driver 了。需要使用的工具是 palm-meteo 。
目前 palm-meteo 不支持单个包含多个时间的 wrfout 数据,需要手动切分文件,或者在 WRF 的 namelist 中设置 frames_per_outfile = 1 让 WRF 每个输出时刻单独一个文件。
palm-meteo 的运行也需要 YAML 配置文件,下面是我用于生成 dynamic driver 的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 case: nju tasks: - wrf paths: base: 'data' palm_input: static_driver: 'temp/nju_static_driver_root.h5' wrf: file_mask: '/home/syize/Documents/docker-share/ubuntu/WRFOutputs/2025-12-01_00_to_24/wrf/wrfout_d02_*' intermediate_files: delete_after_success: false domain: dz: 3 nz: 60 proj_palm: 'EPSG:32650' simulation: origin_time: 2025-12-01 00:00:00.00 +0 timestep: 20 m length: 1 d
有个需要注意的地方是,一定要将 proj_palm 设置成生成 static driver 时使用的数据的投影系,否则 palm-meteo 会报错无法执行。
运行
PALM 的手册目前写的还不是很完整,有一些地方是我摸索出来的,所以做法不一定是完全准确的。
想要:
让 PALM 使用 dynamic driver 中的初始场数据
让 PALM 使用 dynamic driver 中的边界条件
以下是一些必须要设置的参数
initializing_actions:设置为 read_from_file,以从文件中读取初始场
psolver:设置为 multigrid
nx 和 ny:模拟区域网格的格子数。这两个参数和 npex、npey 配合,psolver 设置为 multigrid 要求 nx+1 和 ny+1 能分别被 npex 和 npey 整除。
npex 和 npey:沿 x 和 y 方向分配给网格的 CPU 节点数。二者的乘积等于分配给 PALM 模式的总节点数。
nesting_offl_parameters:想要 PALM 使用 dynamic driver 中的边界条件,namelist 文件中必须存在该配置块,即使块内是空的。
需要注意的是,在 namelist 中设置 initializing_actions = 'read_from_file',要同时关闭所有关于边界条件的手动设置的参数,例如 ug_surface,pt_surface 之类的。
还有一个需要注意的地方是,PALM 的 namelist 中,urban_surface_parameters 的 switch_off_module 默认值是 .false.,但是如果 namelist 中不存在 urban_surface_parameters配置块,PALM 会认为找不到 urban_surface_parameters 的设置,然后不启用启用 urban surface model。所以必须要在 namelist 中添加 urban_surface_parameters 的设置 (即使是空的) 来启用 urban surface model。
下面是完整的 namelist 设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 &initialization_parameters nx = 223 ny = 199 nz = 60 dx = 6.0 dy = 6.0 dz = 3.0 origin_date_time = '2025-12-01 00:00:00 +00' longitude = 118.952778 latitude = 32.120556 initializing_actions = 'read_from_file' psolver = 'multigrid' fft_method = 'fftw' humidity = .true . reference_state = 'horizontal_average' topography = 'read_from_file' restart_data_format = 'mpi_shared_memory' / &runtime_parameters end_time = 86400.0 create_disturbances = .true . dt_disturb = 150.0 disturbance_energy_limit = 0.015 npex = 4 npey = 4 netcdf_data_format = 4 dt_run_control = 0.0 dt_data_output = 600.0 dt_data_output_av = 600.0 dt_do3d = 600.0 dt_do2d_xy = 1.0 dt_do2d_xz = 600.0 dt_do2d_yz = 600.0 dt_dopr = 600.0 dt_dots = 600.0 data_output = 'u' , 'u_av' , 'p' , 'e' , 'v' , 'v_av' , 'w' , 'w_av' , 'theta' , 'theta_av' , 'theta_xz' , 'q' , 'rh' , 'pra*' , 'ta' , 'ta_xz' , 'usm_surfz_up' , 'usm_surfcat_up' section_xy = 5 section_xz = 50 averaging_interval = 600.0 dt_averaging_input = 10.0 / &radiation_parameters dt_radiation = 60.0 radiation_scheme = 'clear-sky' / &bulk_cloud_parameters cloud_scheme = 'kessler' cloud_water_sedimentation = .true . / &land_surface_parameters soil_type = 3 soil_moisture = 0.18352804 , 0.18352804 , 0.18352804 , 0.183911 , 0.1869747 , 0.19142141 , 0.19797706 , 0.23697187 soil_temperature = 296.5668869 , 296.5668869 , 296.5668869 , 296.3213401 , 294.35696555 , 291.63102998 , 290.93325411 , 289.27697754 deep_soil_temperature = 285.82938 surface_type = 'read_from_file' conserve_water_content = .true . / &urban_surface_parameters switch_off_module = .false . / &stg_par dt_stg_adjust = 30.0 dt_stg_call = 1.0 / &nesting_offl_parameters /
Comments