def trace_drift_shell(self,sm_loc,t_loc,Ech,sinA_loc,sim_dt,verbose=True,Vdip_inj=None): # This function is an improve version of trace_drift, it accept coordinates in SM as a vector # And the time as datetime parameter # Input parameters # 1- Date and time of the injection #-------------------------------------------------------------------------------# #_date = self.date _imod = self.imod # magnetic field model: 0=dipole, 1=T96_01, 2=T01_1, 3=T04_s _ipot = self.ipot # electric field model: 1=Weimer, 2=CIMI _itrace = self.itrace # 1=forward, -1=backward tracing #_tsec0 = self.tsec # initial time in second #_tend = self.tend # end time in second #_ro = self.ro # initial radial distance in RE #_mlt = self.mlt # initial mlt in hour _ekev0 = Ech # initial energy in keV _ion= self.ion # 1=ion, -1=electron _tf = self.tf # time resolution in seconds in updating omni parameters #-------------------------------------------------------------------------------# ### Main trace_drift subroutine pi=np.pi dra=_itrace*0.5*pi/180. # drift path tracing step size in radian iprint=1 # print result every iprint steps re=6.371e6 # Earth's radius (m) if (_ion == 1): Eo=9.38269e5 # proton rest energy if (_ion == -1): Eo=511. # electron rest energy Eo2=Eo*Eo pc_sq=(_ekev0+Eo)**2-Eo2 # (pc)^2 in keV^2 latmax=72.*pi/180. # max allowable latitude at the ionosphere reqmax=10. # max allowable equatorial distance istepmax=3000 # max allowable istep rc=1. #Find dipole moment iyear = t_loc.year dts = spt.Ticktock(t_loc) iday = dts.DOY tsec0_dt = t_loc parmod,nsw,vxgse,vygse,vzgse = self.TsyParmod(tsec0_dt,_imod)# vy and vz are 0 to ensure GSM coordinate system tsygFort.recalc_08(iyear,iday,tsec0_dt.hour,tsec0_dt.minute,tsec0_dt.second,vxgse,vygse,vzgse) GGG=tsygFort.geopack2.g HHH=tsygFort.geopack2.h DIPMOM=np.sqrt(GGG[1]**2+GGG[2]**2+HHH[2]**2) # DIPMOM in (nT RE^3) xme=DIPMOM*re**3*1.e-9 # dipole moment in (T m^3) #xme = np.exp(36.58626097) # Find the initial ionospheric projection (along field line) point #phi=_mlt*pi/12. #xeq=-_ro*np.cos(phi) # +x --> Sun #yeq=-_ro*np.sin(phi) #zeq=0. lati,mlti = self.mapping(_imod,parmod,sm_loc[0],sm_loc[1],sm_loc[2],0,0,1) x0 = np.zeros(2) x0[0]=lati # latitude in radian x0[1]=mlti # local time in radian xeq,yeq,zeq,iout=self.mapping(_imod,parmod,0,0,0,x0[0],x0[1],-1) # find Bmag, sinA at the initial position and the invariant pcy2B bx,by,bz,Bmag=self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) # find B at magnetic equator bx,by,bz,Bloc=self.Tsy_w_dip(_imod,parmod,sm_loc[0],sm_loc[1],sm_loc[2]) # find B at local position _sinA=np.sqrt(Bmag/Bloc*sinA_loc*sinA_loc) # Pitch angle at the magnetic equator if _sinA > 1: _sinA = 1 print('Warning: B at the equator > B loc, possible orbit bifurcation. Temp solution make sin(PA)=1') #ipdb.set_trace() if (np.arcsin(_sinA) >= 80/180*pi): # if PA > 80 we consider as 90 degrees. print('Warning: real PA is %4.2f, as it is > 80 we assume 90' %(np.arcsin(_sinA)*180/pi) ) _sinA = 1 self.pcy2B=pc_sq*_sinA*_sinA/Bmag # First invariant, Bmag = B at equator self.K = 0. else: self.pcy2B=pc_sq*_sinA*_sinA/Bmag # First invariant, Bmag = B at equator self.K = self.KofAlpha(np.arcsin(_sinA),lati,mlti,_imod,parmod) # Second invariant K # Print the initial condition #ipdb.set_trace() pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(lati))**2 mlti_d=mlti*12./pi # mlt at ionosphere in hour ro_loc=np.sqrt(sm_loc[0]*sm_loc[0]+sm_loc[1]*sm_loc[1]+sm_loc[2]*sm_loc[2]) phi=np.arctan2(sm_loc[1],sm_loc[0]) mlt_loc=phi*12./pi+12. print('Info: the first line show Ro local and mlt local, i.e at the pos of the S/C and not at the equator') print('%i %i %i %i %i %4.2f ! iyear,iday,imod,ipot,ion,tf' %(iyear,iday,_imod,_ipot,_ion,_tf)) print(' tsec Dst Lshell mlti ro mlto ekeV PA Vsw Pdyn') print('%s %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f' %(tsec0_dt.isoformat()\ ,parmod[1],Lshell,mlti_d,ro_loc,mlt_loc,_ekev0,pitchA)) #ipdb.set_trace() # Start drift path tracing epoch = dt.datetime(1970,1,1) _tend=(tsec0_dt-epoch).total_seconds() + _itrace*sim_dt # UTC seconds since epoch time tsec=(tsec0_dt-epoch).total_seconds() # UTC seconds since epoch time istep=0 iexit=0 lastprint=0 iexit=0 vswi=vxgse xnswi = nsw Dst0 = parmod[1] xeq0=0;yeq0=0;zeq0=0 ## roarr=np.zeros(istepmax) mltoarr=np.zeros(istepmax) #tsecarr=np.zeros(istepmax) tsecarr = [] Eoarr = np.zeros(istepmax) pitchAarr = np.zeros(istepmax) if Vdip_inj!=None: #ipdb.set_trace() vdip = self.Vdip_i(Vdip_inj,_imod,parmod) ## Added May 25, simulate injection else: vdip = 0 ## Start debugging while (iexit != 1): #ipdb.set_trace() xend,dtsec=self.rk4(_imod,_ipot,parmod,vswi,xnswi,_ion,dra,Eo,xme,x0,_sinA,veldip=vdip) if (np.arcsin(_sinA) < 80/180*pi): _Alpha,_Bmag = self.AlphaOfK(self.K,xend[0],xend[1],_imod,parmod) _sinA = np.sin(_Alpha) else: _sinA = 1 # update istep, tsec, Bmag istep=istep+1 tsec=tsec+dtsec xeq,yeq,zeq,iout=self.mapping(_imod,parmod,0,0,0,xend[0],xend[1],-1) req=np.sqrt(xeq*xeq+yeq*yeq) # test for exit or continue if (istep==istepmax): iexit=1 if (iout==1): iexit=1 if (xend[0]>=latmax): iexit=1 print('Warning: xend[0]>=latmax') if (req>=reqmax): iexit=1 if ((_itrace==1) and (tsec>=_tend)): iexit=1 if ((_itrace==-1) and (tsec<=_tend)): iexit=1 # Reasign values if iexit.eq.1 if (iexit==1): #ipdb.set_trace() tsec=tsec-dtsec xend=x0 parmod[1]=Dst0 xeq=xeq0 yeq=yeq0 zeq=zeq0 req=np.sqrt(xeq*xeq+yeq*yeq) if (tsec>=tprint): lastprint=1 # print result every iprint step and at the end of the trace if ((np.mod(istep,iprint)==0) or (lastprint==1)): bx,by,bz,Bmag = self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) #ipdb.set_trace() pc_sq=self.pcy2B*Bmag/_sinA/_sinA ekev=np.sqrt(pc_sq+Eo2)-Eo pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(xend[0]))**2 mlti_d=xend[1]*12./pi ## mlt at ionosphere in hour phi=np.arctan2(yeq,xeq) mlteq=phi*12./pi+12. tprint=tsec roarr[istep-1]=req ## variables for ploting mltoarr[istep-1]=mlteq #tsecarr[istep-1]= tsec tsecarr.append(epoch + timedelta(seconds=tsec)) Eoarr[istep-1]=ekev pitchAarr[istep-1] = pitchA if verbose == True: print('%s %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f %7.2f %6.4f'\ %(tsecarr[istep-1].isoformat(),parmod[1],Lshell,mlti_d,req,mlteq,ekev,pitchA,vswi,parmod[0])) # Save values Dst0=parmod[1] xeq0=xeq yeq0=yeq zeq0=zeq # Update x0 and Tsyganenko parmod x0=xend if istep==1: dstep = int(_tf/dtsec) # choose an aproximate dt step for changing SW parameters if np.mod(istep,dstep)==0: parmod,xnswi,vswi,vygse,vzgse = self.TsyParmod(tsecarr[istep-1],_imod) return tsecarr,mltoarr,roarr,Eoarr,pitchAarr,istep
def trace(self, lat=None, lon=None, rho=None, coords=None, datetime=None, vswgse=None, pdyn=None, dst=None, byimf=None, bzimf=None, lmax=5000, rmax=60., rmin=1., dsmax=0.01, err=0.000001): """See tsygTrace for a description of each parameter Any unspecified parameter default to the one stored in the object Unspecified lmax, rmax, rmin, dsmax, err has a set default value Parameters ---------- lat : Optional[ ] latitude [degrees] lon : Optional[ ] longitude [degrees] rho : Optional[ ] distance from center of the Earth [km] coords : Optional[str] coordinates used for start point ['geo'] datetime : Optional[datetime] a python datetime object vswgse : Optional[list, float] solar wind velocity in GSE coordinates [m/s, m/s, m/s] pdyn : Optional[float] solar wind dynamic pressure [nPa] dst : Optional[flaot] Dst index [nT] byimf : Optional[float] IMF By [nT] bzimf : Optional[float] IMF Bz [nT] lmax : Optional[int] maximum number of points to trace rmax : Optional[float] upper trace boundary in Re rmin : Optional[float] lower trace boundary in Re dsmax : Optional[float] maximum tracing step size err : Optional[float] tracing step tolerance Written by Sebastien 2012-10 """ from numpy import radians, degrees, zeros # Store existing values of class attributes in case something is wrong # and we need to revert back to them if lat: _lat = self.lat if lon: _lon = self.lon if rho: _rho = self.rho if coords: _coords = self.coords if vswgse: _vswgse = self.vswgse if not datetime is None: _datetime = self.datetime # Pass position if new if lat: self.lat = lat lat = self.lat if lon: self.lon = lon lon = self.lon if rho: self.rho = rho rho = self.rho if not datetime is None: self.datetime = datetime datetime = self.datetime # Set necessary parameters if new if coords: self.coords = coords coords = self.coords if not datetime is None: self.datetime = datetime datetime = self.datetime if vswgse: self.vswgse = vswgse vswgse = self.vswgse if pdyn: self.pdyn = pdyn pdyn = self.pdyn if dst: self.dst = dst dst = self.dst if byimf: self.byimf = byimf byimf = self.byimf if bzimf: self.bzimf = bzimf bzimf = self.bzimf # Test that everything is in order, if not revert to existing values iTest = self.__test_valid__() if not iTest: if lat: self.lat = _lat if lon: _self.lon = lon if rho: self.rho = _rho if coords: self.coords = _coords if vswgse: self.vswgse = _vswgse if not datetime is None: self.datetime = _datetime # Declare the same Re as used in Tsyganenko models [km] Re = 6371.2 # Initialize trace array self.l = zeros(len(lat)) self.xTrace = zeros((len(lat), 2 * lmax)) self.yTrace = self.xTrace.copy() self.zTrace = self.xTrace.copy() self.xGsw = self.l.copy() self.yGsw = self.l.copy() self.zGsw = self.l.copy() self.latNH = self.l.copy() self.lonNH = self.l.copy() self.rhoNH = self.l.copy() self.latSH = self.l.copy() self.lonSH = self.l.copy() self.rhoSH = self.l.copy() # And now iterate through the desired points for ip in xrange(len(lat)): # This has to be called first tsygFort.recalc_08(datetime[ip].year, datetime[ip].timetuple().tm_yday, datetime[ip].hour, datetime[ip].minute, datetime[ip].second, vswgse[0], vswgse[1], vswgse[2]) # Convert lat,lon to geographic cartesian and then gsw r, theta, phi, xgeo, ygeo, zgeo = tsygFort.sphcar_08( rho[ip] / Re, radians(90. - lat[ip]), radians(lon[ip]), 0., 0., 0., 1) if coords.lower() == 'geo': xgeo, ygeo, zgeo, xgsw, ygsw, zgsw = tsygFort.geogsw_08( xgeo, ygeo, zgeo, 0., 0., 0., 1) self.xGsw[ip] = xgsw self.yGsw[ip] = ygsw self.zGsw[ip] = zgsw # Trace field line inmod = 'IGRF_GSW_08' exmod = 'T96_01' parmod = [pdyn, dst, byimf, bzimf, 0, 0, 0, 0, 0, 0] # First towards southern hemisphere maptoL = [-1, 1] for mapto in maptoL: xfgsw, yfgsw, zfgsw, xarr, yarr, zarr, l = tsygFort.trace_08( xgsw, ygsw, zgsw, mapto, dsmax, err, rmax, rmin, 0, parmod, exmod, inmod, lmax) # Convert back to spherical geographic coords xfgeo, yfgeo, zfgeo, xfgsw, yfgsw, zfgsw = tsygFort.geogsw_08( 0., 0., 0., xfgsw, yfgsw, zfgsw, -1) geoR, geoColat, geoLon, xgeo, ygeo, zgeo = tsygFort.sphcar_08( 0., 0., 0., xfgeo, yfgeo, zfgeo, -1) # Get coordinates of traced point if mapto == 1: self.latSH[ip] = 90. - degrees(geoColat) self.lonSH[ip] = degrees(geoLon) self.rhoSH[ip] = geoR * Re elif mapto == -1: self.latNH[ip] = 90. - degrees(geoColat) self.lonNH[ip] = degrees(geoLon) self.rhoNH[ip] = geoR * Re # Store trace if mapto == -1: self.xTrace[ip, 0:l] = xarr[l - 1::-1] self.yTrace[ip, 0:l] = yarr[l - 1::-1] self.zTrace[ip, 0:l] = zarr[l - 1::-1] elif mapto == 1: ind = int(self.l[ip]) self.xTrace[ip, ind:ind + l] = xarr[0:l] self.yTrace[ip, ind:ind + l] = yarr[0:l] self.zTrace[ip, ind:ind + l] = zarr[0:l] self.l[ip] += l # Resize trace output to more minimum possible length ind = int(self.l.max()) self.xTrace = self.xTrace[:, 0:ind] self.yTrace = self.yTrace[:, 0:ind] self.zTrace = self.zTrace[:, 0:ind]
def trace_drift(self): # Input parameters # 1- Date and time of the injection #-------------------------------------------------------------------------------# _date = self.date _imod = self.imod # magnetic field model: 0=dipole, 1=T96_01, 2=T01_1, 3=T04_s _ipot = self.ipot # electric field model: 1=Weimer, 2=CIMI _itrace = self.itrace # 1=forward, -1=backward tracing _tsec0 = self.tsec # initial time in second _tend = self.tend # end time in second _ro = self.ro # initial radial distance in RE _mlt = self.mlt # initial mlt in hour _ekev0 = self.ekev0 # initial energy in keV _Kin = 0 # K index, 0=equatorially mirroring (reserved, not used now) _ion= self.ion # 1=ion, -1=electron _tf = self.tf # time resolution in seconds in updating omni parameters #-------------------------------------------------------------------------------# ### Main trace_drift subroutine pi=np.pi dra=_itrace*0.5*pi/180. # drift path tracing step size in radian iprint=1 # print result every iprint steps re=6.371e6 # earth's radius (m) if (_ion == 1): Eo=9.38269e5 # proton rest energy if (_ion == -1): Eo=511. # electron rest energy Eo2=Eo*Eo pc_sq=(_ekev0+Eo)**2-Eo2 # (pc)^2 in keV^2 latmax=72.*pi/180. # max allowable latitude at the ionosphere reqmax=10. # max allowable equatorial distance istepmax=3000 # max allowable istep rc=1. #Find dipole moment iyear = _date.year dts = spt.Ticktock(_date) iday = dts.DOY tsec0_dt = _date+timedelta(seconds=_tsec0) parmod,nsw,vxgse,vygse,vzgse = self.TsyParmod(_date+timedelta(seconds=_tsec0),_imod)# vy and vz are 0 to ensure GSM coordinate system tsygFort.recalc_08(iyear,iday,tsec0_dt.hour,tsec0_dt.minute,tsec0_dt.second,vxgse,vygse,vzgse) GGG=tsygFort.geopack2.g HHH=tsygFort.geopack2.h DIPMOM=np.sqrt(GGG[1]**2+GGG[2]**2+HHH[2]**2) # DIPMOM in (nT RE^3) xme=DIPMOM*re**3*1.e-9 # dipole moment in (T m^3) #xme = np.exp(36.58626097) # Find the initial ionospheric projection (along field line) point phi=_mlt*pi/12. xeq=-_ro*np.cos(phi) # +x --> Sun yeq=-_ro*np.sin(phi) zeq=0. lati,mlti = self.mapping(_imod,parmod,xeq,yeq,zeq,0,0,1) x0 = np.zeros(2) x0[0]=lati # latitude in radian x0[1]=mlti # local time in radian # find Bmag, sinA at the initial position and the invariant pcy2B bx,by,bz,Bmag=self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) _sinA=self.sinA #ipdb.set_trace() self.pcy2B=pc_sq*_sinA*_sinA/Bmag # First invariant, Bmag = B at equator self.K = self.KofAlpha(np.arcsin(_sinA),lati,mlti,_imod,parmod) # Second invariant K # Print the initial condition pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(lati))**2 mlti_d=mlti*12./pi # mlt at ionosphere in hour print('%i %i %i %i %i %4.2f ! iyear,iday,imod,ipot,ion,tf' %(iyear,iday,_imod,_ipot,_ion,_tf)) print(' tsec Dst Lshell mlti ro mlto ekeV PA Vsw Pdyn') print('%6.2f %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f' %(_tsec0,parmod[1],Lshell,mlti_d,_ro,_mlt,_ekev0,pitchA)) # ipdb.set_trace() # Start drift path tracing tsec=_tsec0 istep=0 iexit=0 lastprint=0 iexit=0 vswi=vxgse xnswi = nsw Dst0 = parmod[1] xeq0=0;yeq0=0;zeq0=0 ## roarr=np.zeros(istepmax) mltoarr=np.zeros(istepmax) tsecarr=np.zeros(istepmax) Eoarr=np.zeros(istepmax) ## Start debugging while (iexit != 1): #ipdb.set_trace() xend,dtsec=self.rk4(_imod,_ipot,parmod,vswi,xnswi,_ion,dra,Eo,xme,x0,_sinA) if (_sinA!=1): _Alpha,_Bmag = self.AlphaOfK(self.K,xend[0],xend[1],_imod,parmod) _sinA = np.sin(_Alpha) # update istep, tsec, Bmag istep=istep+1 tsec=tsec+dtsec xeq,yeq,zeq,iout=self.mapping(_imod,parmod,0,0,0,xend[0],xend[1],-1) req=np.sqrt(xeq*xeq+yeq*yeq) # test for exit or continue if (istep==istepmax): iexit=1 if (iout==1): iexit=1 if (xend[0]>=latmax): iexit=1 print('Warning: xend[0]>=latmax') if (req>=reqmax): iexit=1 if ((_itrace==1) and (tsec>=_tend)): iexit=1 if ((_itrace==-1) and (tsec<=_tend)): iexit=1 # Reasign values if iexit.eq.1 if (iexit==1): #ipdb.set_trace() tsec=tsec-dtsec xend=x0 parmod[1]=Dst0 xeq=xeq0 yeq=yeq0 zeq=zeq0 req=np.sqrt(xeq*xeq+yeq*yeq) if (tsec>=tprint): lastprint=1 # print result every iprint step and at the end of the trace if ((np.mod(istep,iprint)==0) or (lastprint==1)): bx,by,bz,Bmag = self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) ipdb.set_trace() pc_sq=self.pcy2B*Bmag/_sinA/_sinA ekev=np.sqrt(pc_sq+Eo2)-Eo pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(xend[0]))**2 mlti_d=xend[1]*12./pi # mlt at ionosphere in hour phi=np.arctan2(yeq,xeq) mlteq=phi*12./pi+12. tprint=tsec print('%6.2f %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f %7.2f %6.4f'\ %(tsec,parmod[1],Lshell,mlti_d,req,mlteq,ekev,pitchA,vswi,parmod[0])) roarr[istep-1]=req ## variables for ploting mltoarr[istep-1]=mlteq tsecarr[istep-1]=tsec Eoarr[istep-1]=ekev # Save values Dst0=parmod[1] xeq0=xeq yeq0=yeq zeq0=zeq # Update x0 and Tsyganenko parmod x0=xend if istep==1: dstep = int(_tf/dtsec) # choose an aproximate dt step for changing SW parameters if np.mod(istep,dstep)==0: parmod,xnswi,vswi,vygse,vzgse = self.TsyParmod(_date+timedelta(seconds=tsec),_imod) return tsecarr,mltoarr,roarr,Eoarr,istep
def trace(self, lat=None, lon=None, rho=None, coords=None, datetime=None, vswgse=None, pdyn=None, dst=None, byimf=None, bzimf=None, lmax=5000, rmax=60., rmin=1., dsmax=0.01, err=0.000001): """ | See tsygTrace for a description of each parameter | Any unspecified parameter default to the one stored in the object | Unspecified lmax, rmax, rmin, dsmax, err has a set default value | | Written by Sebastien 2012-10 """ from numpy import radians, degrees, zeros # Store existing values of class attributes in case something is wrong # and we need to revert back to them if lat: _lat = self.lat if lon: _lon = self.lon if rho: _rho = self.rho if coords: _coords = self.coords if vswgse: _vswgse = self.vswgse if not datetime==None: _datetime = self.datetime # Pass position if new if lat: self.lat = lat lat = self.lat if lon: self.lon = lon lon = self.lon if rho: self.rho = rho rho = self.rho if not datetime==None: self.datetime = datetime datetime = self.datetime # Set necessary parameters if new if coords: self.coords = coords coords = self.coords if not datetime==None: self.datetime = datetime datetime = self.datetime if vswgse: self.vswgse = vswgse vswgse = self.vswgse if pdyn: self.pdyn = pdyn pdyn = self.pdyn if dst: self.dst = dst dst = self.dst if byimf: self.byimf = byimf byimf = self.byimf if bzimf: self.bzimf = bzimf bzimf = self.bzimf # Test that everything is in order, if not revert to existing values iTest = self.__test_valid__() if not iTest: if lat: self.lat = _lat if lon: _self.lon = lon if rho: self.rho = _rho if coords: self.coords = _coords if vswgse: self.vswgse = _vswgse if not datetime==None: self.datetime = _datetime # Declare the same Re as used in Tsyganenko models [km] Re = 6371.2 # Initialize trace array self.l = zeros(len(lat)) self.xTrace = zeros((len(lat),2*lmax)) self.yTrace = self.xTrace.copy() self.zTrace = self.xTrace.copy() self.xGsw = self.l.copy() self.yGsw = self.l.copy() self.zGsw = self.l.copy() self.latNH = self.l.copy() self.lonNH = self.l.copy() self.rhoNH = self.l.copy() self.latSH = self.l.copy() self.lonSH = self.l.copy() self.rhoSH = self.l.copy() # And now iterate through the desired points for ip in xrange(len(lat)): # This has to be called first tsygFort.recalc_08(datetime[ip].year,datetime[ip].timetuple().tm_yday, datetime[ip].hour,datetime[ip].minute,datetime[ip].second, vswgse[0],vswgse[1],vswgse[2]) # Convert lat,lon to geographic cartesian and then gsw r, theta, phi, xgeo, ygeo, zgeo = tsygFort.sphcar_08( rho[ip]/Re, radians(90.-lat[ip]), radians(lon[ip]), 0., 0., 0., 1) if coords.lower() == 'geo': xgeo, ygeo, zgeo, xgsw, ygsw, zgsw = tsygFort.geogsw_08( xgeo, ygeo, zgeo, 0. ,0. ,0. , 1) self.xGsw[ip] = xgsw self.yGsw[ip] = ygsw self.zGsw[ip] = zgsw # Trace field line inmod = 'IGRF_GSW_08' exmod = 'T96_01' parmod = [pdyn, dst, byimf, bzimf, 0, 0, 0, 0, 0, 0] # First towards southern hemisphere maptoL = [-1, 1] for mapto in maptoL: xfgsw, yfgsw, zfgsw, xarr, yarr, zarr, l = tsygFort.trace_08( xgsw, ygsw, zgsw, mapto, dsmax, err, rmax, rmin, 0, parmod, exmod, inmod, lmax ) # Convert back to spherical geographic coords xfgeo, yfgeo, zfgeo, xfgsw, yfgsw, zfgsw = tsygFort.geogsw_08( 0. ,0. ,0. , xfgsw, yfgsw, zfgsw, -1) geoR, geoColat, geoLon, xgeo, ygeo, zgeo = tsygFort.sphcar_08( 0., 0., 0., xfgeo, yfgeo, zfgeo, -1) # Get coordinates of traced point if mapto == 1: self.latSH[ip] = 90. - degrees(geoColat) self.lonSH[ip] = degrees(geoLon) self.rhoSH[ip] = geoR*Re elif mapto == -1: self.latNH[ip] = 90. - degrees(geoColat) self.lonNH[ip] = degrees(geoLon) self.rhoNH[ip] = geoR*Re # Store trace if mapto == -1: self.xTrace[ip,0:l] = xarr[l-1::-1] self.yTrace[ip,0:l] = yarr[l-1::-1] self.zTrace[ip,0:l] = zarr[l-1::-1] elif mapto == 1: self.xTrace[ip,self.l[ip]:self.l[ip]+l] = xarr[0:l] self.yTrace[ip,self.l[ip]:self.l[ip]+l] = yarr[0:l] self.zTrace[ip,self.l[ip]:self.l[ip]+l] = zarr[0:l] self.l[ip] += l # Resize trace output to more minimum possible length self.xTrace = self.xTrace[:,0:self.l.max()] self.yTrace = self.yTrace[:,0:self.l.max()] self.zTrace = self.zTrace[:,0:self.l.max()]