int main() { double lat_deg,lon_deg,h,var; int yy,mm,dd; lat_deg=45.0; lon_deg=9.0; h= 1; // altitude in km mm= 10; dd= 1; yy= 11; var=rad_to_deg(SGMagVar(deg_to_rad(lat_deg),deg_to_rad(lon_deg),h, yymmdd_to_julian_days(yy,mm,dd))); fprintf(stdout,"var= %4.2f \n",var); }
void SGMagVar(Mag_Real lat, Mag_Real lon, Mag_Real h, Mag_Uint32 dat, float32* field) { int model = 9; // 9 is IGRF2005 int n,m,nmaxl; Mag_Real yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z; Mag_Real sinpsi, cospsi, inv_s; Mag_Real mm,c1_n,c2_n,c3_n,tmp; static int been_here = 0; Mag_Real sinlat; Mag_Real coslat; Mag_Real norm; /* output field B_r,B_th,B_phi,B_x,B_y,B_z */ h = h/1000.0; sinlat = sin(lat); coslat = cos(lat); /* convert to geocentric */ sr = sqrt(a*a*coslat*coslat + b*b*sinlat*sinlat); /* sr is effective radius */ theta = atan2(coslat * (h*sr + a*a), sinlat * (h*sr + b*b)); /* theta is geocentric co-latitude */ r = h*h + 2.0*h * sr + (a*a*a*a - ( a*a*a*a - b*b*b*b ) * sinlat*sinlat ) / (a*a - (a*a - b*b) * sinlat*sinlat ); r = sqrt(r); /* r is geocentric radial distance */ c = cos(theta); s = sin(theta); /* protect against zero divide at geographic poles */ inv_s = 1.0 / (s + (s == 0.)*1.0e-8); /*zero out arrays */ for ( n = 0; n <= nmax; n++ ) { for ( m = 0; m <= n; m++ ) { P[n][m] = 0; DP[n][m] = 0; } } /* diagonal elements */ P[0][0] = 1; P[1][1] = s; DP[0][0] = 0; DP[1][1] = c; P[1][0] = c ; DP[1][0] = -s; /* these values will not change for subsequent function calls */ if( !been_here ) { for ( n = 2; n <= nmax; n++ ) { root[n] = sqrt((2.0*n-1) / (2.0*n)); } for ( m = 0; m <= nmax; m++ ) { mm = m*m; for ( n = max_mag(m + 1, 2); n <= nmax; n++ ) { roots[m][n][0] = sqrt((n-1)*(n-1) - mm); roots[m][n][1] = 1.0 / sqrt( n*n - mm); } } been_here = 1; } for ( n=2; n <= nmax; n++ ) { /* double root = sqrt((2.0*n-1) / (2.0*n)); */ P[n][n] = P[n-1][n-1] * s * root[n]; DP[n][n] = (DP[n-1][n-1] * s + P[n-1][n-1] * c) * root[n]; } /* lower triangle */ for ( m = 0; m <= nmax; m++ ) { /* double mm = m*m; */ for ( n = max_mag(m + 1, 2); n <= nmax; n++ ) { /* double root1 = sqrt((n-1)*(n-1) - mm); */ /* double root2 = 1.0 / sqrt( n*n - mm); */ P[n][m] = (P[n-1][m] * c * (2.0*n-1) - P[n-2][m] * roots[m][n][0]) * roots[m][n][1]; DP[n][m] = ((DP[n-1][m] * c - P[n-1][m] * s) * (2.0*n-1) - DP[n-2][m] * roots[m][n][0]) * roots[m][n][1]; } } /* compute gnm, hnm at dat */ nmaxl = 12; /* models except IGRF2005 */ switch(model) { case 8: /* WMM2005 */ yearfrac = (dat - yymmdd_to_julian_days(5,1,1)) / 365.25; for (n=1;n<=nmaxl;n++) for (m = 0;m<=nmaxl;m++) { gnm[n][m] = gnm_wmm2005[n][m] + yearfrac * gtnm_wmm2005[n][m]; hnm[n][m] = hnm_wmm2005[n][m] + yearfrac * htnm_wmm2005[n][m]; } break; case 9: /* IGRF2005 */ yearfrac = (dat - yymmdd_to_julian_days(5,1,1)) / 365.25; nmaxl = 13; for (n=1;n<=nmaxl;n++) for (m = 0;m<=nmaxl;m++) { gnm[n][m] = gnm_igrf2005[n][m] + yearfrac * gtnm_igrf2005[n][m]; hnm[n][m] = hnm_igrf2005[n][m] + yearfrac * htnm_igrf2005[n][m]; } break; } /* compute sm (sin(m lon) and cm (cos(m lon)) */ for (m = 0;m<=nmaxl;m++) { sm[m] = sin(m * lon); cm[m] = cos(m * lon); } /* compute B fields */ B_r = 0.0; B_theta = 0.0; B_phi = 0.0; fn_0 = r_0/r; fn = fn_0 * fn_0; for ( n = 1; n <= nmaxl; n++ ) { c1_n=0; c2_n=0; c3_n=0; for ( m = 0; m <= n; m++ ) { tmp = (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]); c1_n += tmp * P[n][m]; c2_n += tmp * DP[n][m]; c3_n += m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m]; } /* fn=pow(r_0/r,n+2.0); */ fn *= fn_0; B_r += (n + 1) * c1_n * fn; B_theta -= c2_n * fn; B_phi += c3_n * fn * inv_s; } /* Find geodetic field components: */ psi = theta - (pi / 2.0 - lat); sinpsi = sin(psi); cospsi = cos(psi); X = -B_theta * cospsi - B_r * sinpsi; Y = B_phi; Z = B_theta * sinpsi - B_r * cospsi; //field[0]=B_r; //field[1]=B_theta; //field[2]=B_phi; norm = sqrt(X*X + Y*Y + Z*Z); field[0]=X/norm; field[1]=Y/norm; field[2]=Z/norm; /* output fields */ /* find variation in radians */ /* return zero variation at magnetic pole X=Y=0. */ /* E is positive */ return; }