77 ! Also updated to check that transform has been initialized for the
88 ! correct type (to avoid having wSave too small)
99 ! ADP: 07/28/2014: Added in the complex FFT routines from fftpack v. 4.1
10+ ! ADP: 08/15/2026: upgraded from fftpack v4.1 to v5.1 and added interfaces for 2D fft
1011! =======================================================================
1112MODULE NWTC_FFTPACK
1213!- ----------------------------------------------------------------------
@@ -674,6 +675,38 @@ SUBROUTINE ExitSINT(FFT_Data, ErrStat)
674675
675676 END SUBROUTINE ExitSINT
676677 !- -----------------------------------------------------------------------
678+ SUBROUTINE CheckFFTPACKRealKind ( ErrStat )
679+
680+ ! This subroutine verifies that fftpack5.1.f was compiled with a default REAL
681+ ! kind of SiKi. FFTPACK 5.1 declares its arrays as bare REAL/COMPLEX, but this
682+ ! wrapper hands it explicitly kinded REAL(SiKi)/COMPLEX(SiKi) buffers and passes
683+ ! their element counts as LENSAV/LENWRK. If the build promotes the default REAL
684+ ! to 8 bytes in fftpack5.1.f (DOUBLE_PRECISION does this by default, via
685+ ! -fdefault-real-8 for GNU or -real-size 64 for Intel), FFTPACK writes twice as
686+ ! many bytes as those buffers hold and silently corrupts the heap and stack.
687+ ! See the FFTPACK_SOURCES block in modules/nwtc-library/CMakeLists.txt.
688+
689+ IMPLICIT NONE
690+
691+ INTEGER , INTENT (OUT ),OPTIONAL :: ErrStat ! returns non-zero if an error occurred
692+
693+ INTEGER , EXTERNAL :: FFTPACK_REALKIND ! from src/NetLib/fftpack/fftpack_kind.f
694+
695+
696+ IF ( PRESENT (ErrStat) ) ErrStat = ErrID_None
697+
698+ IF ( FFTPACK_REALKIND() /= SiKi ) THEN
699+ CALL ProgAbort ( ' FFTPACK 5.1 was compiled with a default REAL kind of ' // &
700+ TRIM (Num2LStr(FFTPACK_REALKIND()))// ' , but NWTC_FFTPACK requires ' // &
701+ TRIM (Num2LStr(SiKi))// ' . The build must suppress default-real promotion ' // &
702+ ' for fftpack5.1.f and fftpack_kind.f.' , PRESENT (ErrStat) )
703+ IF ( PRESENT (ErrStat) ) ErrStat = ErrID_Fatal
704+ ENDIF
705+
706+
707+ END SUBROUTINE CheckFFTPACKRealKind
708+ !- -----------------------------------------------------------------------
709+
677710 SUBROUTINE InitCOST ( NumSteps , FFT_Data , NormalizeIn , ErrStat )
678711
679712 ! This subroutine initializes the cosine transform working space
@@ -694,6 +727,14 @@ SUBROUTINE InitCOST( NumSteps, FFT_Data, NormalizeIn, ErrStat )
694727
695728 IF ( PRESENT (ErrStat) ) ErrStat = ErrID_None
696729
730+ ! Verify FFTPACK's default REAL kind matches this wrapper's (SiKi)
731+
732+ CALL CheckFFTPACKRealKind( ErrStat )
733+ IF ( PRESENT (ErrStat) ) THEN
734+ IF ( ErrStat >= AbortErrLev ) RETURN
735+ ENDIF
736+
737+
697738 ! Number of timesteps in the time series returned from the cosine transform
698739 ! N should be odd:
699740
@@ -763,6 +804,14 @@ SUBROUTINE InitCFFT( NumSteps, FFT_Data, NormalizeIn, ErrStat )
763804
764805 IF ( PRESENT (ErrStat) ) ErrStat = ErrID_None
765806
807+ ! Verify FFTPACK's default REAL kind matches this wrapper's (SiKi)
808+
809+ CALL CheckFFTPACKRealKind( ErrStat )
810+ IF ( PRESENT (ErrStat) ) THEN
811+ IF ( ErrStat >= AbortErrLev ) RETURN
812+ ENDIF
813+
814+
766815 ! Number of timesteps in the time series returned from the backward FFT
767816 ! N should be even:
768817
@@ -832,6 +881,14 @@ SUBROUTINE InitFFT( NumSteps, FFT_Data, NormalizeIn, ErrStat )
832881
833882 IF ( PRESENT (ErrStat) ) ErrStat = ErrID_None
834883
884+ ! Verify FFTPACK's default REAL kind matches this wrapper's (SiKi)
885+
886+ CALL CheckFFTPACKRealKind( ErrStat )
887+ IF ( PRESENT (ErrStat) ) THEN
888+ IF ( ErrStat >= AbortErrLev ) RETURN
889+ ENDIF
890+
891+
835892 ! Number of timesteps in the time series returned from the backward FFT
836893 ! N should be even:
837894
@@ -902,6 +959,14 @@ SUBROUTINE InitSINT( NumSteps, FFT_Data, NormalizeIn, ErrStat )
902959
903960 IF ( PRESENT (ErrStat) ) ErrStat = ErrID_None
904961
962+ ! Verify FFTPACK's default REAL kind matches this wrapper's (SiKi)
963+
964+ CALL CheckFFTPACKRealKind( ErrStat )
965+ IF ( PRESENT (ErrStat) ) THEN
966+ IF ( ErrStat >= AbortErrLev ) RETURN
967+ ENDIF
968+
969+
905970 ! Number of timesteps in the time series returned from the sine transform
906971 ! N should be odd:
907972
@@ -994,6 +1059,14 @@ SUBROUTINE InitFFT2D( L, M, FFT_Data, NormalizeIn, ErrStat )
9941059
9951060 IF ( PRESENT (ErrStat) ) ErrStat = ErrID_None
9961061
1062+ ! Verify FFTPACK's default REAL kind matches this wrapper's (SiKi)
1063+
1064+ CALL CheckFFTPACKRealKind( ErrStat )
1065+ IF ( PRESENT (ErrStat) ) THEN
1066+ IF ( ErrStat >= AbortErrLev ) RETURN
1067+ ENDIF
1068+
1069+
9971070 FFT_Data% L = L
9981071 FFT_Data% M = M
9991072
@@ -1155,6 +1228,14 @@ SUBROUTINE InitCFFT2D( L, M, FFT_Data, NormalizeIn, ErrStat )
11551228
11561229 IF ( PRESENT (ErrStat) ) ErrStat = ErrID_None
11571230
1231+ ! Verify FFTPACK's default REAL kind matches this wrapper's (SiKi)
1232+
1233+ CALL CheckFFTPACKRealKind( ErrStat )
1234+ IF ( PRESENT (ErrStat) ) THEN
1235+ IF ( ErrStat >= AbortErrLev ) RETURN
1236+ ENDIF
1237+
1238+
11581239 FFT_Data% L = L
11591240 FFT_Data% M = M
11601241
0 commit comments