def tt89(pos_var_gsm, iopt=3, suffix='', igrf_only=False): """ tplot wrapper for the functional interface to Sheng Tian's implementation of the Tsyganenko 96 and IGRF model: https://github.com/tsssss/geopack Input ------ pos_gsm_tvar: str tplot variable containing the position data (km) in GSM coordinates Parameters ----------- iopt: int Specifies the ground disturbance level: iopt= 1 2 3 4 5 6 7 correspond to: kp= 0,0+ 1-,1,1+ 2-,2,2+ 3-,3,3+ 4-,4,4+ 5-,5,5+ > =6- suffix: str Suffix to append to the tplot output variable Returns -------- Name of the tplot variable containing the model data """ pos_data = get_data(pos_var_gsm) if pos_data is None: print('Variable not found: ' + pos_var_gsm) return b0gsm = np.zeros((len(pos_data.times), 3)) dbgsm = np.zeros((len(pos_data.times), 3)) # convert to Re pos_re = pos_data.y/6371.2 for idx, time in enumerate(pos_data.times): tilt = geopack.recalc(time) # dipole B in GSM b0gsm[idx, 0], b0gsm[idx, 1], b0gsm[idx, 2] = geopack.dip(pos_re[idx, 0], pos_re[idx, 1], pos_re[idx, 2]) # T89 dB in GSM dbgsm[idx, 0], dbgsm[idx, 1], dbgsm[idx, 2] = t89.t89(iopt, tilt, pos_re[idx, 0], pos_re[idx, 1], pos_re[idx, 2]) if igrf_only: bgsm = b0gsm else: bgsm = b0gsm + dbgsm saved = store_data(pos_var_gsm + '_bt89' + suffix, data={'x': pos_data.times, 'y': bgsm}) if saved: return pos_var_gsm + '_bt89' + suffix
def b(self, xvec): # x,y,z can be an array or list try: x, y, z = xvec except: x, y, z = xvec.T # we need to call recalc since common block may be shared between instances # of geopack-2008 and T89,T96,T01,T04 self.ps = geopack.recalc(self.dt_seconds) x = np.array([x]) y = np.array([y]) z = np.array([z]) x = x.flatten() y = y.flatten() z = z.flatten() nx = len(x) ny = len(y) nz = len(z) nn = min([nx, ny, nz]) bx_out = np.zeros(nn, dtype=float) by_out = np.zeros(nn, dtype=float) bz_out = np.zeros(nn, dtype=float) for ix in range(nn): rr = np.sqrt(x[ix]**2 + y[ix]**2 + z[ix]**2) if (rr > 0.000001): bx_, by_, bz_ = geopack.t04.t04(self.parmod, self.ps, x[ix], y[ix], z[ix]) if self.use_igrf: bx0, by0, bz0 = geopack.igrf_gsm(x[ix], y[ix], z[ix]) else: bx0, by0, bz0 = geopack.dip(x[ix], y[ix], z[ix]) bx_out[ix] = bx_ + bx0 by_out[ix] = by_ + by0 bz_out[ix] = bz_ + bz0 else: bx_out[ix] = np.nan by_out[ix] = np.nan bz_out[ix] = np.nan return (np.column_stack((bx_out, by_out, bz_out)))
def plot_field_slice(max_L): ''' Need to convert L, MLAT, MLON into a coordinate system that meshes with geopack: -- GSM (in RE) -- GSW Nah for now just plot in GSM around xy plane (z = 0) up to max_L in R_E ''' from geopack import geopack ds = 0.1 x_gsm = np.arange(-max_L, max_L, ds) y_gsm = np.arange(-max_L, max_L, ds) z_gsm = 0.0 r_lim = 3.0 B_out = np.zeros((x_gsm.shape[0], y_gsm.shape[0], 3), dtype=float) for ii in range(x_gsm.shape[0]): for jj in range(y_gsm.shape[0]): r_gsm = np.sqrt(x_gsm[ii]**2 + y_gsm[jj]**2) if r_gsm < r_lim: B_out[ii, jj] = np.ones(3) * np.nan else: B_out[ii, jj] = geopack.dip(x_gsm[ii], y_gsm[jj], z_gsm) B0 = np.sqrt(B_out[:, :, 0]**2 + B_out[:, :, 1]**2 + B_out[:, :, 2]**2) # Normalize B_out[:, :, 0] = B_out[:, :, 0] / np.sqrt(B_out[:, :, 0]**2 + B_out[:, :, 1]**2) B_out[:, :, 1] = B_out[:, :, 1] / np.sqrt(B_out[:, :, 0]**2 + B_out[:, :, 1]**2) plt.ioff() fig, ax = plt.subplots() im1 = ax.quiver(x_gsm, y_gsm, B_out[:, :, 0].T, B_out[:, :, 1].T, B0) ax.set_xlabel('X (RE, GSM)') ax.set_ylabel('Y (RE, GSM)') fig.colorbar(im1).set_label('|B| (nT)') plt.show() return x_gsm, y_gsm, B0
def tt01(pos_var_gsm, parmod=None, suffix=''): """ tplot wrapper for the functional interface to Sheng Tian's implementation of the Tsyganenko 2001 and IGRF model: https://github.com/tsssss/geopack Input ------ pos_gsm_tvar: str tplot variable containing the position data (km) in GSM coordinates Parameters ----------- parmod: ndarray 10-element array (vs. time), but only the first 6 elements are used (1) solar wind pressure pdyn (nanopascals), (2) dst (nanotesla) (3) byimf (nanotesla) (4) bzimf (nanotesla) (5) g1-index (6) g2-index (see Tsyganenko [2001] for an exact definition of these two indices) suffix: str Suffix to append to the tplot output variable Returns -------- Name of the tplot variable containing the model data """ pos_data = get_data(pos_var_gsm) if pos_data is None: print('Variable not found: ' + pos_var_gsm) return b0gsm = np.zeros((len(pos_data.times), 3)) dbgsm = np.zeros((len(pos_data.times), 3)) # convert to Re pos_re = pos_data.y/6371.2 if parmod is not None: par = get_data(parmod) if par is not None: par = par.y else: print('parmod keyword required.') return for idx, time in enumerate(pos_data.times): tilt = geopack.recalc(time) # dipole B in GSM b0gsm[idx, 0], b0gsm[idx, 1], b0gsm[idx, 2] = geopack.dip(pos_re[idx, 0], pos_re[idx, 1], pos_re[idx, 2]) # T96 dB in GSM dbgsm[idx, 0], dbgsm[idx, 1], dbgsm[idx, 2] = t01.t01(par[idx, :], tilt, pos_re[idx, 0], pos_re[idx, 1], pos_re[idx, 2]) bgsm = b0gsm + dbgsm saved = store_data(pos_var_gsm + '_bt01' + suffix, data={'x': pos_data.times, 'y': bgsm}) if saved: return pos_var_gsm + '_bt01' + suffix
def tts04(pos_var_gsm, parmod=None, suffix=''): """ tplot wrapper for the functional interface to Sheng Tian's implementation of the Tsyganenko-Sitnov (2004) storm-time geomagnetic field model https://github.com/tsssss/geopack Input ------ pos_gsm_tvar: str tplot variable containing the position data (km) in GSM coordinates Parameters ----------- parmod: ndarray 10-element array (vs. time): (1) solar wind pressure pdyn (nanopascals), (2) dst (nanotesla), (3) byimf, (4) bzimf (nanotesla) (5-10) indices w1 - w6, calculated as time integrals from the beginning of a storm see the reference (3) below, for a detailed definition of those variables suffix: str Suffix to append to the tplot output variable Returns -------- Name of the tplot variable containing the model data """ pos_data = get_data(pos_var_gsm) if pos_data is None: print('Variable not found: ' + pos_var_gsm) return b0gsm = np.zeros((len(pos_data.times), 3)) dbgsm = np.zeros((len(pos_data.times), 3)) # convert to Re pos_re = pos_data.y / 6371.2 if parmod is not None: par = get_data(parmod) if par is not None: par = par.y else: print('parmod keyword required.') return for idx, time in enumerate(pos_data.times): tilt = geopack.recalc(time) if not np.isfinite(par[idx, :]).all(): # skip if there are any NaNs in the input continue # dipole B in GSM b0gsm[idx, 0], b0gsm[idx, 1], b0gsm[idx, 2] = geopack.dip(pos_re[idx, 0], pos_re[idx, 1], pos_re[idx, 2]) # T96 dB in GSM dbgsm[idx, 0], dbgsm[idx, 1], dbgsm[idx, 2] = t04.t04(par[idx, :], tilt, pos_re[idx, 0], pos_re[idx, 1], pos_re[idx, 2]) bgsm = b0gsm + dbgsm saved = store_data(pos_var_gsm + '_bts04' + suffix, data={ 'x': pos_data.times, 'y': bgsm }) if saved: return pos_var_gsm + '_bts04' + suffix
def test_to_known_values(self): """geopack should give known result with known input""" # test recalc, which returns dipole tilt angle in rad. self.assertEqual(self.test['recalc'], geopack.recalc(self.test['ut'], *self.test['v_gse'])) # test sun, which returns 5 angles in rad. self.assertEqual(self.test['sun'], geopack.sun(self.test['ut'])) # test internal models. self.assertTrue( approx_eq(self.test['igrf'], geopack.igrf_gsm(*self.test['r_gsm']))) self.assertTrue( approx_eq(self.test['dip'], geopack.dip(*self.test['r_gsm']))) self.assertTrue( approx_eq(self.test['igrf_gsw'], geopack.igrf_gsw(*self.test['r_gsw']), 1e-3)) self.assertTrue( approx_eq(self.test['dip_gsw'], geopack.dip_gsw(*self.test['r_gsw']), 1e-3)) # test external models. self.assertTrue( approx_eq(self.test['t89'], t89.t89(*self.test['par1']))) self.assertTrue( approx_eq(self.test['t96'], t96.t96(*self.test['par2']))) self.assertTrue( approx_eq(self.test['t01'], t01.t01(*self.test['par2']))) self.assertTrue( approx_eq(self.test['t04'], t04.t04(*self.test['par2']))) # test coord transform, which returns B in nT. self.assertTrue( approx_eq(self.test['r_mag'], geopack.geomag(*self.test['r_geo'], 1))) self.assertTrue( approx_eq(self.test['r_geo'], geopack.geomag(*self.test['r_mag'], -1))) self.assertTrue( approx_eq(self.test['r_geo'], geopack.geigeo(*self.test['r_gei'], 1))) self.assertTrue( approx_eq(self.test['r_gei'], geopack.geigeo(*self.test['r_geo'], -1))) self.assertTrue( approx_eq(self.test['r_sm'], geopack.magsm(*self.test['r_mag'], 1))) self.assertTrue( approx_eq(self.test['r_mag'], geopack.magsm(*self.test['r_sm'], -1))) self.assertTrue( approx_eq(self.test['r_gse'], geopack.gsmgse(*self.test['r_gsm'], 1))) self.assertTrue( approx_eq(self.test['r_gsm'], geopack.gsmgse(*self.test['r_gse'], -1))) self.assertTrue( approx_eq(self.test['r_gsm'], geopack.smgsm(*self.test['r_sm'], 1))) self.assertTrue( approx_eq(self.test['r_sm'], geopack.smgsm(*self.test['r_gsm'], -1))) self.assertTrue( approx_eq(self.test['r_gsm'], geopack.geogsm(*self.test['r_geo'], 1))) self.assertTrue( approx_eq(self.test['r_geo'], geopack.geogsm(*self.test['r_gsm'], -1))) self.assertTrue( approx_eq(self.test['r_gsw'], geopack.gswgsm(*self.test['r_gsm'], -1))) self.assertTrue( approx_eq(self.test['r_gsm'], geopack.gswgsm(*self.test['r_gsw'], 1))) self.assertTrue( approx_eq(self.test['geo'], geopack.geodgeo(*self.test['geod'], 1), 1e-3)) self.assertTrue( approx_eq(self.test['geod2'], geopack.geodgeo(*self.test['geo2'], -1), 1e-3)) # test trace. self.assertTrue( approx_eq( self.test['trace_t89_igrf'], geopack.trace(*self.test['r_gsm'], *self.test['trace_setting'], self.test['par1'][0], 't89', 'igrf'))) self.assertTrue( approx_eq( self.test['trace_t96_igrf'], geopack.trace(*self.test['r_gsm'], *self.test['trace_setting'], self.test['par2'][0], 't96', 'igrf'))) self.assertTrue( approx_eq( self.test['trace_t01_igrf'], geopack.trace(*self.test['r_gsm'], *self.test['trace_setting'], self.test['par2'][0], 't01', 'igrf'))) self.assertTrue( approx_eq( self.test['trace_t04_igrf'], geopack.trace(*self.test['r_gsm'], *self.test['trace_setting'], self.test['par2'][0], 't04', 'igrf'))) # test magnetopaus model. self.assertTrue( approx_eq( self.test['mgnp_t96'], geopack.t96_mgnp(*self.test['mgnp_t96_par'], *self.test['r_gsm']))) self.assertTrue( approx_eq( self.test['mgnp_shu'], geopack.shuetal_mgnp(*self.test['mgnp_shu_par'], *self.test['r_gsm'])))