Ejemplo n.º 1
0
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);

}
Ejemplo n.º 2
0
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; 
}