!***************************************************************************************************
! Copyright 2006, 2007 S. Bourdarie
!
! This file is part of IRBEM-LIB.
!
! IRBEM-LIB is free software: you can redistribute it and/or modify
! it under the terms of the GNU Lesser General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! IRBEM-LIB is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU Lesser General Public License for more details.
!
! You should have received a copy of the GNU Lesser General Public License
! along with IRBEM-LIB. If not, see .
!
! CREATION: S. Bourdarie - ONERA-DESP
!
! FILE CONTENT:
! SUBROUTINE fly_in_afrl_crres1: Allows to fly a spacecraft in AFRL CRRES ele and pro models.
! SUBROUTINE get_crres_flux: Compute flux from AFRL CRRES models for an energy, B/B0 and L
! SUBROUTINE Init_CRRESPRO_Quiet: Set block data for AFRL CRRESPRO QUIET model
! SUBROUTINE Init_CRRESPRO_Active: Set block data for AFRL CRRESPRO Active model
! SUBROUTINE Init_CRRESELE_Average: Set block data for AFRL CRRESELE Average model
! SUBROUTINE Init_CRRESELE_WorstCase: Set block data for AFRL CRRESELE Worstcase model
!
!***************************************************************************************************
!---------------------------------------------------------------------------------------------------
! Introduced in version 3.0
!
! CREATION: S. Bourdarie - May 2006
! MODIFICATION: S. Bourdarie - March 2007 (add multi channel calculcations; add time input for coordinates transformations) - V4.1
!
! DESCRIPTION: Allows to fly a spacecraft in CRRES models (AFRL)
!
! INPUT: ntime -> maximum number of time to compute (long integer)
! sysaxes -> define which coordinate system is provided in
! whichm -> which model to use, 1=pro quiet 2=pro active 3=ele ave 4=ele worst case 5=ele Ap15 (long integer)
! whatf -> which kind of flux, 1=differential 2=E range 3=integral (long integer)
! Nene -> Number of energy channels to compute
! energy -> energy (MeV) at which fluxes must be computed (double array [2,25])
! iyear,idoy,UT -> times when flux are to be computed (not usefull if imput position is not in GSE, GSM, SM,GEI) (respectively long array(ntime_max), long array(ntime_max), double array(ntime_max))
! xIN1 -> first coordinate in the chosen system (double array [ntime_max])
! xIN2 -> second coordinate in the chosen system (double array [ntime_max])
! xIN3 -> third coordinate in the chosen system (double array [ntime_max])
! Ap15 -> 15 previous days average of Ap index assuming a one day delay (double array [ntime_max])
!
! OUTPUT: flux -> Computed fluxes (MeV-1 cm-2 s-1 or cm-2 s-1) (double array [ntime_max,25])
!
! CALLING SEQUENCE: CALL fly_in_afrl_crres1(ntime,sysaxes,whichm,whatf,energy,xIN1,xIN2,xIN3,flux)
!---------------------------------------------------------------------------------------------------
SUBROUTINE fly_in_afrl_crres1(ntime,sysaxes,whichm,whatf,nene,
& energy,iyear,idoy,UT,xIN1,xIN2,xIN3,
& Ap15,flux,ascii_path,STRLEN)
c
IMPLICIT NONE
INCLUDE 'ntime_max.inc'
C
c declare inputs
INTEGER*4 STRLEN
BYTE ascii_path(strlen)
c
INTEGER*4 nene_max
PARAMETER (nene_max=25)
INTEGER*4 ntime,sysaxes,whichm,whatf,nene
INTEGER*4 iyear(ntime_max),idoy(ntime_max)
REAL*8 energy(2,nene_max)
REAL*8 UT(ntime_max)
real*8 xIN1(ntime_max),xIN2(ntime_max),xIN3(ntime_max)
c Declare internal variables
INTEGER*4 k_ext,k_l,isat,kint
INTEGER*4 t_resol,r_resol,Ilflag
INTEGER*4 i,iyear_dip,idoy_dip
REAL*8 dec_year,ut_dip
REAL*8 xGEO(3),xMAG(3),xSUN(3),rM,MLAT,Mlon1
REAL*8 xGSM(3),xSM(3),xGEI(3),xGSE(3)
real*8 alti,lati,longi,psi,tilt
REAL*8 ERA,AQUAD,BQUAD
REAL*8 BLOCAL(ntime_max),BMIN(ntime_max),XJ(ntime_max)
REAL*8 Lm(ntime_max),Lstar(ntime_max),BBo(ntime_max)
REAL*8 Ap15(ntime_max)
c
c Declare output variables
REAL*8 flux(ntime_max,nene_max)
c
CHARACTER*(500) afrl_crres_path
C
COMMON/GENER/ERA,AQUAD,BQUAD
COMMON /magmod/k_ext,k_l,kint
COMMON /flag_L/Ilflag
COMMON /dip_ang/tilt
DATA xSUN /1.d0,0.d0,0.d0/
REAL*8 pi,rad
common /rconst/rad,pi
C
DO i=1,strlen
afrl_crres_path(i:i)=char(ascii_path(i))
ENDDO
afrl_crres_path=afrl_crres_path(1:strlen)
Ilflag=0
k_ext=5
t_resol=3
r_resol=0
k_l=0
if (whichm .lt. 1 .or. whichm .gt. 5) then
whichm=1
WRITE(6,*)
WRITE(6,*)'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
WRITE(6,*)'Invalid AFRL CRRES model specification'
WRITE(6,*)'Selecting crrespro quiet'
WRITE(6,*)'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
WRITE(6,*)
endif
c
if (whatf .lt. 1 .or. whatf .gt. 3) then
whatf=1
WRITE(6,*)
WRITE(6,*)'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
WRITE(6,*)'Invalid flux output specification'
WRITE(6,*)'Selecting differential flux'
WRITE(6,*)'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
WRITE(6,*)
endif
c
kint=1 !set IGRF
CALL INITIZE
dec_year=1985.5d0
CALL INIT_DTD(dec_year)
c
iyear_dip=1985
idoy_dip=182
UT_dip=0.d0
CALL INIT_GSM(iyear_dip,idoy_dip,UT_dip,psi)
tilt = psi/rad
DO isat = 1,ntime
call get_coordinates ( sysaxes,
6 xIN1(isat), xIN2(isat), xIN3(isat),
6 alti, lati, longi, xGEO )
CALL calcul_Lstar_opt(t_resol,r_resol,xGEO
& ,Lm(isat),Lstar(isat),XJ(isat),BLOCAL(isat),BMIN(isat))
BBo(isat)=BLOCAL(isat)/BMIN(isat)
if (Lm(isat) .le. 0.D0 .and. Lm(isat) .ne. -1.D31)
& Lm(isat)=-Lm(isat)
enddo
call get_crres_flux(ntime,whichm,whatf,nene,
& energy,BBo,Lm,Ap15,flux,afrl_crres_path,strlen)
end
!
!---------------------------------------------------------------------------------------------------
! Introduced in version 3.0
!
! CREATION: S. Bourdarie - May 2006
! MODIFICATION: S. Bourdarie - March 2007 (add multi channel calculcations) - V4.1
!
! DESCRIPTION: Compute flux from CRRES models for an energy, B/B0 and L
!
! INPUT: ntmax -> maximum number of time to compute (long integer)
! whichm -> which model to use, 1=pro quiet 2=pro active 3=ele ave 4=ele worst case 5=ele Ap15 (long integer)
! whatf -> which kind of flux, 1=differential 2=E range 3=integral (long integer)
! Nene -> Number of energy channels to compute
! energy -> energy (MeV) at which fluxes must be computed (double array [2,25])
! BBo -> Blocal/Bequator (double array [ntime_max])
! L -> McIlwain L (double array [ntime_max])
! Ap15 -> 15 previous days average of Ap index assuming a one day delay (double array [ntime_max])
!
! OUTPUT: flux -> Computed fluxes (MeV-1 cm-2 s-1 or cm-2 s-1) (double array [ntime_max,25])
!
! CALLING SEQUENCE: get_crres_flux(ntmax,whichm,whatf,energy,BBo,L,flux)
!---------------------------------------------------------------------------------------------------
SUBROUTINE get_crres_flux(ntmax,whichm,whatf,nene,
& energy,BBo,L,Ap15,flux,afrl_crres_path,strlen)
c
IMPLICIT NONE
INCLUDE 'variables.inc'
INCLUDE 'ntime_max.inc'
c
INTEGER*4 STRLEN
c
INTEGER*4 ntmax,nene,i,ie,il,ib,ie1,ie2,iap,ieny
INTEGER*4 whichm !1=pro quiet 2=pro active 3=ele ave 4=ele worst case 5=ele Ap15
INTEGER*4 whatf !1=diff 2=E range 3=int
c
INTEGER*4 Ne,Nl,Nbb0,ind
c
REAL*8 energy(2,25)
REAL*8 flux(ntime_max,25),BBo(ntime_max),L(ntime_max)
REAL*8 Ap15(ntime_max)
REAL*8 pente,cste,Flux1,Flux2
c
c crres variables
REAL*8 c_Ec(22)
REAL*8 c_bb0(35)
REAL*8 c_flux(22,34,90) !energy;bb0,Lshell
REAL*8 c_Lshell(91)
REAL*8 c_Ap15(7)
c
CHARACTER*(*) afrl_crres_path
C
c
c common /crres_model/Ne,Nbb0,Nl,c_Lshell,c_Ec,c_bb0,c_flux
common /crres_model_int/Ne,Nbb0,Nl
common /crres_model_dbl/c_Lshell,c_Ec,c_bb0,c_flux
c
data c_Ap15 /5.0D0,7.0D0,10.0D0,15.0D0,20.0D0,25.0D0,55.0D0/
c
c init
DO i=1,ntmax
do ieny=1,25
Flux(i,ieny) = baddata
enddo
enddo
CALL Init_CRRES(whichm,afrl_crres_path,strlen)
c
if (whatf.EQ. 1) then
DO i=1,ntmax
c
c search in Lbin
if (L(i).GE.c_Lshell(1) .AND.
& L(i).LT.c_Lshell(Nl)) then
do il=2,Nl
if (L(i).LT.c_Lshell(IL)) goto 10
enddo
10 continue
Il=Il-1
c
c search in bb0bin
if (BBo(i).GT.c_bb0(Nbb0)) goto 50
do ib=2,Nbb0
if (BBo(i).LE.c_bb0(IB)) goto 20
enddo
20 continue
ib=ib-1
c
c search in Ap15bin if whichm=5
if (whichm .EQ. 5) then
if (Ap15(i).LT.c_Ap15(1) .OR.
& Ap15(i).GT.c_Ap15(7)) goto 50
do iap=2,7
if (Ap15(i).LE.c_Ap15(iap)) goto 30
enddo
30 continue
iap=iap-1
ind=4+iap
CALL Init_CRRES(ind,afrl_crres_path,strlen)
endif
c
c loop on energies
do ieny=1,nene
if (energy(1,ieny).LT.c_Ec(1) .OR.
& energy(1,ieny).GT.c_Ec(Ne)) then
Flux(i,ieny) = baddata
else
do ie=2,Ne
if (energy(1,ieny).LE.c_Ec(ie)) goto 40
enddo
40 continue
c
if (c_flux(ie,ib,il).LE.0.D0 .OR.
& c_flux(ie-1,ib,il).LE.0.D0) then
Flux(i,ieny) = baddata
else
pente=(LOG(c_flux(ie,ib,il))-
& LOG(c_flux(ie-1,ib,il)))/
& (LOG(c_Ec(ie))-LOG(c_Ec(ie-1)))
cste=LOG(c_flux(ie,ib,il))-
& pente*LOG(c_Ec(ie))
Flux(i,ieny)=exp(pente*LOG(energy(1,ieny))
& +cste)
endif
endif
enddo
else
do ieny=1,nene
Flux(i,ieny) = baddata
enddo
endif
50 continue
enddo
endif
c
c
if (whatf.EQ. 2) then
DO i=1,ntmax
if (L(i).GE.c_Lshell(1) .AND.
& L(i).LT.c_Lshell(Nl)) then
do il=2,Nl
if (L(i).LT.c_Lshell(IL)) goto 110
enddo
110 continue
Il=Il-1
if (BBo(i).GT.c_bb0(Nbb0)) then
do ieny=1,nene
Flux(i,ieny) = baddata
enddo
goto 150
endif
do ib=2,Nbb0
if (BBo(i).LE.c_bb0(IB)) goto 120
enddo
120 continue
Ib=Ib-1
c search in Ap15bin if whichm=5
if (whichm .EQ. 5) then
if (Ap15(i).LT.c_Ap15(1) .OR.
& Ap15(i).GT.c_Ap15(7)) then
do ieny=1,nene
Flux(i,ieny) = baddata
enddo
goto 150
endif
do iap=2,7
if (Ap15(i).LE.c_Ap15(iap)) goto 125
enddo
125 continue
iap=iap-1
ind=4+iap
CALL Init_CRRES(ind,afrl_crres_path,strlen)
endif
c
c loop on energies
do ieny=1,nene
if (energy(1,ieny).LT.c_Ec(1) .OR.
& energy(1,ieny).GT.c_Ec(Ne)) then
Flux(i,ieny) = baddata
else
do ie1=2,Ne
if (energy(1,ieny).LE.c_Ec(ie1)) goto 140
enddo
140 continue
do ie2=2,Ne
if (energy(2,ieny).LE.c_Ec(ie2)) goto 145
enddo
145 continue
if (c_flux(ie1,ib,il).LE.0.D0 .OR.
& c_flux(ie1-1,ib,il).LE.0.D0) then
flux1=0.D0
else
pente=(LOG(c_flux(ie1,ib,il))-
& LOG(c_flux(ie1-1,ib,il)))/
& (LOG(c_Ec(ie1))-LOG(c_Ec(ie1-1)))
cste=LOG(c_flux(ie1,ib,il))-
& pente*LOG(c_Ec(ie1))
Flux1=exp(pente*LOG(energy(1,ieny))+cste)
endif
c
if (c_flux(ie2,ib,il).LE.0.D0 .OR.
& c_flux(ie2-1,ib,il).LE.0.D0) then
flux2=0.D0
else
pente=(LOG(c_flux(ie2,ib,il))-
& LOG(c_flux(ie2-1,ib,il)))/
& (LOG(c_Ec(ie2))-LOG(c_Ec(ie2-1)))
cste=LOG(c_flux(ie2,ib,il))-
& pente*LOG(c_Ec(ie2))
Flux2=exp(pente*LOG(energy(2,ieny))+cste)
endif
if (ie1.ne.ie2) then
Flux(i,ieny)=(Flux1+c_flux(ie1,ib,il))*
& (c_Ec(ie1)-energy(1,ieny))/2.D0
do ie=ie1,ie2-2
Flux(i,ieny)=Flux(i,ieny)+
& (c_flux(ie,ib,il)+c_flux(ie+1,ib,il))*
& (c_Ec(ie+1)-c_Ec(ie))/2.D0
enddo
Flux(i,ieny)=Flux(i,ieny)+
& (c_flux(ie2-1,ib,il)+flux2)*
& (energy(2,ieny)-c_Ec(ie2-1))/2.D0
Flux(i,ieny)=Flux(i,ieny)/(energy(2,ieny)-
& energy(1,ieny))
else
Flux(i,ieny)=(Flux1+Flux2)/2.D0
endif
if (Flux(i,ieny).LE.0.D0) Flux(i,ieny)=baddata
endif
enddo
else
do ieny=1,nene
Flux(i,ieny) = baddata
enddo
endif
150 continue
enddo
endif
c
c
if (whatf.EQ. 3) then
DO i=1,ntmax
if (L(i).GE.c_Lshell(1) .AND.
& L(i).LT.c_Lshell(Nl)) then
do il=2,Nl
if (L(i).LT.c_Lshell(IL)) goto 210
enddo
210 continue
Il=Il-1
if (BBo(i).GT.c_bb0(Nbb0)) then
do ieny=1,nene
Flux(i,ieny) = baddata
enddo
goto 250
endif
do ib=2,Nbb0
if (BBo(i).LE.c_bb0(IB)) goto 220
enddo
220 continue
Ib=Ib-1
c search in Ap15bin if whichm=5
if (whichm .EQ. 5) then
if (Ap15(i).LT.c_Ap15(1) .OR.
& Ap15(i).GT.c_Ap15(7)) then
do ieny=1,nene
Flux(i,ieny) = baddata
enddo
goto 250
endif
do iap=2,7
if (Ap15(i).LE.c_Ap15(iap)) goto 225
enddo
225 continue
iap=iap-1
ind=4+iap
CALL Init_CRRES(ind,afrl_crres_path,strlen)
endif
c
c loop on energies
do ieny=1,nene
if (energy(1,ieny).LT.c_Ec(1) .OR.
& energy(1,ieny).GT.c_Ec(Ne)) then
Flux(i,ieny) = baddata
else
do ie1=2,Ne
if (energy(1,ieny).LE.c_Ec(ie1)) goto 240
enddo
240 continue
c
if (c_flux(ie1,ib,il).LE.0.D0 .OR.
& c_flux(ie1-1,ib,il).LE.0.D0) then
Flux1 = 0.D0
else
pente=(LOG(c_flux(ie1,ib,il))-
& LOG(c_flux(ie1-1,ib,il)))/
& (LOG(c_Ec(ie1))-LOG(c_Ec(ie1-1)))
cste=LOG(c_flux(ie1,ib,il))-
& pente*LOG(c_Ec(ie1))
Flux1=exp(pente*LOG(energy(1,ieny))+cste)
endif
c
if (ie1.ne.Ne) then
Flux(i,ieny)=(Flux1+c_flux(ie1,ib,il))*
& (c_Ec(ie1)-energy(1,ieny))/2.D0
do ie=ie1,Ne-1
Flux(i,ieny)=Flux(i,ieny)+
& (c_flux(ie,ib,il)+c_flux(ie+1,ib,il))*
& (c_Ec(ie+1)-c_Ec(ie))/2.D0
enddo
else
Flux(i,ieny)=(Flux1+c_flux(Ne,ib,il))*
& (c_Ec(Ne)-energy(1,ieny))/2.D0
endif
if (Flux(i,ieny).LE.0.D0) Flux(i,ieny)=baddata
endif
enddo
else
do ieny=1,nene
Flux(i,ieny) = baddata
enddo
endif
250 continue
enddo
endif
end
!
!---------------------------------------------------------------------------------------------------
! Introduced in version 3.0
!
! CREATION: S. Bourdarie - May 2006 (from Don Brautigam)
!
! DESCRIPTION: Set block data for CRRES model
! Valid range is: 1.5 1.200D0,1.300D0,1.400D0,1.520D0,1.690D0,1.880D0,
> 2.100D0,2.400D0,2.730D0,3.130D0,3.670D0,4.350D0,
> 5.02D0 ,6.1D0 ,7.410D0,9.088D0,11.29D0,14.22D0,
> 18.16D0,23.56D0,31.07D0,41.47D0,57.23D0,80.25D0,
> 115.4D0,170.7D0,260.7D0,413.4D0,684.6D0/
c
data tmp_Ec /1.5D0,2.1D0,2.5D0,2.9D0,3.6D0,4.3D0,5.7D0,
> 6.8D0,8.5D0,
> 9.7D0,10.7D0,13.2D0,16.9D0,19.4D0,26.3D0,30.9D0,36.3D0,
> 41.1D0,47.0D0,55.0D0,65.7D0,81.3D0/
c
do ish=1,35
bb0(ish)=tmp_bb0(ish)
enddo
do ish=1,22
Ec(ish)=tmp_Ec(ish)
enddo
do ish=1,91
Lshell(ish)=1.0D0+(ish-1)*.05D0
enddo
end
c
!---------------------------------------------------------------------------------------------------
! Introduced in version 3.0
!
! CREATION: S. Bourdarie - May 2006 (from Don Brautigam)
!
! DESCRIPTION: Set block data for CRRES ELE Average model
! Valid range is: 0.65 1.200D0,1.300D0,1.400D0,1.520D0,1.690D0,1.880D0,
> 2.100D0,2.400D0,2.730D0,3.130D0,3.670D0,4.350D0,
> 5.02D0 ,6.1D0 ,7.410D0,9.088D0,11.29D0,14.22D0,
> 18.16D0,23.56D0,31.07D0,41.47D0,57.23D0,80.25D0,
> 115.4D0,170.7D0,260.7D0,413.4D0,684.6D0/
c
data tmp_Ec /0.65D0,0.95D0,1.60D0,2.00D0,2.35D0,2.75D0,3.15D0,
> 3.75D0,4.55D0,5.75D0,12*0.D0/
c
do ish=1,35
bb0(ish)=tmp_bb0(ish)
enddo
do ish=1,22
Ec(ish)=tmp_Ec(ish)
enddo
do ish=1,87
Lshell(ish)=2.5D0+(ish-1)*.05D0
enddo
do ish=88,91
Lshell(ish)=0.D0
enddo
end