gctl_toolkits/archive/sh2xyz/NALF-SFCM.h
2024-09-10 20:25:18 +08:00

143 lines
4.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Fully normalized associated Legendre functions calculated by standard forward column methods
// Holmes, S. A., & Featherstone, W. E. (2002).
// A unified approach to the Clenshaw summation and the recursive computation of very high degree and order normalised associated Legendre functions.
// Journal of Geodesy, 76(5), 279299. https://doi.org/10.1007/s00190-002-0216-2
// Author: Yi Zhang (zhangyi.cugwuhan@gmail.com)
#ifndef _NALF_SFCM_H
#define _NALF_SFCM_H
#include "sysDefine.h"
//计算向前列推的系数 避免重复计算 这里不要使用vector at() 速度比较慢 直接使用[] 注意调用size()函数也会降低执行效率
_2dArray get_a_nm_array(int MaxOrder)
{
int i,j;
_2dArray cs;
cs.resize(MaxOrder);
for (i = 0; i < MaxOrder; i++)
cs[i].resize(i+1);
//向下列推计算
#pragma omp parallel for private(i,j) schedule(guided)
for (j = 0; j < MaxOrder; j++)
{
cs[j][j] = 0; //对角线上的值直接给0 反正用不到
for (i = j+1; i < MaxOrder; i++)
{
cs[i][j] = sqrt(((2.0*i-1)*(2.0*i+1))/((i-j)*(i+j)));
}
}
return cs;
}
_2dArray get_b_nm_array(int MaxOrder)
{
int i,j;
_2dArray cs;
cs.resize(MaxOrder);
for (i = 0; i < MaxOrder; i++)
cs[i].resize(i+1);
//向下列推计算
#pragma omp parallel for private(i,j) schedule(guided)
for (j = 0; j < MaxOrder; j++)
{
cs[j][j] = 0; //对角线上的值直接给0 反正用不到
for (i = j+1; i < MaxOrder; i++)
{
cs[i][j] = sqrt(((2.0*i+1)*(i+j-1)*(i-j-1))/((i-j)*(i+j)*(2.0*i-3)));
}
}
return cs;
}
// 计算标准前向列推法计算规格化的勒让德多项式 输入参数为需要计算的最大阶次MaxOrder 余纬度theta(度) 返回一个下半三角二维数组
// 最大维度为MaxOrder+1二维数组中行数代表阶数列数为次数
_2dArray NALF_SFCM(int MaxOrder,_2dArray a_nm,_2dArray b_nm,double theta)
{
//声明数组 初始化一个下半三角二维数组
_2dArray nalf;
nalf.resize(MaxOrder);
for (int i = 0; i < MaxOrder; i++)
nalf.at(i).resize(i+1);
//赋初值给前两个对角线上的值
nalf.at(0).at(0) = 1.0;
nalf.at(1).at(1) = sqrt(3.0)*sin(theta*pi/180.0);
//计算对角线上的值 递归计算 不能并行
for (int i = 2; i < nalf.size(); i++)
nalf.at(i).at(i) = sin(theta*pi/180.0)*sqrt(0.5*(2.0*i+1)/i)*nalf.at(i-1).at(i-1);
//声明系数和迭代变量
int i,j;
double Pn_2m,Pn_1m; //Pn-1,m Pn-2,m
//这里可以使用并行加速计算外层循环 内层计算因为是递归计算因此不能并行
#pragma omp parallel for private(i,j,Pn_2m,Pn_1m) schedule(guided)
for (j = 0; j < nalf.size()-1; j++)
{
Pn_2m = 0;
Pn_1m = nalf.at(j).at(j);
for (i = j+1; i < nalf.size(); i++)
{
nalf.at(i).at(j) = a_nm.at(i).at(j)*cos(theta*pi/180.0)*Pn_1m - b_nm.at(i).at(j)*Pn_2m;
Pn_2m = nalf.at(i-1).at(j);
Pn_1m = nalf.at(i).at(j);
}
}
return nalf;
}
// 计算标准前向列推法计算规格化的勒让德多项式 输入参数 一个下半三角二维矩阵 余纬度theta(度) 无返回值
// 二维数组中行数代表阶数列数为次数
void NALF_SFCM2(_2dArray& nalf,_2dArray a_nm,_2dArray b_nm,double theta)
{
//赋初值给前两个对角线上的值
nalf.at(0).at(0) = 1.0;
nalf.at(1).at(1) = sqrt(3.0)*sin(theta*pi/180.0);
//计算对角线上的值 递归计算 不能并行
for (int i = 2; i < nalf.size(); i++)
nalf.at(i).at(i) = sin(theta*pi/180.0)*sqrt(0.5*(2.0*i+1)/i)*nalf.at(i-1).at(i-1);
//声明系数和迭代变量
int i,j;
double Pn_2m,Pn_1m; //Pn-1,m Pn-2,m
//这里可以使用并行加速计算外层循环 内层计算因为是递归计算因此不能并行
#pragma omp parallel for private(i,j,Pn_2m,Pn_1m) schedule(guided)
for (j = 0; j < nalf.size()-1; j++)
{
Pn_2m = 0;
Pn_1m = nalf.at(j).at(j);
for (i = j+1; i < nalf.size(); i++)
{
nalf.at(i).at(j) = a_nm.at(i).at(j)*cos(theta*pi/180.0)*Pn_1m - b_nm.at(i).at(j)*Pn_2m;
Pn_2m = nalf.at(i-1).at(j);
Pn_1m = nalf.at(i).at(j);
}
}
}
void NALF_SFCM3(_2dArray& nalf,_2dArray a_nm,_2dArray b_nm,int maxOrder,double theta,double norSum)
{
//赋初值给前两个对角线上的值
//norSum为1时第一个值为1/sqrt(4.0*pi),归一化值为1, norSum为4.0*pi时第一个值为4.0*pi/sqrt(4.0*pi)=1,归一化值为4.0*pi
nalf[0][0] = sqrt(norSum)/sqrt(4.0*pi);
nalf[1][1] = sqrt(3.0)*sin(theta*pi/180.0);
//计算对角线上的值 递归计算 不能并行
for (int i = 2; i < maxOrder; i++)
nalf[i][i] = sin(theta*pi/180.0)*sqrt(0.5*(2.0*i+1)/i)*nalf[i-1][i-1];
//计算次对角线(m+1,m)上的值 递归计算 不能并行
for (int i = 0; i < maxOrder-1; i++)
nalf[i+1][i] = cos(theta*pi/180.0)*sqrt(2.0*i+3)*nalf[i][i];
//声明系数和迭代变量
int i,j;
//这里可以使用并行加速计算外层循环 内层计算因为是递归计算因此不能并行
#pragma omp parallel for private(i,j) schedule(guided)
for (j = 0; j < maxOrder-1; j++)
{
for (i = j+2; i < maxOrder; i++)
{
nalf[i][j] = a_nm[i][j]*cos(theta*pi/180.0)*nalf[i-1][j] - b_nm[i][j]*nalf[i-2][j];
}
}
}
#endif