igrf20.f 10.9 KB
      subroutine igrf20 (year,rre,thet,phi,br,bt,bp,bb,ier)
c*
c***********************************************************************
c*
c*          "Copyright [c] CNES 98 - tous droits reserves"
c*          **********************************************
c*
c*PRO MAGLIB
c*
c*VER 20.07.13 - V 1.0
c*
c*AUT spec. CNES - JC KOSIK - fevrier 2001
c*AUT port. AKKA
c*
c*ROL         Calcul du champ magnetique d'origine interne avec les
c*ROL         coefficients definitifs du modele IGRF-13.
c*
c*PAR year (I) : annee fractionnaire (>= 2020.)
c*
c*PAR rre  (I) : distance radiale geocentrique (rayons terrestres)
c*PAR thet (I) : colatitude geocentrique (radians)
c*PAR phi  (I) : longitude geocentrique (radians)
c*
c*PAR br   (O) : composante radiale du champ magnetique le long du
c*             : meridien positive vers l'exterieur (gauss)
c*PAR bt   (O) : composante tangentielle du champ magnetique le long
c*PAR          : du meridien positive vers le sud (gauss)
c*PAR bp   (O) : composante azimuthale du champ magnetique, positive
c*PAR          : vers l'est (gauss)
c*
c*PAR bb   (O) : module du champ magnetique (gauss)
c*
c*PAR ier  (O) : code de retour
c*
c*NOT ier      : sans objet
c*
c*NOT Dans le cas ou l'angle thet est nul, son sinus est
c*NOT remplacee par 1.d-15 afin d'eviter des divisions par 0 et
c*NOT son cosinus est remplace par 1.0d0.
c*NOT Dans le cas ou l'angle thet est egal a pi, son sinus est
c*NOT remplacee par 1.d-15 afin d'eviter des divisions par 0 et
c*NOT son cosinus est remplace par -1.0d0.
c*
c*NOT common   : util, util2
c*
c*INF utilise  : sans objet
c*
c*HST version 1.0 - 20.07.13 - Coefficients de Schmidt et variations
c*HST                          seculaires provisoires 2020
c*
c***********************************************************************
c*
      implicit none
c
c     ---------------------------------
c*FON Declaration identificateur rcs_id
c     ---------------------------------
c
      character rcs_id*100
c
c     --------------------------
c*FON Declaration des parametres
c     --------------------------
c
      double precision year, rre, thet, phi
      double precision br, bt, bp, bb
      integer ier
c
c     ----------------------------------
c*FON Declaration des variables communes
c     ----------------------------------
c
      double precision pi,dpi,rad,deg,pid,xmu,rayt
c
c*COM pi   : constante pi (obtenue a partir de acos(-1.))
c*COM dpi  : constante 2 * pi
c*COM pid  : constante pi / 2
c*COM rad  : facteur de conversion degres  ----> radians
c*COM deg  : facteur de conversion radians ----> degres
c*COM xmu  : constante de gravitation terrestre (km**3/sec**2)
c*COM rayt : rayon equatorial terrestre (km)
c
      common/util/pi,dpi,rad,deg,pid,xmu,rayt
c
      double precision rgmt
c
c*COM rgmt : rayon geocentrique terrestre (km)
c
      common/util2/rgmt
c
c     ---------------------------------
c*FON Declaration des variables locales
c     ---------------------------------
c
      integer lg(14,14),lgt(14,14)
c*LOC lg, lgt : coefficients du modele igrf 2015
c
      integer kmax
c*LOC kmax : nombre de pas de calcul (= 14)
c
      integer n,m,jj
c*LOC n,m,jj : indices de boucles et de tableaux
c
      double precision gg(14,14),ggt(14,14)
      double precision shmit(14,14)
      double precision g(14,14)
      double precision const(14,14),fn(14),fm(14)
      double precision p(14,14),dp(14,14),sp(14),cp(14)
      double precision tmold,tzero,sph,st,t,temp,par,f2
      double precision cph,ct,f1,aor,ar,rrmag
c*LOC Variables de travail intermediaires
c
      SAVE
c
c     ---------------------------------
c*FON Affectation identificateur rcs_id
c     ---------------------------------
c
      data rcs_id /"
     >$Id$"/
c
c     --------------------------
c*FON Affectation des constantes
c     --------------------------
c
c     Revision février 2017- coefficients lg et lgt
c
      data lg/10,
     > -294048,-24996,13632,9030,-2343,660,806,237,50,-19,30,-20,1,
     >  46525,-14509,29820,-23812,8095,3632,655,-767,97,84,-62,-14,-1,
     > -9,
     > -29916,-7346,16770,12362,863,1878,729,-82,-176,29,-1,-25,5,5,
     > -821,2419,-5434,5257,-3094,-1407,-1215,565,-5,-15,17,23,13,7,
     >  2819,-1584,1997,-3497,480,-1512,-362,158,-211,-11,-9,-9,-12,-3,
     >  477,2083,-1212,323,989,135,135,64,153,-132,7,3,7,8,
     > -191,251,528,-645,89,681,-647,-72,137,11,-9,-7,3,0,
     > -515,-169,22,235,-22,-272,-18,98,-165,88,19,-1,5,8,
     >  84,-153,128,-117,149,36,-69,28,-3,-93,14,14,-3,0,
     > -234,110,98,-51,-63,78,4,-14,96,-119,-24,-6,-5,4,
     >  34,-2,36,48,-86,-1,-43,-34,-1,-88,-38,2,1,1,
     >  0,25,-6,-4,6,-2,-17,-16,-30,-20,-26,31,-11,5,
     > -12,5,14,-18,1,8,-2,6,2,-9,0,5,-3,-5,
     > -9,6,14,-4,-13,-1,3,-1,5,5,-4,-4,-6,-4
     > /
c
       data lgt/10,
     >  57,-110,22,-12,-3,-5,-1,0,0,0,0,0,0,
     > -259,74,-70,-59,-16,5,-3,-2,1,0,0,0,0,0,
     > -302,-224,-21,31,-59,-6,4,0,-1,0,0,0,0,0,
     >  60,-11,5,-120,52,2,13,7,4,0,0,0,0,0,
     > -1,65,36,-50,-51,13,-14,1,-1,0,0,0,0,0,
     >  0,25,-6,30,3,9,0,-5,4,0,0,0,0,0,
     >  0,-16,-13,8,0,10,9,-8,3,0,0,0,0,0,
     >  6,6,-8,-2,-11,1,3,8,-1,0,0,0,0,0,
     > -2,6,-2,5,-3,-4,5,0,4,0,0,0,0,0,
     >  0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     >  0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     >  0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     >  0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     >  0,0,0,0,0,0,0,0,0,0,0,0,0,0
     > /
c
      data f1 /10.d0/, f2 /10.d0/
c
      data kmax /14/
c
      data p(1,1)  /1.d0/
      data cp(1)   /1.d0/
      data dp(1,1) /0.d0/
      data sp(1)   /0.d0/
c
      data shmit(1,1) /0.d0/
c
      data tmold /0.d0/
c
      data tzero /2020.d0/
c
c     ******************
c     Debut de programme
c     ******************
c
      ier = 0
c
c     ---------------------------------------------------------------
c*FON Initialisation a 0 des composantes du champ ainsi que du module
c     ---------------------------------------------------------------
c
      br = 0.0d0
      bt = 0.0d0
      bp = 0.0d0
      bb = 0.0d0
c
c     --------------------------------------------------
c*FON Initialisations  faites au premier appel du module
c     --------------------------------------------------
c
      if (shmit(1,1) .ne. -1.d0) then
c
c     ----------------------------------
c*FON Calcul des tableaux fn,fm et const
c     ----------------------------------
c
         shmit(1,1) = -1.d0
         do 10 n = 1, 14
            fn(n) = n
            do 20 m = 1, 14
               fm(m)      = m - 1
               const(n,m) = dble((n - 2)**2 - (m - 1)**2) /
     >                      dble((2 * n - 3) * (2 * n - 5))
20         continue
10       continue
c
c     ----------------------------
c*FON Calcul du tableau shmit(n,m)
c     ----------------------------
c
         do 30 n = 2, 14
            shmit(n,1) = dble(2 * n - 3) * shmit(n-1,1) / dble(n - 1)
            jj = 2
            do 40 m = 2, n
               shmit(n,m)   = shmit(n,m-1) *
     >                        sqrt(dble((n - m + 1) * jj) / (n + m - 2))
               shmit(m-1,n) = shmit(n,m)
               jj           = 1
40          continue
30       continue
c
c     ---------------------------------------
c*FON Calcul des tableaux gg(n,m) et ggt(n,m)
c     ---------------------------------------
c
         f1 = dble(lg(1,1))
         f2 = dble(lgt(1,1))
         do 50 n = 1, kmax
            do 60 m = 1, kmax
               gg(n,m)  = dble(lg(n,m)) * shmit(n,m) / f1
               ggt(n,m) = dble(lgt(n,m)) * shmit(n,m) / f2
60          continue
50       continue
c
c     --------------------------------------------------
c*FON Traitements effectues si ce n'est pas le 1er appel
c     --------------------------------------------------
c
      endif
c
c     ------------------------
c*FON Calcul du tableau g(n,m)
c     ------------------------
c
      if (year .ne. tmold) then
c
         tmold = year
         t     = year - tzero
c
         do 70 n = 1, kmax
            do 80 m= 1, kmax
               g(n,m) = gg(n,m) + t * ggt(n,m)
80          continue
70       continue
c
      endif
c
c     ----------------------------------------------------
c*FON Calcul des cosinus directeurs de la colatitude et de
c*FON la longitude geocentriques
c     ----------------------------------------------------
c
      cph = cos(phi)
      sph = sin(phi)
c
      if (thet .ne. 0.0d0 .and. thet .ne. acos(-1.0d0)) then
c
         ct  = cos(thet)
         st  = sin(thet)
c
      else
c
         if (thet .ne. acos(-1.0d0)) then
            ct  = 1.0d0
            st  = 1.d-15
         elseif (thet .ne. 0.0d0) then
            ct  = -1.0d0
            st  = 1.d-15
         endif
c
      endif
c
      sp(2) = sph
      cp(2) = cph
c
c     ----------------------------
c*FON Calcul des tableaux cp et sp
c     ----------------------------
c
      do 90 m = 3, kmax
         sp(m) = sp(2) * cp(m-1) + cp(2) * sp(m-1)
         cp(m) = cp(2) * cp(m-1) - sp(2) * sp(m-1)
90    continue
c
c     ---------------------------------------------------
c*FON Premiers termes des composantes du champ magnetique
c     ---------------------------------------------------
c
      rrmag   = rre * rayt / rgmt
      aor     = 1.d0 / rrmag
      ar      = aor * aor * aor
c
      p(2,1)  = ct
      dp(2,1) = -st
      p(2,2)  = st
      dp(2,2) = ct
c
      br = - (ar + ar) * (g(2,1) * p(2,1) + p(2,2) * (g(2,2) * cp(2) +
     >     g(1,2) * sp(2)))
      bt = ar * (g(2,1) * dp(2,1) + dp(2,2) * (g(2,2) * cp(2) +
     >     g(1,2) * sp(2)))
      bp = ar * (g(1,2) * cp(2) - g(2,2) * sp(2)) * p(2,2)
c
c     -----------------------------------------------------
c*FON Evaluation finale des composantes du champ magnetique
c     -----------------------------------------------------
c
      do 100 n = 3, kmax
         ar = aor * ar
         do 110 m = 1, n
c
            if (m .eq. n) then
               p(n,n)  = st * p(n-1,n-1)
               dp(n,n) = st * dp(n-1,n-1) + ct * p(n-1,n-1)
            else
               if (const(n,m) .eq. 0) then
                  p(n,m)  = ct * p(n-1,m)
                  dp(n,m) = ct * dp(n-1,m) - st * p(n-1,m)
               else
                  p(n,m)  = ct * p(n-1,m) - const(n,m) * p(n-2,m)
                  dp(n,m) = ct * dp(n-1,m) - st * p(n-1,m)
     >                      - const(n,m) * dp(n-2,m)
               endif
            endif
c
            par = p(n,m) * ar
c
            if (m .eq. 1) then
               temp = g(n,m)
            else
               temp = g(n,m) * cp(m) + g(m-1,n) * sp(m)
               bp   = bp - (g(n,m) * sp(m) - g(m-1,n) * cp(m)) *
     >                fm(m) * par
            endif
c
            br = br - temp * fn(n) * par
            bt = bt + temp * dp(n,m) * ar
c
110      continue
c
100   continue
c
      bp = bp / st
c
c     ---------------------------------------
c*FON Expression du champ magnetique en gauss
c     ---------------------------------------
c
      br = br / 100000.d0
      bt = bt / 100000.d0
      bp = bp / 100000.d0
c
      bb = sqrt(bp * bp + bt * bt + br * br)
c
c     ****************
c     Fin de programme
c     ****************
c
      return
      end