def tempB(a, h, cb, sb, cA, sA, nlon, date): """ calculate temporary magnetic field used in def lineToApex :param a: variation latitude (float, rad) :param h: variation altitude (float, km) :param cb: cos(pi/2 - north pole latitude) (float) :param sb: sin(pi/2 - north pole latitude) (float) :param cA: cos(pi - magnetic longitude) (float) :param sA: sin(pi - magnetic longitude) (float) :param nlon: north pole longitude (float, rad) :param date: years (float year) :return bz: downward magnetic field (float, nT) bb: total magnetic field (float, nT) lat: latitude for Apex point (float, rad) lon: longitude for Apex point (float, rad) """ sgn = np.sign(sA) sa = np.sin(a) ca = np.cos(a) sB = sb * sA / sa cB = np.sqrt(1 - sB * sB) cC = (sA * sB * ca * cb - cA * cB) / (1 - sb * sb * sA * sA) lon = (sgn * np.arccos(cC) + nlon) % (2 * np.pi) lat = np.pi / 2 - a bx, by, bz, bb = igrf12syn(0, date, 1, h, lat * FACT, lon * FACT) return bz, bb, lat, lon
def igrf_variation(lat, lon, alt=0., year=2005): """ Annual variation D is declination (+ve east) I is inclination (+ve down) H is horizontal intensity x is north component y is east component Z is vertical component (+ve down) F is total intensity """ x1, y1, z1, f1 = calculate.igrf12syn(year - 1, 1, alt, lat, lon) x2, y2, z2, f2 = calculate.igrf12syn(year + 1, 1, alt, lat, lon) x, y, z, f = (x1 + x2) / 2, (y1 + y2) / 2, (z1 + z2) / 2, (f1 + f2) / 2 dx, dy, dz, df = (x2 - x1) / 2, (y2 - y1) / 2, (z2 - z1) / 2, (f2 - f1) / 2 h = np.sqrt(x * x + y * y) dd = (FACT * (x * dy - y * dx)) / (h * h) dh = (x * dx + y * dy) / h ds = (FACT * (h * dz - z * dh)) / (f * f) df = (h * dh + z * dz) / f return dd, ds, dh, dx, dy, dz, df
def dipLat(lat, lon, alt, year=2005.): """ maglatitude defined as inclination with dipole model :param lat: geolatitude (float, deg) :param lon: geolongitude (float, deg) :param alt: altitude (float, km) :param year: years (float, year) :return: maglatitude (float, deg) """ mag = igrf12syn(0, year, 1, alt, lat, lon) print(mag) mlat = np.tan(mag[1] / 2 / FACT) * FACT return mlat
def igrf_value(lat, lon, alt=0., year=2005.): """ :return D is declination (+ve east) I is inclination (+ve down) H is horizontal intensity X is north component Y is east component Z is vertical component (+ve down) F is total intensity """ x, y, z, f = calculate.igrf12syn(year, 1, alt, lat, lon) d = FACT * np.arctan2(y, x) h = np.sqrt(x * x + y * y) i = FACT * np.arctan2(z, h) return d, i, h, x, y, z, f
def traceToStart(alat, alon, ha, date, sgn, hs, nlat, nlon, deltaH, tDS=1): """ :param alat: apex latitude (float, rad) :param alon: apex longitude (float, rad) :param ha: apex altitude (float, km) :param date: time (float, year) :param sgn: 1 for north, -1 for south :param hs: altitude of start point (float, km) :param nlat: latitude of north pole (float, deg) :param nlon: longitude of north pole (float, deg) :param deltaH: bias in altitude (float, km) :param tDS: 1 for using def getDS, 0 for using def getDS_old :return trace: [x, y, z] from apex to start point (list(float), km) """ ctp = np.cos(np.pi / 2 - nlat) stp = np.sin(np.pi / 2 - nlat) gccolat, plon, gcrho = geodetic2geocentric(np.pi / 2 - alat, ha) gclat, gclon = np.pi / 2 - gccolat, alon x0, y0, z0 = geocentric2cartesian(gclat, gclon, gcrho) alt = 0. trace = [] step = 0 arrive = False Y = [x0, y0, z0] YOLD = [0, 0, 0] YAPX = [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]] YP = [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]] while not arrive and step < 500: if tDS == 1: DS = getDS(ctp, stp, gcrho, gclat, gclon, nlon) else: DS = getDS_old(ctp, stp, gcrho, gclat, gclon, nlon) bx, by, bz, bb = igrf12syn(0, date, 2, gcrho, gclat * FACT, gclon * FACT) Bx, By, Bz = rotateVector([bx, by, bz], gclon, gclat) itrace(Y, YOLD, YAPX, YP, Bx, By, Bz, bb, sgn, DS, step) step += 1 gclat, gclon, gcrho = cartesian2geocentric(Y[0], Y[1], Y[2]) trace.append(Y[:]) if step >= 7: lat, alt = geocentric2geodetic(gclat, gcrho) arrive = alt < hs # interpolate to where h = hs to find cartesian coordinates at start point dot = [trace[-3], trace[-2], trace[-1]] h = [0., 0., 0.] step = 0 while abs(alt - hs) > deltaH and step < 500: if step >= 3: dot1, dot2, dot3 = dot[-3], dot[-2], dot[-1] Ax = secDegInterpolate(h[0], h[1], h[2], dot1[0], dot2[0], dot3[0], hs) Ay = secDegInterpolate(h[0], h[1], h[2], dot1[1], dot2[1], dot3[1], hs) Az = secDegInterpolate(h[0], h[1], h[2], dot1[2], dot2[2], dot3[2], hs) dot.append([Ax, Ay, Az]) gclat, gclon, gcrho = cartesian2geocentric(Ax, Ay, Az) lat, alt = geocentric2geodetic(gclat, gcrho) h = [h[1], h[2], alt] else: Ax, Ay, Az = dot[step] gclat, gclon, gcrho = cartesian2geocentric(Ax, Ay, Az) lat, talt = geocentric2geodetic(gclat, gcrho) h = [h[1], h[2], talt] step += 1 trace[-1] = dot[-1] return trace
def traceToApex(lat, lon, alt, date, nlat, nlon, tDS=1): """ Follow a geomagnetic field line until passing its apex. :param lat: latitude of start position (float deg) :param lon: longitude of start position (float deg) :param alt: altitude of start position (float deg) :param date: time (float year) :param nlat: latitude of north pole (float rad) :param nlon: longitude of north pole (float rad) :return: trace: dots of the field line(list([float, float, float]) km) """ ctp = np.cos(np.pi / 2 - nlat) stp = np.sin(np.pi / 2 - nlat) gccolat, plon, gcrho = geodetic2geocentric(np.pi / 2 - lat / FACT, alt) gclat, gclon = np.pi / 2 - gccolat, lon / FACT x0, y0, z0 = geocentric2cartesian(gclat, gclon, gcrho) bx, by, bz, bb = igrf12syn(0, date, 2, gcrho, gclat * FACT, gclon * FACT) trace = [] step = 0 sgn = -np.sign(bz) arrive = False Y = [x0, y0, z0] YOLD = [0, 0, 0] YAPX = [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]] YP = [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]] while not arrive and step < 500: # stngml = ctp*np.sin(gclat)+stp*np.cos(gclat)*np.cos(gclon-nlon) # cgml2 = max(1-stngml**2, 0.25) # DS = gcrho*0.06/cgml2-370 if tDS == 1: DS = getDS(ctp, stp, gcrho, gclat, gclon, nlon) else: DS = getDS_old(ctp, stp, gcrho, gclat, gclon, nlon) bx, by, bz, bb = igrf12syn(0, date, 2, gcrho, gclat * FACT, gclon * FACT) # lstBdown = [lstBdown[1], lstBdown[2], bz] Bx, By, Bz = rotateVector([bx, by, bz], gclon, gclat) itrace(Y, YOLD, YAPX, YP, Bx, By, Bz, bb, sgn, DS, step) step += 1 gclat, gclon, gcrho = cartesian2geocentric(Y[0], Y[1], Y[2]) trace.append(Y[:]) if step >= 7: RC = np.sqrt(YAPX[0][2]**2 + YAPX[1][2]**2 + YAPX[2][2]**2) RP = np.sqrt(YAPX[0][1]**2 + YAPX[1][1]**2 + YAPX[2][1]**2) arrive = RC < RP # print('step = '+str(step)) # interpolate to where Bdown/B < 0.00002 to find cartesian coordinates at dip equator dot = [trace[-3], trace[-2], trace[-1]] lstBdown = [0., 0., 0.] step = 0 while abs(bz / bb) > delta: if step >= 3: dot1, dot2, dot3 = dot[-3], dot[-2], dot[-1] Ax = secDegInterpolate(lstBdown[0], lstBdown[1], lstBdown[2], dot1[0], dot2[0], dot3[0], 0.) Ay = secDegInterpolate(lstBdown[0], lstBdown[1], lstBdown[2], dot1[1], dot2[1], dot3[1], 0.) Az = secDegInterpolate(lstBdown[0], lstBdown[1], lstBdown[2], dot1[2], dot2[2], dot3[2], 0.) dot.append([Ax, Ay, Az]) gclat, gclon, gcrho = cartesian2geocentric(Ax, Ay, Az) bx, by, bz, bb = igrf12syn(0, date, 2, gcrho, gclat * FACT, gclon * FACT) lstBdown = [lstBdown[1], lstBdown[2], bz] else: Ax, Ay, Az = dot[step] gclat, gclon, gcrho = cartesian2geocentric(Ax, Ay, Az) bx, by, bz, bb = igrf12syn(0, date, 2, gcrho, gclat * FACT, gclon * FACT) lstBdown = [lstBdown[1], lstBdown[2], bz] step += 1 trace[-1] = dot[-1] return trace, sgn