parse_tracer_file.F90
路径
LMDZ.MARS\libf\phymars\parse_tracer_file.F90
所属目录/模块
libf/phymars
文件定位
parse_tracer_file.F90 是"新格式" tracer.def 配置文件的解析接口模块。它封装了外部库 readtracfiles_mod 的调用,向 LMDZ 物理层提供三个简洁的查询子程序:获取 tracer 数量、获取 tracer 名称列表、获取 tracer 父子关系。这些子程序仅在 tracer_mod 的 ini_tracer_mod 初始化阶段被调用一次。
旧格式 traceur.def 由对应的 parse_traceur_file_mod(不同文件)处理。当两个文件都不存在时,ini_tracer_mod 会调用 abort_physic 终止执行。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
parse_tracer_file_mod |
module |
1 |
包裹三个 tracer.def 解析子程序的模块 |
get_nq_from_tracer_file |
subroutine |
11 |
从 tracer.def 读取 tracer 总数 nq |
get_names_from_tracer_file |
subroutine |
47 |
从已解析的 tracers 数组提取所有 tracer 名称 |
get_children_from_tracer_file |
subroutine |
69 |
统计每个 tracer 的子 tracer 数量(parent 字段匹配) |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
strings_mod |
maxlen(别名 strings_mod_max_len) |
字符串最大长度常量,用于声明 type_trac 和 parent 数组 |
外部库,不在本源码树中 |
readtracfiles_mod |
trac_type(派生类型)、tracers(全局对象)、readTracersFiles(函数)、getKey(函数) |
解析 tracer.def 文件并填充 tracers 数组;getKey 提取 tracer 属性 |
外部库,不在本源码树中 |
mod_phys_lmdz_para |
is_master, bcast |
MPI 并行:仅主进程解析文件,再广播结果 |
|
mod_grid_phy_lmdz |
grid_type, regular_lonlat |
判断网格类型以选择 tracer.def 的解析段(lmdz vs dynamico) |
仅 get_nq_from_tracer_file 使用 |
调用的关键例程
| 被调用例程 |
所在模块/文件 |
调用位置 |
作用 |
readTracersFiles |
readtracfiles_mod(外部库) |
行 34 |
解析 tracer.def 文件,填充全局 tracers 数组 |
getKey |
readtracfiles_mod(外部库) |
行 90 |
从已解析的 tracer 属性中提取指定 key(如 parent)的值 |
bcast |
mod_phys_lmdz_para |
行 42, 63–64, 112–113 |
广播整数/字符串到所有 MPI 进程 |
输入
get_nq_from_tracer_file
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
| (无显式输入) |
内部:grid_type module 变量 |
— |
— |
决定解析段为 "lmdz" 或 "dynamico" |
get_names_from_tracer_file
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
nq |
调用方(来自 get_nq_from_tracer_file) |
integer |
— |
tracer 数量 |
get_children_from_tracer_file
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
nq |
调用方 |
integer |
— |
tracer 数量 |
noms |
调用方(来自 get_names_from_tracer_file) |
character(len=*)(nq) |
— |
tracer 名称数组 |
输出
get_nq_from_tracer_file
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
nq |
调用方 |
integer |
— |
tracer 总数(= size(tracers)) |
get_names_from_tracer_file
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
noms |
调用方 |
character(len=*)(nq) |
— |
所有 tracer 名称(从 tracers(:)%name 复制) |
get_children_from_tracer_file
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
nqparents |
调用方 |
integer |
— |
parent 为 "air" 的 tracer 数量(即顶层 tracer 数) |
nqchildren |
调用方 |
integer(nq) |
— |
每个 tracer 拥有的子 tracer 数量 |
共享状态与副作用
- 读取外部全局对象
tracers(readtracfiles_mod 中的 module 变量):readTracersFiles 填充该对象后,三个子程序从中提取数据。
readTracersFiles 非线程安全:代码注释明确说明(行 15–16),因此仅由 is_master 调用,再通过 bcast 广播结果。
getKey 同样非线程安全:注释说明(行 72–73),同样仅主进程调用。
- 不修改任何 module 变量:所有输出通过子程序参数返回。
核心逻辑
get_nq_from_tracer_file(行 11–44)
- 仅
is_master 执行:
- 根据
grid_type 选择解析段:regular_lonlat → "lmdz",否则 → "dynamico"。
- 调用
readTracersFiles(type_trac) 解析 tracer.def。
nq = size(tracers)。
bcast(nq) 广播到所有进程。
get_names_from_tracer_file(行 47–66)
- 仅
is_master:noms(:) = tracers(:)%name。
- 逐个
bcast(noms(i)) 广播所有名称。
get_children_from_tracer_file(行 69–115)
- 仅
is_master:
- 调用
getKey('parent', parent) 提取所有 tracer 的 parent 属性(getKey 负责分配 parent 数组)。
- 统计
nqparents:遍历所有 tracer,parent 为 "air" 的计数。
- 统计
nqchildren(i):对每个 tracer i,遍历所有 tracer j,若 noms(i) == parent(j) 则 i 的子计数 +1。
bcast(nqparents) 和 bcast(nqchildren) 广播。
伪代码
! get_nq_from_tracer_file
if master:
if regular_lonlat: type_trac = "lmdz"
else: type_trac = "dynamico"
readTracersFiles(type_trac) ! 解析 tracer.def → 填充 tracers
nq = size(tracers)
bcast(nq)
! get_names_from_tracer_file
if master:
noms = tracers.name
for i in 1..nq: bcast(noms[i])
! get_children_from_tracer_file
if master:
getKey('parent', parent) ! 提取 parent 属性数组
nqparents = count(parent == "air")
for each tracer i:
nqchildren[i] = count(noms[i] == parent[j] for all j)
bcast(nqparents)
bcast(nqchildren)
参与的主题流程
| 主题 |
参与方式 |
| tracer 配置体系 |
为 tracer_mod 提供 tracer 数量、名称和父子关系,是 tracer 初始化的第一步 |
| 水循环配置 |
间接:tracer 名称决定水相关 tracer(h2o_vap, h2o_ice 等)的索引 |
| CO2 循环配置 |
间接:tracer 名称决定 CO2 相关 tracer(co2, co2_ice 等)的索引 |
写法特点
- 外部库依赖:
readtracfiles_mod 和 strings_mod 不在本源码树中,属于 LMDZ 共享基础设施。
- 非线程安全:
readTracersFiles 和 getKey 明确标注非线程安全,代码强制仅 is_master 调用。
- 旧/新格式双轨:
tracer_mod 先查 traceur.def(旧格式),不存在时再查 tracer.def(新格式),两者由不同模块处理。
- 奇怪的返回值约定:
readTracersFiles 和 getKey 返回 .false. 表示成功(行 36, 92 注释),代码中 result 变量被赋值但未检查。
getKey 自动分配:注释说明 getKey 负责 parent 数组的内存分配(行 91),调用方使用 allocatable 声明。
复现要点
- 必须有
tracer.def 或 traceur.def 文件存在于运行目录,否则 ini_tracer_mod 调用 abort_physic 终止。
tracer.def 中必须包含名为 "co2" 的 tracer,否则 ini_tracer_mod 同样终止(行 220)。
grid_type 决定解析段:regular_lonlat 网格用 "lmdz" 段,其他(如 dynamico)用 "dynamico" 段。
待确认
readtracfiles_mod 和 strings_mod 的具体实现不在本源码树中,推断来自 LMDZ 共享库(待确认:需查编译系统 Makefile 或 fcm 配置)。
getKey 返回值 .false. 表示成功的约定是否为历史遗留(待确认:可能与早期 Fortran 库的错误码约定有关)。
result 变量在 get_nq_from_tracer_file(行 25)和 get_children_from_tracer_file(行 84)中被赋值但从未检查(推断:错误处理依赖 readtracfiles_mod 内部的 write(*,*) 打印)。
相关页面