time_phylmdz_mod.F90
快速理解
它做什么: 保存物理时间步 dtphys/sol 长度 daysec/起止日/输出频率/restart 频率等全局标量。
基本过程: 3D 由 phys_state_var_init 写入 → conf_phys 补写输出调度 → 1D 由 init_testphys1d_mod 直接写入。
关键结果: 跨模块共享的物理时间与输出调度标量。
路径
LMDZ.MARS\libf\phymars\time_phylmdz_mod.F90
所属目录 / 模块
libf/phymars
文件定位
time_phylmdz_mod.F90 是 phymars 物理包的共享时间状态模块。它不推进模型时间,也不直接读写配置文件;它保存物理时间步、sol 长度、运行起止日、诊断输出频率和 restart 写出频率等全局标量,供初始化、配置、主物理调度、诊断输出、辐射和云物理等下游代码读取。
3D 路径中,phys_state_var_init_mod.F90 通过 init_time(day_ini,day_end,hour_ini,pdaysec,ptimestep) 写入基础日历状态;随后 conf_phys.F 读取配置并补写 outputs_per_sol、slow_diagfi、iphysiq 和 ecritstart。1D dyn1d/init_testphys1d_mod.F90 也直接写入部分变量,并在调用 phys_state_var_init 后把 iphysiq 约束为 1。
定义的符号
| 符号 | 类型 | 行号 | 作用 |
|---|---|---|---|
time_phylmdz_mod |
module | 1 | 保存物理时间和输出调度共享状态。 |
dtphys |
real saved module variable | 4 | 物理时间步,单位 s。 |
daysec |
real saved module variable | 7 | 一个 sol 的秒数。 |
steps_per_sol |
integer saved module variable | 10 | 每个 sol 的物理步数,由 nint(daysec/dtphys) 得到。 |
day_ini |
integer saved module variable | 13 | 运行初始 sol。 |
day_end |
integer saved module variable | 15 | 运行结束 sol。 |
hour_ini |
real saved module variable | 17 | 运行初始时刻,源码注释约束为 0 <= hour_ini < 1。 |
outputs_per_sol |
integer saved module variable | 21 | diagfi.nc 每 sol 输出次数,由 conf_phys 设置。 |
slow_diagfi |
logical saved module variable | 25 | 控制 1D diagfi.nc 是一次打开还是按输出频率打开/关闭,由 conf_phys 设置。 |
iphysiq |
integer saved module variable | 29 | 每 iphysiq 个动力步调用一次物理,由 conf_phys 设置。 |
ecritstart |
integer saved module variable | 32 | 每多少个动力步写一次 restart,由 conf_phys 设置。 |
init_time |
subroutine | 37 | 写入运行起止日、初始时刻、sol 长度和物理时间步,并派生 steps_per_sol。 |
依赖的模块
| use 模块 | only 列表 | 用途 | 待确认 |
|---|---|---|---|
| 无 | - | 本文件没有 use 语句。 |
- |
调用的关键例程
| 被调用例程 | 所在模块 / 文件 | 调用位置 | 作用 |
|---|---|---|---|
| 无 | - | - | init_time 只做标量赋值和 nint(daysec/dtphys)。 |
被调用位置
| 调用方 | 文件 | 调用位置 | 作用 |
|---|---|---|---|
phys_state_var_init |
phys_state_var_init_mod.F90 |
121 | 在物理共享数组分配流程中写入基础时间状态。 |
init_testphys1d |
dyn1d/init_testphys1d_mod.F90 |
430 | 1D 初始化路径通过 phys_state_var_init 间接调用本例程;同文件还直接设置 daysec、steps_per_sol、outputs_per_sol 和 iphysiq。 |
输入
| 输入 | 来源 | 类型 / 维度 | 单位 | 含义 |
|---|---|---|---|---|
day_ini_ |
phys_state_var_init 调用方 |
integer scalar | sol | 运行初始日。 |
day_end_ |
phys_state_var_init 调用方 |
integer scalar | sol | 运行结束日。 |
hour_ini_ |
phys_state_var_init 调用方 |
real scalar | sol fraction | 初始时刻。 |
daysec_ |
phys_state_var_init 调用方 |
real scalar | s | 一个 sol 的秒数。 |
dtphys_ |
phys_state_var_init 调用方 |
real scalar | s | 物理时间步。 |
输出
| 输出 | 去向 | 类型 / 维度 | 单位 | 含义 |
|---|---|---|---|---|
day_ini, day_end, hour_ini |
本模块共享状态 | integer/real scalar | sol / sol fraction | 供 physiq、诊断和 restart 路径读取的运行时间边界。 |
daysec, dtphys |
本模块共享状态 | real scalar | s | 供时间换算、辐射/云物理速率换算和诊断初始化读取。 |
steps_per_sol |
本模块共享状态 | integer scalar | steps/sol | 供 conf_phys 校验输出频率、physiq 每 sol 调度、诊断输出时间轴使用。 |
共享状态与副作用
本文件声明的所有模块变量都是 SAVE,并逐个标记为 OpenMP THREADPRIVATE。这意味着 OpenMP 物理区内每个线程都有自己的副本;复现初始化顺序时必须保证 init_time 和后续 conf_phys 的调用上下文与源码一致,否则某些线程可能读取未初始化或未同步的时间/输出调度状态。
init_time 只写入 day_ini/day_end/hour_ini/daysec/dtphys/steps_per_sol。outputs_per_sol、slow_diagfi、iphysiq 和 ecritstart 虽然定义在本模块中,但不在 init_time 内初始化;3D 常规路径由 conf_phys.F 在读取配置时设置,1D 路径还会在 dyn1d/init_testphys1d_mod.F90 中直接覆盖部分变量。
核心逻辑
- 接收上游传入的运行初始日、结束日、初始时刻、sol 长度和物理时间步。
- 把这些输入直接写入同名模块变量。
- 用
steps_per_sol = nint(daysec/dtphys)派生每 sol 物理步数。 - 不处理输出频率、物理调用频率和 restart 频率;这些变量留给
conf_phys或 1D 初始化路径设置。
伪代码
init_time(day_ini_, day_end_, hour_ini_, daysec_, dtphys_)
day_ini = day_ini_
day_end = day_end_
hour_ini = hour_ini_
daysec = daysec_
dtphys = dtphys_
steps_per_sol = nearest_integer(daysec / dtphys)
参与的主题流程
| 主题 | 参与方式 |
|---|---|
| 物理初始化 | phys_state_var_init_mod 调用 init_time,把动力/上游传入的日历和物理时间步写入物理共享状态。 |
| 物理调度与 restart | conf_phys 设置 iphysiq/ecritstart,physiq 用这些变量决定物理调用和 restart 写出时机。 |
| 诊断输出 | conf_phys 设置 outputs_per_sol/slow_diagfi,writediagfi、writediagmicrofi、writediagsoil 用 steps_per_sol/outputs_per_sol 计算采样间隔和输出时间轴。 |
| 时间单位换算 | daysec 和 dtphys 被 compute_dtau_mod、dust_rad_adjust_mod、lwi、nirco2abs、nlte_tcool_mod、wstats_mod 等模块用于 sol/秒、K/s/K/day 或本地时刻换算。 |
写法特点
- 文件只定义共享标量和一个初始化例程,没有本地数组、外部 I/O 或显式错误处理。
steps_per_sol使用nint(daysec/dtphys),源码没有检查daysec/dtphys是否严格为整数。- 所有共享变量都是
THREADPRIVATE,与 OpenMP 初始化上下文强相关。 outputs_per_sol、slow_diagfi、iphysiq、ecritstart的注释都说明由conf_phys设置;不要把init_time误认为完整时间配置入口。
复现要点
- 复现诊断输出频率时,需要同时核对
steps_per_sol和outputs_per_sol;conf_phys.F会检查steps_per_sol能否被outputs_per_sol整除。 steps_per_sol=nint(daysec/dtphys)会把接近整数的比值四舍五入;若实验使用非整除的daysec/dtphys,后续时间轴和采样间隔可能与实际秒数有偏差。daysec是多个物理速率换算的全局尺度,例如 CO2 雪发射率弛豫、近红外 CO2 加热、NLTE K/day 换算和 dust optical depth 时间记忆。- OpenMP 路径下必须保证
THREADPRIVATE副本在正确并行区内初始化;否则不同线程可能看到不一致的时间状态。 - 1D 路径会直接写
daysec/steps_per_sol/outputs_per_sol/iphysiq,不要只按 3Dphys_state_var_init顺序推断 1D 行为。
待确认
- 源码没有在本模块内验证
dtphys_ > 0或daysec_/dtphys_的整数性;是否完全由上游配置保证,需结合运行配置入口继续确认。 hour_ini的单位由注释描述为 sol fraction;旧诊断/控制表路径中如何与小时制显示对应,需要结合iniwrite、phyetat0_mod和动力时间模块继续核对。