1010! Activation (no recompile to toggle): env vars read once in GREGLOADDG:
1111! FVS_GREGDG 1/on/true to enable Greg DG substitution.
1212! FVS_GREGDG_COEF path to greg_dg_coefficients.csv (header + SPCD,n,B0..B6).
13- ! FVS_GREG_CONFDIR dir holding the config CSVs; used to resolve DGDRIVER-selected
14- ! files. Default '/users/PUOM0008/crsfaaron/wt-dgdriver/config'.
1513! FVS_GREG_EMT per-stand extreme min temperature (deg C).
1614! FVS_GREG_TD per-stand temperature difference MWMT-MCMT (deg C).
1715! FVS_GREG_ELEV stand elevation (feet); if unset, 0.
18- !
19- ! DGDRIVER keyword (common /GREGKW/ IDGDRV, GREGKW.f90) selects the coefficient
20- ! file directly, so a keyword-only run needs no FVS_GREGDG / FVS_GREGDG_COEF:
21- ! DGDRIVER 1 -> <confdir>/greg_dg_coefficients.csv (deployed)
22- ! DGDRIVER 2 -> <confdir>/greg_dg_coefficients_refit.csv (refit on our data)
23- ! A mapped IDGDRV both turns the hook on (LGREGDG) and picks the file; it takes
24- ! precedence over FVS_GREGDG_COEF. Unmapped/unset IDGDRV falls back to the env
25- ! var behaviour. NOTE: the 8-column driver-family files (cspi/bgi/esi/elev/emt)
26- ! are NOT loadable by this 9-column reader, so codes other than 1/2 are not yet
27- ! wired here (downstream / out of scope).
2816! ==============================================================================
2917SUBROUTINE GREGLOADDG
3018IMPLICIT NONE
3119INCLUDE ' PRGPRM.f90'
3220INCLUDE ' CONTRL.f90'
3321INCLUDE ' PLOT.f90'
3422INCLUDE ' GREGMC.f90'
35- INCLUDE ' GREGKW.f90'
3623!
3724INTEGER , PARAMETER :: MXG = 600
3825INTEGER GSPCD(MXG)
39- REAL TB(MXG,7 ), TBMAX(MXG)
40- CHARACTER (LEN= 256 ) CVAL, CPATH, CDIR
41- LOGICAL LKWSEL
26+ REAL TB(MXG,7 )
27+ CHARACTER (LEN= 256 ) CVAL, CPATH
4228CHARACTER (LEN= 512 ) LINE
4329INTEGER J, NG, IOS, U, IFIA, NN, ISPC
44- REAL B0,B1,B2,B3,B4,B5,B6,BMX
45- REAL , PARAMETER :: DGMAX_NONE = 1.0E6 ! sentinel: no DBHMAX -> decel==1
30+ REAL B0,B1,B2,B3,B4,B5,B6
4631LOGICAL , SAVE :: LDONE = .FALSE.
4732!
4833IF (LDONE) RETURN
49- ! LKWSEL: did the DGDRIVER keyword set a code we map to a loadable coef file?
50- ! Codes 1 (deployed) and 2 (refit) are the two engine-loadable 9-col files.
51- LKWSEL = (IDGDRV.EQ. 1 .OR. IDGDRV.EQ. 2 )
5234CALL GETENV(' FVS_GREGDG' , CVAL)
53- ! Enable if either the env toggle is on OR a mapped DGDRIVER code was given.
54- ! This makes DGDRIVER self-contained: a keyword-only run needs no env var.
55- IF (.NOT. LKWSEL) THEN
56- IF (CVAL.EQ. ' ' .OR. CVAL(1 :1 ).EQ. ' 0' .OR. CVAL(1 :1 ).EQ. ' n' .OR. CVAL(1 :1 ).EQ. ' N' ) THEN
57- LGREGDG = .FALSE. ; RETURN
58- ENDIF
35+ IF (CVAL.EQ. ' ' .OR. CVAL(1 :1 ).EQ. ' 0' .OR. CVAL(1 :1 ).EQ. ' n' .OR. CVAL(1 :1 ).EQ. ' N' ) THEN
36+ LGREGDG = .FALSE. ; RETURN
5937ENDIF
6038LGREGDG = .TRUE.
6139LDONE = .TRUE.
@@ -69,27 +47,9 @@ SUBROUTINE GREGLOADDG
6947 GPC1 = 0.252 * GDD0 + 0.002 * GTD - 0.035 * GPPT_SM + 0.967 * GDD18
7048 GPC2 = 0.882 * GDD0 + 0.015 * GTD + 0.420 * GPPT_SM - 0.215 * GDD18
7149!
72- ! ---- Coefficient-file resolution ------------------------------------------
73- ! Precedence: a mapped DGDRIVER code selects the file (keyword self-contained);
74- ! otherwise fall back to FVS_GREGDG_COEF (the original env-var behaviour).
75- CPATH = ' '
76- IF (LKWSEL) THEN
77- ! Resolve config dir robustly: FVS_GREG_CONFDIR if set, else a known abs dir.
78- CALL GETENV(' FVS_GREG_CONFDIR' , CDIR)
79- IF (CDIR.EQ. ' ' ) CDIR = ' /users/PUOM0008/crsfaaron/wt-dgdriver/config'
80- ! DGDRIVER code -> coefficient filename mapping.
81- IF (IDGDRV.EQ. 1 ) THEN
82- CPATH = TRIM (CDIR)// ' /greg_dg_coefficients.csv' ! deployed
83- ELSE IF (IDGDRV.EQ. 2 ) THEN
84- CPATH = TRIM (CDIR)// ' /greg_dg_coefficients_refit.csv' ! refit on our data
85- ENDIF
86- WRITE (JOSTND,* ) ' GREGDG: DGDRIVER code ' , IDGDRV, ' selected ' , TRIM (CPATH)
87- ELSE
88- CALL GETENV(' FVS_GREGDG_COEF' , CPATH)
89- ENDIF
50+ CALL GETENV(' FVS_GREGDG_COEF' , CPATH)
9051IF (CPATH.EQ. ' ' ) THEN
91- WRITE (JOSTND,* ) ' GREGDG: no coefficient file (DGDRIVER unset/unmapped and ' , &
92- ' FVS_GREGDG_COEF empty); NOT enabled.'
52+ WRITE (JOSTND,* ) ' GREGDG: FVS_GREGDG set but FVS_GREGDG_COEF empty; NOT enabled.'
9353 LGREGDG = .FALSE. ; RETURN
9454ENDIF
9555U = 68
@@ -101,33 +61,20 @@ SUBROUTINE GREGLOADDG
10161READ (U,' (A)' ,IOSTAT= IOS) LINE ! header
10262NG = 0
1036310 CONTINUE
104- READ (U,' (A) ' ,IOSTAT= IOS) LINE
64+ READ (U,* ,IOSTAT= IOS) IFIA, NN, B0, B1, B2, B3, B4, B5, B6
10565 IF (IOS.NE. 0 ) GO TO 20
106- IF (LINE.EQ. ' ' ) GO TO 10
10766 IF (NG.GE. MXG) GO TO 20
108- ! Try 10-field record (SPCD,n,B0..B6,DBHMAX); if that fails, fall back to the
109- ! legacy 9-field record and leave DBHMAX at the sentinel (decel==1).
110- BMX = DGMAX_NONE
111- READ (LINE,* ,IOSTAT= IOS) IFIA, NN, B0, B1, B2, B3, B4, B5, B6, BMX
112- IF (IOS.NE. 0 ) THEN
113- BMX = DGMAX_NONE
114- READ (LINE,* ,IOSTAT= IOS) IFIA, NN, B0, B1, B2, B3, B4, B5, B6
115- IF (IOS.NE. 0 ) GO TO 10
116- ENDIF
117- IF (BMX.LE. 0.0 ) BMX = DGMAX_NONE
11867 NG = NG + 1
11968 GSPCD(NG) = IFIA
12069 TB(NG,1 )= B0; TB(NG,2 )= B1; TB(NG,3 )= B2; TB(NG,4 )= B3
12170 TB(NG,5 )= B4; TB(NG,6 )= B5; TB(NG,7 )= B6
122- TBMAX(NG)= BMX
12371 GO TO 10
1247220 CONTINUE
12573CLOSE (U)
12674NGREGDG = NG
12775!
12876DO ISPC= 1 ,MAXSP
12977 GHAVE_DG(ISPC) = .FALSE.
130- GDGMAX(ISPC) = DGMAX_NONE
13178 IFIA = - 1
13279 IF (FIAJSP(ISPC).NE. ' ' ) THEN
13380 READ (FIAJSP(ISPC),* ,IOSTAT= IOS) IFIA
@@ -138,7 +85,6 @@ SUBROUTINE GREGLOADDG
13885 IF (GSPCD(J).EQ. IFIA) THEN
13986 GDG(ISPC,1 )= TB(J,1 ); GDG(ISPC,2 )= TB(J,2 ); GDG(ISPC,3 )= TB(J,3 )
14087 GDG(ISPC,4 )= TB(J,4 ); GDG(ISPC,5 )= TB(J,5 ); GDG(ISPC,6 )= TB(J,6 ); GDG(ISPC,7 )= TB(J,7 )
141- GDGMAX(ISPC) = TBMAX(J)
14288 GHAVE_DG(ISPC) = .TRUE.
14389 EXIT
14490 ENDIF
@@ -147,7 +93,6 @@ SUBROUTINE GREGLOADDG
14793ENDDO
14894WRITE (JOSTND,* ) ' GREGDG enabled: ' , NG, ' species; DD0=' , GDD0, ' TD=' , GTD, &
14995 ' PPT_SM=' , GPPT_SM, ' DD18=' , GDD18, ' PC1=' , GPC1, ' PC2=' , GPC2
150- IF (IDGDRV.GE. 0 ) WRITE (JOSTND,* ) ' GREGDG keyword DGDRIVER code=' , IDGDRV
15196RETURN
15297END
15398
@@ -159,7 +104,6 @@ SUBROUTINE GREGDGV(ISPC, DBH, CR, HT, BAL, G)
159104INCLUDE ' GREGMC.f90'
160105INTEGER ISPC
161106REAL DBH, CR, HT, BAL, G, Z, CRC, HTC, BALC, ARGNUM, ARGDEN
162- REAL DECEL, DBHMX, XR
163107CRC = CR; IF (CRC.LT. 1.0E-4 ) CRC = 1.0E-4
164108HTC = HT; IF (HTC.LT. 0.0 ) HTC = 0.0
165109BALC = BAL; IF (BALC.LT. 0.0 ) BALC = 0.0
@@ -171,34 +115,5 @@ SUBROUTINE GREGDGV(ISPC, DBH, CR, HT, BAL, G)
171115IF (Z.GT. 5.0 ) Z = 5.0
172116IF (Z.LT. - 30.0 ) Z = - 30.0
173117G = EXP (Z); IF (G.LT. 0.0 ) G = 0.0
174- ! ---- Size-based deceleration (COR-style plateau) --------------------------
175- ! Native NE-TWIGS DG plateaus via a size calibration this hook otherwise omits,
176- ! so an unbounded compounding loop runs QMD away over multi-century horizons.
177- ! Multiply the annual increment by a logistic that is ~1 until DBH nears the
178- ! per-species maximum diameter GDGMAX (from the DBHMAX coef column) and ramps
179- ! to 0 as DBH -> GDGMAX. Onset ~85% of max, half-width 4% of max, so trees far
180- ! below max (all short remeasurement intervals) are essentially untouched.
181- ! Sentinel GDGMAX (no DBHMAX column) leaves DECEL=1 -> exact old behaviour.
182- DBHMX = GDGMAX(ISPC)
183- IF (DBHMX .LT. 1.0E5 ) THEN
184- XR = (DBH - 0.85 * DBHMX) / (0.04 * DBHMX)
185- IF (XR .GT. 30.0 ) THEN
186- DECEL = 0.0
187- ELSE IF (XR .LT. - 30.0 ) THEN
188- DECEL = 1.0
189- ELSE
190- DECEL = 1.0 / (1.0 + EXP (XR))
191- ENDIF
192- IF (DECEL .LT. 0.0 ) DECEL = 0.0
193- IF (DECEL .GT. 1.0 ) DECEL = 1.0
194- G = G * DECEL
195- ENDIF
196118RETURN
197119END
198-
199- BLOCK DATA GREGKWBD
200- ! Initialise keyword-selected driver codes to -1 (unset) before any keyword runs.
201- IMPLICIT NONE
202- INCLUDE ' GREGKW.f90'
203- DATA IDGDRV /- 1 / , IMORTDRV /- 1 /
204- END
0 commit comments