UNNORM_STABILITY_MAIN Program

Uses

  • program~~unnorm_stability_main~~UsesGraph program~unnorm_stability_main UNNORM_STABILITY_MAIN module~globals GLOBALS program~unnorm_stability_main->module~globals module~kinds KINDS program~unnorm_stability_main->module~kinds module~vsh VSH program~unnorm_stability_main->module~vsh module~globals->module~kinds module~vsh->module~globals module~vsh->module~kinds

Driver for mapping the UNNORMALIZED Bonnet recurrence's (ASSOC_LEGENDRE/ASSOC_LEGENDRE_ALL, and everything single-mode built on it) usable accuracy range across (opt-in VSH_BUILD_STABILITY CMake target, same as STABILITY_MAIN -- not part of ctest). See STABILITY_FINDINGS.md at the repo root.

Unlike the normalized-recurrence scan, this one doesn't hunt for a literal overflow -- the seed grows/shrinks combinatorially with , so raw magnitude alone is a poor proxy for accuracy: catastrophic cancellation in the later three-term upward recurrence in can destroy relative precision well before the value is anywhere near double-precision overflow. So this driver writes RAW single-mode and batch values (not a broken/not-broken flag) for py/plot_stability_unnorm.py to diff against py/mpmath_reference.py's legendre_ref -- the same arbitrary-precision rerun of this exact recurrence used to validate ASSOC_LEGENDRE_NORM_ALL's stable range.

For each theta, one call to ASSOC_LEGENDRE_ALL at LMAX_SCAN yields the whole l<=LMAX_SCAN, m<=l table; three m fractions of l (1.0 = diagonal/worst-case, 0.75, 0.5) are sampled per l to confirm the diagonal really is the worst case rather than assuming it.


Calls

program~~unnorm_stability_main~~CallsGraph program~unnorm_stability_main UNNORM_STABILITY_MAIN dcos dcos program~unnorm_stability_main->dcos interface~assoc_legendre ASSOC_LEGENDRE program~unnorm_stability_main->interface~assoc_legendre interface~assoc_legendre_all ASSOC_LEGENDRE_ALL program~unnorm_stability_main->interface~assoc_legendre_all proc~plm_index PLM_INDEX program~unnorm_stability_main->proc~plm_index proc~assoc_legendre_dp ASSOC_LEGENDRE_DP interface~assoc_legendre->proc~assoc_legendre_dp proc~assoc_legendre_all_dp ASSOC_LEGENDRE_ALL_DP interface~assoc_legendre_all->proc~assoc_legendre_all_dp proc~assoc_legendre_all_dp->proc~plm_index interface~log_fact LOG_FACT proc~assoc_legendre_dp->interface~log_fact proc~log_fact_dp LOG_FACT_DP interface~log_fact->proc~log_fact_dp

Variables

Type Attributes Name Initial
integer(kind=i4) :: IF_
integer(kind=i4) :: ITH
integer(kind=i4) :: L
integer(kind=i4), parameter :: LMAX_SCAN = 200
integer(kind=i4) :: M
real(kind=dp), parameter, DIMENSION(NFRAC) :: MFRAC = (/1.0_dp, 0.75_dp, 0.5_dp/)
integer(kind=i4) :: MPREV
integer(kind=i4), parameter :: NFRAC = 3
integer(kind=i4), parameter :: NTHETA = 179
real(kind=dp), ALLOCATABLE :: PBATCH(:)
real(kind=dp) :: PSING
real(kind=dp) :: THETA
real(kind=dp) :: THETA_DEG
real(kind=dp) :: X

Source Code

PROGRAM UNNORM_STABILITY_MAIN
USE KINDS,   ONLY: i4, dp
USE GLOBALS, ONLY: pi
USE VSH,     ONLY: ASSOC_LEGENDRE, ASSOC_LEGENDRE_ALL, PLM_INDEX
IMPLICIT NONE

INTEGER(KIND=i4), PARAMETER :: LMAX_SCAN = 200
INTEGER(KIND=i4), PARAMETER :: NTHETA = 179
INTEGER(KIND=i4), PARAMETER :: NFRAC = 3
REAL(KIND=dp), DIMENSION(NFRAC), PARAMETER :: MFRAC = (/1.0_dp, 0.75_dp, 0.5_dp/)

REAL(KIND=dp), ALLOCATABLE :: PBATCH(:)
REAL(KIND=dp) :: THETA_DEG, THETA, X, PSING
INTEGER(KIND=i4) :: ITH, L, M, IF_, MPREV

ALLOCATE(PBATCH((LMAX_SCAN+1)*(LMAX_SCAN+2)/2))

OPEN(UNIT=41, FILE="./stability/unnorm_diagonal.dat")
WRITE(41,'(A)') '# theta_deg  l  m  m_frac  P_single  P_batch'

DO ITH = 1, NTHETA
  THETA_DEG = REAL(ITH, dp)
  THETA = THETA_DEG * pi / 180.0_dp
  X = DCOS(THETA)
  CALL ASSOC_LEGENDRE_ALL(PBATCH, LMAX_SCAN, X)

  DO L = 1, LMAX_SCAN
    MPREV = -1
    DO IF_ = 1, NFRAC
      M = NINT(MFRAC(IF_) * L)
      IF (M == MPREV) CYCLE
      MPREV = M
      PSING = ASSOC_LEGENDRE(L, M, X)
      WRITE(41,*) THETA_DEG, L, M, MFRAC(IF_), PSING, PBATCH(PLM_INDEX(L,M))
    END DO
  END DO
  IF (MOD(ITH, 20) == 0) WRITE(*,'(A,F6.1,A)') "  theta=", THETA_DEG, " done"
END DO

CLOSE(41)
DEALLOCATE(PBATCH)
WRITE(*,'(A)') "RESULT: unnormalized scan complete - see ./stability/unnorm_diagonal.dat"

END PROGRAM UNNORM_STABILITY_MAIN