对流层延迟误差计算

本文介绍了Saastamoinen和UNB3m两种气象模型,用于计算对流层延迟,包括静力学延迟和湿延迟。Saastamoinen模型详细展示了如何根据气压、气温和海拔计算延迟,而UNB3m模型则依赖于年均值和振幅参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、写在前面

需要实测气象参数的模型:Saastamoinen模型、Hopfield模型

不需要实测气象参数的模型:UNB模型、UNB3m模型(只需要提供高程、纬度和年积日即可计算对流层延迟量)

一般对流层模型中,将对流层天顶总延迟(ZTD:Zenith Total Delay)分为对流层静力学延迟(ZHD:Zenith Hydrostatic Delay)和对流层湿延迟(ZWD:Zenith Wet Delay)。静力学延迟约占总延迟量的90%,可以通过实测气压和气温来计算,而湿延迟影响因素较多,不太容易估算。

PS:静力学延迟又叫做干延迟 ,非静力学延迟又叫做湿延迟。

二、Saastamoinen模型

代码如下:

/*Saastamoinen模型*/
void Saastamoinen(double elevation, double Phi_u, double h, double *Th, double *Tw)
{
    const double P0 = 1013.25, e0 = 11.69, T0 = 288.15;
    double p;//大气压力
    double e;//水汽压
    double T;//大气温度

    /*求大气压力*/
    p = P0 * pow( (1.0 - 0.0068 / T0 / h) , 5);
    printf("大气压力p = %.10lf\n",p);

    /*大气温度*/
    T = 288.15 - 0.0068 * h;//开尔文温度
    printf("大气温度T = %.10lf\n",T);

    /*水汽压e*/
    if(h > 11000)
    {
        e = 0;
    }
    else
    {
        e = e0 * pow((1.0 - 0.0068 * h / T0) , 4);
    }

    /*静力学延迟Th*/
    *Th = 0.002277 * p / (1.0 - 0.00266 * cos(2 * Phi_u * M_PI/180) - 0.00028 * h * 1e-3) ;
    /*湿延迟Tw*/
    *Tw = 0.0022768 * (1255.0 / T + 0.05) / (1.0 - 0.00266 * cos(2 * Phi_u * M_PI/180) - 0.00028 * h * 1e-3) * e;

    printf("静力学延迟Th = %.10lf\n",*Th);
}
//Saastamoinen.h
void Saastamoinen(double elevation, double Phi_u, double h, double *Th, double *Tw);

三、UNB3模型

静力学延迟:

非静力学延迟:

上面参数按照以下公式得出,

Average是年均值,Amplitude是振幅值或者波动值。

Lati指的是离Φ最近的两个纬度中最小的那个,比如41度的Lati为30度。

参考年积日为28,28日为延迟最小的一天。

在式(7)中,T= T0 - βH。

Hopfield的精度较差,此处不做说明。UNB3m与UNB3在参数表上有所不同。UNB3的water vapour pressure (WVP)在UNB3m中被换为relative humidity (RH)。

原因:

The version UNB3m was developed to avoid the problematic values of relative humidity. Following the same method of computation as for the pressure and the temperature, average and amplitude for relative humidity were derived from the U.S. Standard Atmosphere Supplements, 1966 [Orliac, 2002].

代码如下:

const double P_avg[5] = {1013.25, 1017.25, 1015.75, 1011.75, 1013.00};//压强年均值
const double T_avg[5] = {299.65, 294.15, 283.15, 272.15, 263.65};//温度年均值
const double e_avg[5] = {26.31, 21.79, 11.66, 6.78, 4.11};//水汽压年均值
//const double e_avg[5] = {75.0, 80.0, 76.0, 77.5, 82.5};
const double Beta_avg[5] = {6.30e-3, 6.05e-3, 5.58e-3, 5.39e-3, 4.53e-3};//温度梯度年均值
const double LambDa_avg[5] = {2.77, 3.15, 2.57, 1.81, 1.55};//水汽梯度年均值

const double P_amp[5] = {0.00, -3.75, -2.25, -1.75, -0.50};//压强振幅值
const double T_amp[5] = {0.00, 7.00, 11.00, 15.00, 14.50};//温度振幅值
const double e_amp[5] = {0.00, 8.85, 7.24, 5.36, 3.39};//水汽压振幅值
//const double e_amp[5] = {0.0, 0.0, -1.0, -2.5, 2.5};
const double Beta_amp[5] = {0.00, 0.25e-3, 0.32e-3, 0.81e-3, 0.62e-3};//温度梯度振幅值
const double LambDa_amp[5] = {0.00, 0.33, 0.46, 0.74, 0.30};//水汽梯度振幅值

const double k1 = 77.60, k2_l = 16.60, k3 = 377600;
const double g = 9.80665, Rd = 287.054;

/*UNB3*/
void UNB3(double Phi, double H, double DOY, double *ZHD, double *ZWD)
{
    double dh;
    double T0, P0, e0, Beta, LambDa;
    double gm, Tm, LambDa_l;

    /*求5个气象参数*/
    Coefficient(Phi, DOY, &T0, &P0, &e0, &Beta, &LambDa);
    //printf("T0 = %.10lf,P0 = %10.lf,e0 = %.10lf,Beta = %.10lf,LambDa = %.10lf\n",T0,P0,e0,Beta,LambDa);

    LambDa_l = LambDa + 1;
    gm = 9.784 * (1.0 - 2.66 * 1e-3 * cos(2 * Phi * M_PI/180) - 2.8e-7);
    Tm = (T0 - Beta * H) * (1.0 - Beta * Rd / gm / LambDa_l);
    //printf("LambDa = %.10lf\n",LambDa);

    /*天顶方向的干延迟和湿延迟*/
    *ZHD = 1e-6 * k1 * Rd / gm * P0 * pow((1.0 - Beta * H / T0) , g / (Rd * Beta));
    *ZWD = 1e-6 * Rd * (Tm * k2_l + k3) / (gm * LambDa_l - Beta * Rd) * pow((1.0 - Beta * H / T0) , LambDa_l * g / Rd / Beta - 1.0) * (e0 / T0);

}

/*计算5个气象参数*/
void Coefficient(double Phi, double DOY, double *T0, double *P0, double *e0, double *Beta, double *LambDa)
{
    double Tem;

    Tem = cos((DOY - 28) * 2 * M_PI / 365.25);

    /*求T0 P0 e0 Beta LambDa*/
    if(Phi<=15)
    {
        *T0 = T_avg[0] - T_amp[0] * Tem;
        *P0 = P_avg[0] - P_amp[0] * Tem;
        *e0 = e_avg[0] - e_amp[0] * Tem;
        *Beta = Beta_avg[0] - Beta_amp[0] * Tem;
        *LambDa = LambDa_avg[0] - LambDa_amp[0] * Tem;
    }
    if(Phi>15&&Phi<30)
    {
        *T0 = T_avg[0] + (T_avg[1] - T_avg[0]) / 15 * (Phi - 15) - (T_amp[0] + (T_amp[1] - T_amp[0]) / 15 * (Phi - 15)) * Tem;
        *P0 = P_avg[0] + (P_avg[1] - P_avg[0]) / 15 * (Phi - 15) - (P_amp[0] + (P_amp[1] - P_amp[0]) / 15 * (Phi - 15)) * Tem;
        *e0 = e_avg[0] + (e_avg[1] - e_avg[0]) / 15 * (Phi - 15) - (e_amp[0] + (e_amp[1] - e_amp[0]) / 15 * (Phi - 15)) * Tem;
        *Beta = Beta_avg[0] + (Beta_avg[1] - Beta_avg[0]) / 15 * (Phi - 15) - (Beta_amp[0] + (Beta_amp[1] - Beta_amp[0]) / 15 * (Phi - 15)) * Tem;
        *LambDa = LambDa_avg[0] + (LambDa_avg[1] - LambDa_avg[0]) / 15 * (Phi - 15) - (LambDa_amp[0] + (LambDa_amp[1] - LambDa_amp[0]) / 15 * (Phi - 15)) * Tem;
    }
    if(Phi>=30&&Phi<45)
    {
        *T0 = T_avg[1] + (T_avg[2] - T_avg[1]) / 15 * (Phi - 30) - (T_amp[1] + (T_amp[2] - T_amp[1]) / 15 * (Phi - 30)) * Tem;
        *P0 = P_avg[1] + (P_avg[2] - P_avg[1]) / 15 * (Phi - 30) - (P_amp[1] + (P_amp[2] - P_amp[1]) / 15 * (Phi - 30)) * Tem;
        *e0 = e_avg[1] + (e_avg[2] - e_avg[1]) / 15 * (Phi - 30) - (e_amp[1] + (e_amp[2] - e_amp[1]) / 15 * (Phi - 30)) * Tem;
        *Beta = Beta_avg[1] + (Beta_avg[2] - Beta_avg[1]) / 15 * (Phi - 30) - (Beta_amp[1] + (Beta_amp[2] - Beta_amp[1]) / 15 * (Phi - 30)) * Tem;
        *LambDa = LambDa_avg[1] + (LambDa_avg[2] - LambDa_avg[1]) / 15 * (Phi - 30) - (LambDa_amp[1] + (LambDa_amp[2] - LambDa_amp[1]) / 15 * (Phi - 30)) * Tem;
    }
    if(Phi>=45&&Phi<60)
    {
        *T0 = T_avg[2] + (T_avg[3] - T_avg[2]) / 15 * (Phi - 45) - (T_amp[2] + (T_amp[3] - T_amp[2]) / 15 * (Phi - 45)) * Tem;
        *P0 = P_avg[2] + (P_avg[3] - P_avg[2]) / 15 * (Phi - 45) - (P_amp[2] + (P_amp[3] - P_amp[2]) / 15 * (Phi - 45)) * Tem;
        *e0 = e_avg[2] + (e_avg[3] - e_avg[2]) / 15 * (Phi - 45) - (e_amp[2] + (e_amp[3] - e_amp[2]) / 15 * (Phi - 45)) * Tem;
        *Beta = Beta_avg[2] + (Beta_avg[3] - Beta_avg[2]) / 15 * (Phi - 45) - (Beta_amp[2] + (Beta_amp[3] - Beta_amp[2]) / 15 * (Phi - 45)) * Tem;
        *LambDa = LambDa_avg[2] + (LambDa_avg[3] - LambDa_avg[2]) / 15 * (Phi - 45) - (LambDa_amp[2] + (LambDa_amp[3] - LambDa_amp[2]) / 15 * (Phi - 45)) * Tem;

    }
    if(Phi>=60&&Phi<75)
    {
        *T0 = T_avg[3] + (T_avg[4] - T_avg[3]) / 15 * (Phi - 60) - (T_amp[3] + (T_amp[4] - T_amp[3]) / 15 * (Phi - 60)) * Tem;
        *P0 = P_avg[3] + (P_avg[4] - P_avg[3]) / 15 * (Phi - 60) - (P_amp[3] + (P_amp[4] - P_amp[3]) / 15 * (Phi - 60)) * Tem;
        *e0 = e_avg[3] + (e_avg[4] - e_avg[3]) / 15 * (Phi - 60) - (e_amp[3] + (e_amp[4] - e_amp[3]) / 15 * (Phi - 60)) * Tem;
        *Beta = Beta_avg[3] + (Beta_avg[4] - Beta_avg[3]) / 15 * (Phi - 60) - (Beta_amp[3] + (Beta_amp[4] - Beta_amp[3]) / 15 * (Phi - 60)) * Tem;
        *LambDa = LambDa_avg[3] + (LambDa_avg[4] - LambDa_avg[3]) / 15 * (Phi - 60) - (LambDa_amp[3] + (LambDa_amp[4] - LambDa_amp[3]) / 15 * (Phi - 60)) * Tem;

    }
    if(Phi>=75)
    {
        *T0 = T_avg[4] - T_amp[4] * Tem;
        *P0 = P_avg[4] - P_amp[4] * Tem;
        *e0 = e_avg[4] - e_amp[4] * Tem;
        *Beta = Beta_avg[4] - Beta_amp[4] * Tem;
        *LambDa = LambDa_avg[4] - LambDa_amp[4] * Tem;
    }

}
//UNB3.h
void UNB3(double Phi, double H, double DOY, double *ZHD, double *ZWD);
void Coefficient(double Phi, double DOY, double *T0, double *P0, double *e0, double *Beta, double *LambDa);

四、对流层总延迟

根据以上模型算出的皆为对流层天顶延迟,也不需要用到卫星仰角(高度角)。若想算出总延迟,要再乘以映射函数。干延迟乘以干映射函数,湿延迟乘以湿映射函数,再相加。

 

在这里藏一个main函数吧。

#include <stdio.h>
#include <math.h>
#include "Saastamoinen.h"
#include "UNB3.h"
#include "NMF.h"

int main() {

    double Phi = 30.53165278 ;//用户地理纬度
    double elevation =  0.2326965967;//卫星高度角或卫星仰角
    double H = 28.2;//用户海拔
    double DOY[10] = {152, 152 + 300.0/86400, 152 + 600.0/86400, 152 + 900.0/86400, 152 + 1200.0/86400, 152 + 1500.0/86400, 152 + 1800.0/86400,
                      152 + 2100.0/86400, 152 + 2400.0/86400, 152 + 2700.0/86400};//年积日

    for(int i=0;i<10;i++)
    {
        UNB3(Phi, H, DOY[i], &ZHD, &ZWD);
        printf("ZHD = %.10lf,ZWD = %.10lf\n",ZHD,ZWD);
        //Saastamoinen(elevation,Phi, H, &Th, &Tw);
        //printf("Th = %.10lf,Tw = %.10lf\n",Th,Tw);
    }
    return 0;
}

<think>嗯,用户想了解Excel中的VLOOKUP函数的用法和参数含义。首先,我需要回忆一下VLOOKUP的基本结构。VLOOKUP是垂直查找函数,用于在表格的首列查找指定的值,然后返回该行中指定列的数据。它的四个参数分别是查找值、表格范围、列索引号和匹配模式。 接下来,我得确认每个参数的具体作用。第一个参数是lookup_value,也就是用户要查找的值,比如产品ID或者姓名。第二个参数是table_array,即查找的范围,这里要注意的是,查找值必须位于这个范围的第一列,否则函数无法正确工作。第三个参数是col_index_num,也就是用户想要返回的数据在表格范围中的第几列,这个列数是从表格范围的第一列开始算起的,不是整个工作表的列。第四个参数是range_lookup,决定是精确匹配还是近似匹配,通常用FALSE或0来指定精确匹配,避免错误。 然后,用户可能需要一个具体的例子来理解如何使用。比如,假设有一个产品价格表,用户想根据产品ID查找对应的价格。这时候,VLOOKUP就可以在ID列查找,然后返回价格列的数据。同时,要提醒用户注意表格范围最好使用绝对引用,比如$A$2:$C$100,这样在拖动公式时范围不会变化。 可能遇到的问题也需要考虑。比如,如果查找值不在表格的第一列,或者列索引号超过了表格的列数,函数会返回错误。此外,数据格式不一致也可能导致问题,比如查找值是数字,而表格中是文本格式的数字,这时候需要统一格式。还有,当出现#N/A错误时,可能是查找值不存在,或者匹配模式设置不正确,需要检查参数是否正确。 用户可能还会问到如何避免常见的错误,比如部分数据匹配出错的情况。这时候需要检查是否有多余的空格,或者数据格式不一致,或者表格范围没有锁定导致拖动时偏移。此外,XLOOKUP作为VLOOKUP的升级版,可能在某些情况下更方便,比如可以向左查找或者返回多列数据,这也是可以提及的内容。 最后,整理步骤,从基础语法到参数说明,再到具体案例,逐步引导用户理解如何使用VLOOKUP函数。同时,提供常见错误和解决方法,帮助用户在实际应用中避免问题。如果有必要,还可以比较VLOOKUP和其他查找函数的区别,比如HLOOKUP或XLOOKUP,但根据用户的问题,主要集中在VLOOKUP本身即可。</think>### Excel VLOOKUP函数详解 #### 一、基础语法与参数说明 VLOOKUP函数的语法为: $$=VLOOKUP(lookup\_value, table\_array, col\_index\_num, [range\_lookup])$$ 包含4个参数: 1. **lookup_value**(必填):要查找的值(如单元格引用或具体值) 2. **table_array**(必填):包含数据的表格范围(必须包含查找列和返回列) 3. **col_index_num**(必填):返回值所在列的序号(从table_array第一列开始计数) 4. **range_lookup**(可选):匹配类型 - `TRUE`/`1`:近似匹配(默认值,需数据升序排列) - `FALSE`/`0`:精确匹配(常用选项) [^1][^2] #### 二、使用步骤演示(工资表查询案例) 假设需要根据员工编号查询工资: 1. 建立查询单元格(如`B12`) 2. 输入公式: ```excel =VLOOKUP(A12, $A$2:$D$100, 4, 0) ``` - `A12`:待查询的员工编号 - `$A$2:$D$100`:锁定数据区域(绝对引用) - `4`:返回第4列(工资列) - `0`:精确匹配 [^2][^3] #### 三、常见错误与解决方法 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | #N/A | 查找值不存在 | 检查数据源或改用`IFERROR`容错 | | #REF! | 列序号超出范围 | 确认col_index_num ≤ 表格列数 | | 部分匹配失败 | 数据格式不一致 | 统一数值/文本格式 | | 结果错位 | 表格未锁定 | 使用`$`符号固定区域引用 | [^3][^4] #### 四、进阶技巧 1. **多条件查询**: 使用辅助列合并多个条件字段 ```excel =VLOOKUP(A2&B2, $D$2:$F$100, 3, 0) ``` 2. **通配符匹配**: `"*"`匹配任意字符,`"?"`匹配单个字符 ```excel =VLOOKUP("张*", $A$2:$C$100, 3, 0) ``` 3. **跨表查询**: 引用其他工作表数据 ```excel =VLOOKUP(A2, Sheet2!$A$2:$D$100, 4, 0) ``` [^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值