ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CALPUFF大气扩散模型全流程实操:从气象数据准备到风场调试

CALPUFF大气扩散模型全流程实操:从气象数据准备到风场调试 开头做环境咨询或环评的同行应该都有这种体会AERMOD对局地小范围的稳态模拟已经很成熟了可一旦项目涉及复杂地形、长距离输送、静风条件或者海陆风这种非稳态气象常规模型就很难给出让人信服的结果。这时候CALPUFF就派上用场了。作为EPA推荐的第三代高斯烟团扩散模型CALPUFF的优势在于它能把非稳态气象场、时空变化的排放源、化学转化和干湿沉降都装进一个框架里特别适合做区域级、长距离的污染物扩散模拟。不过我想说的是CALPUFF本身并不难跑难的是前面的数据准备。我在实际项目中见过太多人卡在气象数据预处理和地形数据处理这一关还没碰到主程序就跑不下去了。这篇文打算从气象数据预处理、地形与土地利用数据准备、污染源参数化、CALMET风场调试、CALPUFF主程序运行到CALPOST后处理完整梳理一遍我自己的实操流程和踩过的坑。无论你是环评从业人员、环境监测站的技术人员还是学校和科研单位的学生这篇文章的目标就是让你在拿到原始气象数据之后能按图索骥地把模拟跑通并且能让结果经得起推敲。1. 为什么还在用CALPUFF这个模型的核心定位与适用边界1.1 高斯烟团模型和稳态高斯模型的本质区别很多刚开始接触CALPUFF的人会问AERMOD在国内已经很普及了为什么还要折腾CALPUFF这个输入文件多、参数繁杂的老模型要回答这个得先理解稳态高斯模型和非稳态烟团模型的区别。AERMOD假设模拟时段内气象场是均匀定常的污染物浓度通过一条稳态高斯烟羽公式直接计算它适合几十公里范围内、地形相对简单的场景。CALPUFF则是把连续的污染物排放离散成一个个烟团烟团会在三维风场里随气流输送同时不断膨胀扩散。每个小时的风向风速都在变化烟团的轨迹也随之改变。这种设计天然适合处理风速很小、风向频繁转变、有海陆风环流或山谷风环流的场景也适合模拟几百公里尺度上的污染物跨区域输送。我在沿海工业区做过一次模拟白天海风把电厂烟气往内陆推夜间陆风又让污染物往回漂这种风向反转的过程AERMOD做不了CALPUFF却可以通过逐小时变化的三维风场把过程还原出来。国内环评导则里CALPUFF也一直作为复杂地形、长距离输送情景下的推荐模型出现。加上它在光化学转化、能见度影响、干湿沉降方面有现成的模块很多区域规划环评和重大项目的环境风险评价都会用到。所以与其问要不要学不如说做大气环境影响评价的工程师迟早会碰到它。1.2 用CALPUFF踩过的第一道门槛输入数据远比想象中复杂CALPUFF的模块结构决定了它对数据的要求比AERMOD高一个量级。AERMOD只需要一个地面气象站和一个探空站的逐时数据就能跑CALPUFF却要构建一个三维气象场需要多个地面站的观测数据、至少一个探空站的垂直廓线、高分辨率的地形高程、土地利用分类以及网格化的污染源清单。其中任何一类数据出现格式问题或时间缺失CALMET都会报错或者生成异常风场。我用一个实际项目的经验来说明某个焦化厂扩建项目模拟区域从厂区往外扩了40公里地形有丘陵和河谷。当时拿到的是一个市级气象站和一个区域自动站的观测数据探空数据只有每天早晚两次。我花了整整一周时间整理数据、调试CALMET参数才把风场调到一个能看的程度。相比AERMOD半天就能把数据跑通CALPUFF的前期准备确实是另外一套工作量。但反过来也正是因为有这些高要求的数据做支撑最终模拟出的浓度分布和监测结果对标的吻合度才更高。2. 模拟前的数据地图先盘清楚要准备哪些口粮2.1 一张数据清单把CALMET和CALPUFF需要的输入盘清楚开始处理数据之前不要急着打开软件先列一张数据需求表逐项核对。我每次接到新项目都会先做这件事省得跑了一半发现缺关键数据又回头去补。数据类型用途来源时间要求地面气象观测数据CALMET构建近地面风温场国家气象站、区域自动站、项目自建站逐小时至少覆盖模拟时段探空数据CALMET生成垂直廓线高空气象探测站或再分析数据每日1-2次最好覆盖多层中尺度气象模拟输出作为CALMET的初猜场或替代观测WRF、MM5输出3D.DAT格式逐小时三维风温湿场地形高程数据生成地形文件TERRELSRTM 90米、ASTER GDEM静态土地利用数据生成地表分类文件CTGPROCUSGS全球土地覆被、卫星解译数据静态污染源排放清单点源、面源、线源参数环评报告、排污许可、实测逐时或随时间变化监测数据后续模型验证环境监测站网与模拟同期这张表看起来不复杂真正做起来坑很多。比如很多小项目的探空数据一天只有两次CALMET需要的是能代表整个边界层演变过程的廓线两次数据夜间和白天的代表性差距极大过于粗糙的廓线会让混合层高度计算明显失真进而影响地面浓度的估算。2.2 工作目录结构让项目在三个月后还能被顺利接手气象数据预处理和模拟过程会产生大量中间文件如果不建立规范的目录结构做到后期你自己都会找不到某个文件是从哪一步生成的。我习惯的目录结构是这样project/ ├── 01_input/ │ ├── surface/ # 地面逐时气象观测 │ ├── upper/ # 探空数据 │ ├── wrf/ # WRF模拟输出 │ ├── terrain/ # 原始地形数据 │ ├── landuse/ # 土地利用原始数据 │ └── source/ # 源清单 ├── 02_preprocess/ │ ├── geodata/ # TERREL生成的.DAT、CTGPROC生成的土地利用 │ ├── metdata/ # 经过整理的CALMET输入气象 │ └── temp/ # 中间转换文件 ├── 03_met/ │ ├── calmet_in/ # CALMET输入文件 │ ├── calmet_out/ # CALMET气象场输出 │ └── calmet_log/ # 运行日志 ├── 04_dispersion/ │ ├── calpuff_in/ │ ├── calpuff_out/ │ └── calpuff_log/ ├── 05_postprocess/ │ ├── calpost_in/ │ └── results/ └── 06_report/ ├── figures/ └── tables/这样分层的目录看似繁琐但对排查问题特别有用。CALMET跑出一个异常风场时你可以快速回溯到到底是地形数据的问题还是原始气象数据的问题而不是在一堆乱糟糟的文件里翻找。2.3 坐标系与投影最容易出隐形问题的一关CALPUFF整个系统里地形数据、土地利用数据和气象格点都必须处于同一套坐标系下通常使用Lambert Conformal Conic投影或UTM投影。我在一个项目中吃过亏地形数据用的是地理坐标经纬度土地利用数据来自另一个来源已经是UTM投影两者没有统一就输入TERREL和CTGPROC结果生成的地形和土地利用网格错开几十公里CALMET跑出来的风场在山谷和平原之间完全错乱。排查了很久才发现是投影不一致造成的。所以任何数据在进入工作流之前第一件事就是检查投影信息和单位。地形高程数据一般用米土地利用分类代码要严格对应USGS的24类分类体系。不要相信任何看起来差不多的数据集用QGIS或者ArcGIS把每个栅格数据叠到模拟区域边界上检查一遍比什么都来得直接。3. 气象数据预处理把原始观测整理成CALMET承认的格式3.1 地面气象数据宁可多站点也勿强凑CALMET处理地面气象数据时程序默认读取的是地面站逐时数据文件一种纯文本格式扩展名通常是.DAT。每行记录对应一个小时的观测包括站点号、年、月、日、小时、风向、风速、温度、气压、相对湿度、云量、云底高等字段。不同版本的CALMET对字段顺序和单位有细微差别最稳妥的做法是用官方文档里的模板生成不要自己手搓格式。整理地面站数据时有两个常见坑。第一个是风向风速的单位和有效值范围风向必须是度0-360风速是米每秒静风用风速小于0.1或直接用特殊标记不要填0否则CALMET在计算时会因为对数风廓线公式里出现ln(0)而报错。第二个是站点数量的选择CALMET允许输入多个地面站程序会根据各站点距每个格点的距离进行权重插值。理论上站点越多、空间覆盖越好但如果站点数据质量参差不齐反而会引入错误信息。我一般会把参与模拟的站点数据先做一次完整性检查连续缺测超过10%的站点干脆弃用保留3-5个高质量站点就足够支撑几十公里的模拟范围。3.2 探空数据混合层高度准不准就看它探空数据处理是气象数据预处理中最容易被忽视、却对结果影响最大的一环。CALMET的微气象模块需要知道边界层内的温度垂直廓线和风速风向垂直分布用来计算混合层高度、摩擦速度、莫宁-奥布霍夫长度这些关键量。探空数据越粗糙这些参数就越不靠谱最终反映到地面浓度上就是数值偏差很大。处理探空数据时要注意把气压层的温度和位温计算正确同时每一层都应有对应的风速风向。我见过不少初学者把探空文件的层次理解成只有地面和500hPa两个高度结果CALMET计算出的混合层高度不是过高就是过低模拟出来的污染带抬升到半空中地面浓度几乎为零。建议至少使用包含地面层、925hPa、850hPa、700hPa、500hPa等层次的探空数据。如果没有实测探空可以用再分析资料或WRF输出代替但需要做一次偏差检验确保垂直廓线形态合理。3.3 WRF输出接入省力但必须做格式转换中尺度气象模式输出接入CALMET有个明显好处它能提供逐小时的三维风场、温度场和湿度场空间分辨率可以到几公里比稀疏的观测站插值出来的初猜场精细得多。CALMET本身也可以不依赖观测插值直接采用WRF输出的三维格点气象场作为初始风场再用观测资料进行微调。不过WRF输出不能直接喂给CALMET。通常需要通过WPS或者现成的转换工具把WRF的netCDF输出转换成CALMET可识别的3D.DAT格式。这里有一个容易出错的地方WRF输出的水平网格坐标系一般为兰伯特投影而CALMET内部默认使用UTM或用户自定义的兰伯特参数投影参数不一致会让整个格点场发生偏移。所以转换之前要严格核对两个系统定义的投影中心经度、纬度和两条标准纬线。我每次做完转换都会画一张风场矢量图叠加地形肉眼确认风场走向与地形走势和实测站点风向基本一致再进入下一步。3.4 时间完整性检查一小时缺测都可能导致风场跳变CALMET对气象数据的时间连续性要求很严格。它假设每个网格点每小时都有一组完整的气象要素。如果某小时数据缺测程序要么跳过要么用插值填充如果缺测时段恰好处于温度剧烈变化的清晨或傍晚插值出来的气象场会明显偏离真实状态造成污染物扩散路径和实际情况差出好几公里。我在整理数据时的习惯是写一个小脚本把地面观测和探空观测的时间戳全部列出来和模拟时段做对比把缺测的小时数、重复的小时数都标出来。对缺测时长在2小时以内的用前后线性插值补齐超过2小时的干脆在CALMET输入文件里把这个小时对应的DATA_PERIOD标记为缺测让程序用初猜场替代。实测下来这种处理方式的稳定性比硬插值好很多。4. 地形与土地利用处理TERREL和CTGPROC的正确打开方式4.1 地形数据SRTM 90米已经够用关键是范围要超出模拟区域CALMET的模拟区域通常是一个矩形网格网格点上的海拔高度来自地形文件。TERREL程序负责把原始DEM转换成CALMET可读的GEO.DAT格式。原始地形数据我用得最多的是SRTM 90米分辨率数据对几十公里范围内的模拟来说完全够用除非地形特别破碎的山区需要ASTER GDEM这类更高分辨率的数据。这里想提醒一个很容易忽略的细节地形数据的范围一定要比CALMET模拟区域外扩至少10到20公里。因为CALMET在计算诊断风场时会考虑地形对气流的阻挡和绕流效应靠近边界的格点会受到外部地形的影响。如果地形数据刚好截断在模拟边界上边界格点的风场就会因为看到一处悬崖而产生虚假的下沉气流或绕流污染物的输运会明显偏离真实。我一般下载地形数据时直接按模拟区域外扩50公里去裁剪保证边界效应降到最低。TERREL处理完了生成的地形文件还要用检查工具看一眼生成的网格有没有异常值。我遇到过一次某个网格点海拔高程出现了-9999这种填充值程序没有报错但周围几个格点风场全被带偏了原因是有个格点正好处在原始DEM数据的无数据区域。这种问题肉眼看不出来必须用脚本把地形文件中的最小值、最大值和标准差打出来瞄一眼看到异常值就去检查原始数据。4.2 土地利用数据USGS 24类分类和地表参数CALMET计算边界层参数时需要知道每个网格点的地表粗糙度、反照率、土壤热通量参数和波文比等这些参数由土地利用类型决定。CTGPROC程序负责把土地利用栅格转换成CALMET需要的.LU格式文件。国内项目里最常见的坑是土地利用数据源。美国USGS的全球土地覆被数据更新较慢中国的土地利用格局变化又很快直接用原版数据集可能跟实际情况差得很远。比如某个模拟区域已经开发成工业园区但土地利用分类还显示是农田这样算出来的地表粗糙度会偏小边界层湍流偏弱污染物地面浓度容易被高估。所以我通常的做法是先加载USGS原始土地覆被再结合当地最新的土地利用现状图或卫星解译结果把关键网格点的分类手动修正过来。CTGPROC处理完后生成的每个格点的土地利用类型代码必须落在1到24之间。0代表水域。代码乱的网格也会导致CALMET计算时参数查找表匹配到错误的行风场和湍流参数都会出问题。处理完这一步最好用地理信息系统工具把土地利用分类渲染出来和卫星影像叠加对比看看主要的地物边界对不对得上。4.3 网格设计水平网格、垂直分层和嵌套的关系模拟网格的设计虽然不是数据预处理本身但它决定了后面所有计算的工作量和精度。CALPUFF对水平网格的典型做法是外层网格粗、内层网格细但CALMET本身不直接支持嵌套需要分别跑外层和内层的CALMET再让CALPUFF分别使用对应的气象场。垂直分层方面CALMET允许定义最多12层。我常用的垂直分层结构大致是0米地面、10米、30米、60米、100米、200米、400米、600米、1000米、1500米、2200米、3000米。这个分层方案能比较好地描述近地面到边界层顶的关键气象过程也不至于让计算量失控。水平网格分辨率的选择先根据模拟范围定20-40公里的项目用500米到1公里的格距比较合理如果范围扩大到100公里级别格距可以放宽到2-3公里。网格设计时还有一件事要提早确认格点坐标系的原点、格点数和格距直接决定了后面所有源和受体点的位置。如果前面地形和土地利用都是在同一个投影下处理的那这一步通常不会出问题一旦投影不一致后面所有的源坐标转换都会跟着出岔子。我有一次在乌审旗附近做项目就是因为原点和格距设错导致把烟囱坐标换算到网格坐标时出现千人公里的偏差后来在屏幕上发了一下午才找到原因。5. 污染源参数化把排放清单翻译成CALPUFF的源语言5.1 点源参数烟囱不是填个高度就完事CALPUFF里点源描述的信息比AERMOD还要细。除了常规的烟囱高度、内径、出口速度、烟气温度还要设置排放速率以及随时间和季节变化的因子。其中最容易出问题的是浮力通量相关的参数。烟气出口速度和烟温决定了烟气抬升高度两者算出来的浮力通量直接决定烟羽是往上冲还是刚出烟囱就被水平风场带走。项目报告里的烟囱参数往往来自设计值但实际运行时锅炉负荷、脱硫脱硝设施投运情况都会让烟温和排烟量产生波动。我在做逐时模拟时会根据实际运行负荷对烟气温度和出口速度做折减而不是把所有小时都填成满负荷值否则夏季低负荷时段模拟出来的地面浓度会系统性偏大。CALPUFF对点源坐标的处理也值得注意输入烟囱位置时用的是相对于模拟区域原点通常是最左下角格点的东向、北向距离单位是米。很多人会把经纬度直接填进去或者填成UTM绝对坐标结果源被放到模拟区域外面几百公里。CALPUFF运行倒是能跑完但输出的浓度等值线全在模拟区域之外这种低级错误在报告审核时非常尴尬。5.2 面源、线源和体源不要为了省事把线源简化成面源除了点源实际项目里很容易碰到无组织排放、道路扬尘、料场堆场这类排放形式。CALPUFF支持面源和体源也能通过线性源描述道路污染。我的经验是能按线源描述的尽量按线源描述不要图省事把一整条道路的排放浓缩成一个面源。因为面源会人为地把污染物初始扩散尺度拉大近道路处的地面浓度会被显著低估而几十米外又会高估。特别是在做道路交通对周边敏感点的环境影响评价时这种误差很难向评审专家解释清楚。体源适合描述体积较大的释放设施比如仓库无组织泄漏、储罐的大小呼吸排放。参数方面体源的初始扩散尺度通常取建筑或储罐的特征尺寸不要拍脑袋填一个值。我在一个储运项目里就是用的体源模拟储罐区无组织逸散初始扩散尺度按罐区边长的一半来取模拟结果和监测点数据的对应关系明显比用简单面源好。5.3 时变排放与化学转化让模拟更接近真实工况CALPUFF允许给每个源设置排放随季节或逐小时变化的系数用于反映生产工艺负荷、采暖期、上下班高峰期等排放变化。这个功能特别好用但也带来一个问题默认情况下如果不设置任何时间变化程序会当作每个小时排放量都相同这在很多平稳工艺项目里问题不大但遇到交通源、施工扬尘这类有明显日变化特征的源就一定要把时变因子做进去。化学转化方面CALPUFF内置了SO2到SO4、NO到NO2、NO2到硝酸盐等转化的简化机制需要设定反应速率系数和平衡参数。这不仅影响二次污染物浓度还会改变一次污染物的去除效率。如果项目只需要模拟一次污染物可以关闭化学转换模块但如果评审专家关心PM2.5或NO2那就必须把化学模块打开并对照当地实际的大气氧化性情况设置合理的反应速率。6. CALMET核心参数调试诊断风场能否可信的关键开关6.1 稳定度分层与微气象参数从地表能量平衡说起CALMET的微气象模块根据地表能量平衡计算每个小时每个格点的感热通量、摩擦速度和混合层高度。它需要用户提供各种地表参数包括反照率、波文比、土壤热通量参数和地表粗糙度这些参数来自土地利用分类的查找表。如果土地利用分类错了后面的边界层参数就跟着错最终影响的是烟气抬升和垂直扩散参数。我调试时习惯先跑出一段典型时段的微气象参数看一眼混合层高度的日变化曲线是否合理晴天午后混合层高度应该达到一天的峰值夜间应该下降到几百米甚至更低。如果曲线完全平坦或者午夜比中午还高那基本可以肯定是土地利用分类或太阳辐射输入出了问题。这个检查只需要几分钟却能避免后面大量无效的扩散模拟。6.2 地形动力学参数Froude数和避风效应CALMET在复杂地形区域有一个专门的地形适应模块用来处理气流遇山绕流和越山两种情形。它对这两个情形的判断主要通过地形尺度高度和布伦特-维萨拉频率计算出一个无量纲参数通常叫Froude数。当大气层结稳定、风速较小的时候气流倾向于绕过山体而不是翻越山体CALMET会调整风矢量让它沿地形绕行。这个过程的强度由输入参数控制参数设置不当会让风场要么完全无视地形要么过分绕流导致背风坡出现虚构的涡旋。我在一个山区电厂项目的调试中发现把Froude数相关的避风参数从默认值调高一些后风场在山脊背风侧的绕流行为才跟实际观测的风向一致起来。当然具体调多少不能凭空拍板要拿项目区域内的风观测数据去验证。如果模拟区域里有多个气象站可以用CALMET输出的地面风场和实测风场做矢量差对比反复调整参数直到偏差最小。6.3 风场插值过渡平滑参数与地形影响半径CALMET中的风场插值过程包括两个阶段先用权重插值把观测站数据生成初步风场再用地形动力学模型修正风场。这个过程中有几个关键参数插值半径、影响半径和地形协同因子。插值半径决定了观测站数据能影响到多远的格点如果模拟区域很大观测站又少插值半径设置过小会让远离站点的区域几乎完全依赖初始猜测场而初始猜测场又来自稀疏的探空风场自然不可信。影响半径和地形协同因子则控制地形对气流的强迫程度。这两个参数也是需要结合项目区地形起伏程度来调。平原地区取小值山地丘陵区域取大值。不要指望一套参数通吃所有项目。我每接一个新项目都会根据模拟区域的地形特征重新校一遍这组参数这也是CALPUFF和其他模型比起来更费工程师的原因。6.4 CALMET报错日志从数据空洞到风场发散调试CALMET的过程中报错日志是最好的老师。常见问题基本可以归结为三类一是地形文件数据空洞报错信息通常指向某个格点的海拔值异常解决办法是回到TERREL重新检查原始DEM必要时用地形平滑选项处理数据空洞。二是气象数据时间不连续报错信息会明确告诉你缺了哪一天哪一小时的观测这类问题只能回到气象数据预处理环节补时刻。三是垂直分层结构不匹配比如某个气象站上报的探空层顶高度低于CALMET要求的最大垂直层高度这时要么调整垂直分层方案要么补探空数据。我自己遇到过最棘手的一次是CALMET风场出现明显发散风速在相邻两个格点之间暴涨到几十米每秒。排查后发现是土地利用数据里有几个网格被分成了水面和城市交替排列导致粗糙度在空间上出现锯齿状跳变微气象模块计算通量时产生了数值不稳定。把土地利用分类做了一次中值滤波后风场立刻恢复正常。这种问题报告里不会写只有亲自在数据上摸爬滚打过才能积累下来。7. CALPUFF主程序运行把气象场变成浓度场的最后一步7.1 模拟时段、时间步长和化学沉降模块的取舍CALPUFF主程序运行时第一步是把CALMET输出的气象场文件作为输入同时读入污染源参数、受体网格设置、化学模块开关、干湿沉降选项等。模拟时段的设定要和气象数据时段严格一致起点和终点都取整小时。时间步长方面CALPUFF允许用户根据烟团移动速度动态调整步长但合理的最大时间步长还是控制在1小时以内比较好。污染物在强风条件下每小时能移动几十公里步长太大会让烟团跳跃式地穿过网格浓度场出现漏格。化学转化模块在CALPUFF里是可选的。如果模拟的目的是常规环评的SO2地面浓度那就关闭化学反应让SO2以一次污染物的形式随烟团输送这样结果简单可解释评审也好通过。但如果项目涉及NO2或PM2.5的二次组分就必须打开化学模块并设置准确的转化速率参数。需要注意化学模块开启后计算量会成倍增加尤其是模拟时段长达一年的时候运行时间可能从几十分钟膨胀到几个小时。实测下来把化学模块打开后跑全年逐时模拟时间成本至少增加三倍所以做批量情景分析之前要想清楚究竟需不需要化学模块。7.2 受体点设置敏感目标直接设成离散受体别只靠网格点CALPUFF的浓度输出有两种方式一种是格点浓度即模拟区域内每个网格点的浓度值适合画等值线图另一种是离散受体点浓度适合关注敏感目标处的具体数值。后者在环评里尤其重要因为评审专家关心的往往是学校、医院、居民区这些具体位置。我的习惯是把环评报告里涉及的全部敏感目标坐标提前整理出来统一转成CALPUFF坐标设为离散受体点。同时把整个模拟区域的网格浓度输出打开间距一般设为和气象网格一致。这样既能量化敏感点的浓度达标情况又能画出一张连续的浓度等值线图。这里有个小经验受体点的最大数量在不同版本里有限制项目大了要分批跑避免因为受体点超过上限导致程序异常退出。7.3 批量情景运行的脚本技巧CALPUFF主程序的输入文件是文本格式每个源、每个时间段、每个选项都有对应的参数行。做情景分析时经常需要修改排放量或气象时段手动改文件又慢又容易出错。我一般会用脚本批量生成输入文件、批量运行、批量改名输出文件。比如做正常工况和非正常工况两组情景的时候只需要改排放速率相关的两行其他参数全部保持不变。用脚本读入模板文件、替换变量、生成新的输入文件、依次运行calpuff再把每组输出的NCD文件按情景名重命名归档。这个方法看起来简单但能让一个项目从原来的一天工作量缩短到半小时而且基本不会因为漏改参数导致情景之间出现差异。脚本里的参数校验环节也不能省比如跑完后检查输出文件里的总质量是否与排放量一致质量守恒偏差超过5%就说明网格或步长设置有问题需要回头排查。8. CALPOST后处理把无趣的数字变成能用的图和表8.1 CALPOST输出类型平均时段与统计形式的选择CALPOST是CALPUFF配套的后处理程序它读取CALPUFF输出的浓度场按用户指定的平均时段生成统计结果。常见的输出包括1小时平均浓度、3小时平均浓度、24小时平均浓度、年均浓度等。实际应用中环境影响评价关注的类型不同需要的统计时段也就不同。短期浓度看1小时和24小时最大值的分布长期平均浓度则要看全年平均值的空间分布。CALPOST输入文件的设置相对简单但有一个选项特别容易忽略——浓度输出的单位转换。CALPUFF默认输出的浓度单位是微克每立方米但不同版本和不同污染物有细微差异如果直接拿来和标准限值比较不把单位核对清楚结果可能差出1000倍。我在一个水环境项目里面犯过这种低级错误后来养成习惯拿到输出文件先看文件头里记录的污染物名称和单位再决定是否需要换算。8.2 可视化把等值线叠到地图上而不是只在表格里看数字浓度场计算完了如果不做可视化很难向非专业人士解释清楚模拟结果。常规做法是把CALPOST输出的格点浓度写成GRD格式然后用Surfer或者ArcGIS打开叠加地形和敏感目标位置绘制浓度等值线图。CALPUFF的官方图形工具也能直接出图但做报告还是建议用GIS软件控制版面、标注敏感点、叠加比例尺都比专门工具灵活。画图的时候有个细节浓度等值线的分层间隔要结合评价标准来设置而不是用软件默认的等差序列。比如评价标准是24小时平均浓度150微克每立方米那等值线里一定要出现100、150、200这些档位让人一眼就能看出达标区、超标区和衰减趋势。默认等差序列往往会漏掉关键限值对应的等值线图面上看不到超标范围审图的专家会直接质疑你的模拟价值。8.3 模拟值与监测值的对标别迷信模型也别一上来就调参最后一步至关重要用同步期的监测数据验证模拟结果。通常的做法是选择监测点附近的网格或离散受体点将模拟浓度值和实测浓度值放在同一张时间序列图上对比。如果模拟值整体偏高先检查排放清单是不是把源强估大了如果整体偏低就要看气象场是否低估了扩散能力或者源清单漏掉了某些源。对标的时候最大的忌讳是一上来就调模型参数去拟合监测值。模型参数应当基于物理机理和实际站点数据来标定而不是为了凑数字乱调。如果模拟值和监测值趋势一致、数值偏差在合理范围内那这个模型就是可信的。我在一个项目里花了将近两周时间反复校准最后发现主要问题不在模型而是排放清单里有一个大型锅炉的烟气温度填错了导致抬升高度偏大、地面浓度整体偏低。修正数据之后模拟值和监测值的偏差从百分之七八十降到了百分之二三十。这个体验让我坚信模型跑不好八成问题在输入数据而非模型本身。9. 最后说几句我踩过的土坑前面讲了很多技术细节最后再聊聊我个人的感受。CALPUFF全流程里真正考验人的不是模型理论有多深而是你能不能把各种来源的数据洗干净、对齐、转成程序认得的格式。我在这个过程中最大的教训是永远不要相信原始数据是完整且正确的。每次拿到气象站数据先做一遍时间完整性与范围合理性检查每次拿到地形或土地利用数据先做投影核对每次跑完一个情景先看输出文件里有没有警告信息。这些习惯能帮你避开绝大多数让项目卡壳的坑。另外虽然CALPUFF官方文档和用户手册写得很详细但它毕竟是面向专业用户的工具很多参数的含义在手册里只有一句话真正怎么取值还是要靠积累项目经验。建议刚开始接触这个模型的同事拿一个有完整实测数据的项目练手把每个参数的含义、每个中间文件的格式、每次报错的原因都记录下来。跑完两三个项目你会发现自己已经能条件反射式地判断哪些参数出了问题这种手感是任何教程都给不了的。如果你正准备做第一个CALPUFF项目我的建议很简单先别急着追求复杂情景老老实实从单点源、短时段、简单气象场开始把全链路跑通一遍再往里面加地形、加化学、加长时段。全流程通一次之后你会发现CALPUFF从那个输入文件多到吓人的黑箱变成了一个逻辑清晰的工具箱。祝各位都能一次跑通少踩几个我当年踩过的坑。
返回列表