예제 #1
0
        public CalculationOptions(CalculationOptions other)
        {
            Latitude          = other.Latitude;
            Longitude         = other.Longitude;
            StartDate         = other.StartDate;
            EndDate           = other.EndDate;
            StepInterval      = other.StepInterval;
            SecularVariation  = other.SecularVariation;
            CalculationMethod = other.CalculationMethod;

            ElevationValue      = other.ElevationValue;
            ElevationUnit       = other.ElevationUnit;
            ElevationIsAltitude = other.ElevationIsAltitude;
        }
예제 #2
0
        /// <summary>
        /// calculate main field and field change at a 'spot' in time and space
        /// </summary>
        /// <param name="CalculationOptions">details of the time and space to for which to calculate</param>
        /// <param name="dateOfCalc">The DateTime object for the calculation date</param>
        /// <param name="magModels">the models loaded by the Model Reader</param>
        /// <param name="internalSH">internal coeffiecients for a particular date</param>
        /// <param name="externalSH">external coeffiecients for a particular date</param>
        /// <param name="earthRadius">Optional: Radius of the earth used by the model</param>
        /// <returns>The result of the magnetic calculation</returns>
        public static MagneticCalculations SpotCalculation(CalculationOptions CalculationOptions, DateTime dateOfCalc, MagneticModelSet magModels,
                                                           Coefficients internalSH, Coefficients externalSH, double earthRadius = Constants.EarthsRadiusInKm)
        {
            /* call procedure GETFIELD - values returned in geomagfield*/
            var fieldCalculations = GetField(CalculationOptions, internalSH, externalSH, earthRadius);

            GeoMagVector svCalculations = null;

            if (CalculationOptions.SecularVariation)
            {
                double date1 = -1;
                double date2 = -1;

                CalculateDatesForVariation(CalculationOptions.StartDate.ToDecimal(), magModels.MinDate, magModels.MaxDate, out date1, out date2);

                /* get coefficients and field for date1 */
                var SVintSH = new Coefficients();
                var SVextSH = new Coefficients();

                magModels.GetIntExt(date1, out SVintSH, out SVextSH);

                var geomagfield1 = GetField(CalculationOptions, SVintSH, SVextSH, earthRadius);

                /* get coefficients and field for date2 */

                magModels.GetIntExt(date2, out SVintSH, out SVextSH);

                var geomagfield2 = GetField(CalculationOptions, SVintSH, SVextSH, earthRadius);

                /* calculate changes - difference between
                 * fields 1 & 2 returned in fielddiffs */

                svCalculations = geomagfield2.Subtract(geomagfield1);
            } /* end of secular variation calc. for SPOT */

            return(new MagneticCalculations(dateOfCalc, fieldCalculations, svCalculations));
        }
예제 #3
0
        public void MagneticCalculations(CalculationOptions inCalculationOptions)
        {
            _CalculationOptions  = null;
            ResultsOfCalculation = null;

            if (_Models == null || _Models.NumberOfModels.Equals(0))
            {
                throw new GeoMagExceptionModelNotLoaded("Error: No models avaliable for calculation");
            }

            if (!_Models.IsDateInRange(inCalculationOptions.StartDate))
            {
                throw new GeoMagExceptionOutOfRange(string.Format("Error: the date {0} is out of range for this model{1}The valid date range for the is {2} to {3}",
                                                                  inCalculationOptions.StartDate.ToShortDateString(), Environment.NewLine, _Models.MinDate.ToDateTime().ToShortDateString(),
                                                                  _Models.MaxDate.ToDateTime().ToShortDateString()));
            }

            if (inCalculationOptions.EndDate.Equals(DateTime.MinValue))
            {
                inCalculationOptions.EndDate = inCalculationOptions.StartDate;
            }

            if (!_Models.IsDateInRange(inCalculationOptions.EndDate))
            {
                throw new GeoMagExceptionOutOfRange(string.Format("Error: the date {0} is out of range for this model{1}The valid date range for the is {2} to {3}",
                                                                  inCalculationOptions.EndDate.ToShortDateString(), Environment.NewLine, _Models.MinDate.ToDateTime().ToShortDateString(),
                                                                  _Models.MaxDate.ToDateTime().ToShortDateString()));
            }

            TimeSpan timespan = (inCalculationOptions.EndDate.Date - inCalculationOptions.StartDate.Date);

            double dayInc = inCalculationOptions.StepInterval < 1 ? 1 : inCalculationOptions.StepInterval;

            double dateIdx = 0;

            ResultsOfCalculation = new List <MagneticCalculations>();

            _CalculationOptions = new CalculationOptions(inCalculationOptions);

            while (dateIdx <= timespan.Days)
            {
                var internalSH = new Coefficients();

                var externalSH = new Coefficients();

                DateTime intervalDate = _CalculationOptions.StartDate.AddDays(dateIdx);

                _Models.GetIntExt(intervalDate.ToDecimal(), out internalSH, out externalSH);

                var magCalcDate = Calculator.SpotCalculation(_CalculationOptions, intervalDate, _Models, internalSH, externalSH, _Models.EarthRadius);

                if (magCalcDate != null)
                {
                    ResultsOfCalculation.Add(magCalcDate);
                }

                dateIdx = ((dateIdx < timespan.Days) && ((dateIdx + dayInc) > timespan.Days))
                            ? timespan.Days
                            : dateIdx + dayInc;
            }
        }
예제 #4
0
        private static GeoMagVector GetField(CalculationOptions CalculationOptions, Coefficients internalSH, Coefficients externalSH, double er_rad)
        {
            /* allocate storage for arrays */
            Int32 kmx   = (internalSH.MaxDegree + 1) * (internalSH.MaxDegree + 2) / 2;
            Int32 isize = internalSH.MaxDegree * (internalSH.MaxDegree + 2);
            Int32 esize = externalSH.MaxDegree * (externalSH.MaxDegree + 2);
            Int32 nagh  = isize + esize;

            var agh = new double[nagh];
            var zmn = new double[2 * isize];
            var xmn = new double[2 * isize];
            var ymn = new double[2 * isize];

            var cl = new double[isize];
            var sl = new double[isize];

            var p = new double[kmx];
            var q = new double[kmx];

            /* set values of agh */

            for (Int32 aghIdx = 0; aghIdx < nagh; aghIdx++)
            {
                if (aghIdx < isize)
                {
                    agh[aghIdx] = internalSH.coeffs[aghIdx];
                }
                else
                {
                    agh[aghIdx] = externalSH.coeffs[aghIdx - isize];
                }
            } /* end of setting agh */

            double altitude = CalculationOptions.AltitudeInKm;

            double gcCoLat     = 0;
            double earthRadius = 0;
            double cd          = 0;
            double sd          = 0;

            GeodeticToGeocentric(CalculationOptions.CoLatitude, altitude, out gcCoLat, out earthRadius, out cd, out sd);
            double one = gcCoLat;

            double slat = Math.Cos(one.ToRadian());
            double clat = Math.Sin(one.ToRadian());

            one   = CalculationOptions.Longitude;
            cl[0] = (Math.Cos(one.ToRadian()));
            sl[0] = (Math.Sin(one.ToRadian()));

            var geomagfield = new GeoMagVector();

            /* printf("GETFIELD 2: %lf %lf %lf %lf\n", slat, clat, cl[0],sl[0]); */

            /****Computation of the spherical harmonics using
             * Schmidt quasi-normal Legendre polynomials p and q  **/

            Int32 li = 0;
            Int32 le = isize;
            Int32 m  = 0;
            Int32 n  = -1;

            /* reference radius */
            double ratio = er_rad / earthRadius;
            double rri   = ratio * ratio;
            double rre   = ratio;

            p[0] = 1.0;
            p[2] = clat;
            q[0] = 0.0;
            q[2] = slat;

            double fn    = 0;
            double gn    = 0;
            double fm    = 0;
            double two   = 0;
            double three = 0;

            Int32 i = 0;
            Int32 j = 0;


            for (Int32 k = 1; k < kmx; k++, m++)
            {
                if (n < m)
                {
                    m = -1;
                    n++;
                    rri = rri * ratio;
                    rre = rre / ratio;
                    fn  = n + 1;
                    gn  = n;
                }
                fm = m + 1;
                if (n != m)
                {
                    /** block 3 **/
                    one   = Math.Sqrt(fn * fn - fm * fm);
                    two   = Math.Sqrt(gn * gn - fm * fm) / one;
                    three = (fn + gn) / one;
                    i     = k - n - 1;
                    j     = k - 2 * (n + 1) + 1;
                    p[k]  = three * slat * p[i] - two * p[j];
                    q[k]  = three * (slat * q[i] - clat * p[i]) - two * q[j];
                }
                else if (k != 2)
                {
                    /** block 2 **/
                    one   = Math.Sqrt(1.0 - 0.5 / fm);
                    j     = k - n - 2;
                    p[k]  = one * clat * p[j];
                    q[k]  = one * (clat * q[j] + slat * p[j]);
                    sl[m] = sl[m - 1] * cl[0] + cl[m - 1] * sl[0];
                    cl[m] = cl[m - 1] * cl[0] - sl[m - 1] * sl[0];
                }

                if (m < 0)
                {
                    /** block 4 **/
                    zmn[li] = -(fn + 1.0) * p[k] * rri;
                    zmn[le] = fn * p[k] * rre;
                    xmn[li] = q[k] * rri;
                    ymn[li] = 0.0;
                    xmn[le] = q[k] * rre;
                    ymn[le] = 0.0;
                    li++;
                    le++;
                }
                else
                {     /* m >= 0 */
                    /**block 5**/
                    zmn[li] = -(fn + 1.0) * p[k] * rri * cl[m];
                    xmn[li] = q[k] * rri * cl[m];
                    zmn[le] = fn * p[k] * rre * cl[m];
                    xmn[le] = q[k] * rre * cl[m];

                    if (clat != 0)
                    {
                        ymn[li] = fm * p[k] / clat * rri * sl[m];
                        ymn[le] = fm * p[k] / clat * rre * sl[m];
                    }
                    else
                    {
                        ymn[li] = q[k] * slat * rri * sl[m];
                        ymn[le] = q[k] * slat * rre * sl[m];
                    }

                    /**block 8 **/
                    li++;
                    le++;
                    zmn[li] = -(fn + 1.0) * p[k] * rri * sl[m];
                    xmn[li] = q[k] * rri * sl[m];
                    zmn[le] = fn * p[k] * rre * sl[m];
                    xmn[le] = q[k] * rre * sl[m];

                    if (clat != 0)
                    {
                        ymn[li] = -fm * p[k] / clat * rri * cl[m];
                        ymn[le] = -fm * p[k] / clat * rre * cl[m];
                    }
                    else
                    {
                        ymn[li] = -q[k] * slat * rri * cl[m];
                        ymn[le] = -q[k] * slat * rre * cl[m];
                    }

                    /** block 10 **/
                    li++;
                    le++;
                } /* end of if statement for m<=0 */
            }     /* end of for loop */

            for (i = 0; i < 2 * isize; i++)
            {
                if (i >= nagh)
                {
                    xmn[i] = 0.0;
                    ymn[i] = 0.0;
                    zmn[i] = 0.0;
                }
                else
                {
                    geomagfield.x += xmn[i] * agh[i];
                    geomagfield.y += ymn[i] * agh[i];
                    geomagfield.z += zmn[i] * agh[i];
                }
            } /* end of for loop assigning geomagfield */

            /* convert x and z into geodetic coordinate system */
            one           = geomagfield.x;
            geomagfield.x = (geomagfield.x) * cd + (geomagfield.z) * sd;
            geomagfield.z = (geomagfield.z) * cd - one * sd;

            /* compute remaining elements */
            geomagfield.d = Math.Atan2(geomagfield.y, geomagfield.x).ToDegree();
            geomagfield.h = Math.Sqrt(geomagfield.x * geomagfield.x + geomagfield.y * geomagfield.y);
            geomagfield.s = Math.Atan2(geomagfield.z, geomagfield.h).ToDegree();
            geomagfield.f = Math.Sqrt(geomagfield.x * geomagfield.x + geomagfield.y * geomagfield.y + geomagfield.z * geomagfield.z);

            return(geomagfield);
        }