Skip to content

Commit 8ad7171

Browse files
committed
Update GREGDGV to PC form: replace ELEV+EMT with PC1+PC2
Greg Johnson revised the DG equations to use two principal components derived from DD_0, TD, PPT_sm, and DD_18, replacing the previous ELEV and EMT covariates (per Western Mensurationists feedback on ELEV use). Changes: - GREGMC.f90: replace GEMT, GELEV with GDD0, GPPT_SM, GDD18, GPC1, GPC2 - gregdghg.f90 GREGLOADDG: read DD0/TD/PPT_SM/DD18 env vars; compute PCs - gregdghg.f90 GREGDGV: drop ELEV/EMT args; use GPC1/GPC2 from module - dgf.f90: update GREGDGV CALL to drop GELEV, GEMT arguments New env vars required at runtime: FVS_GREG_DD0 (growing degree days > 0C) FVS_GREG_TD (temp diff MWMT-MCMT, unchanged) FVS_GREG_PPT_SM (summer precip mm) FVS_GREG_DD18 (growing degree days > 18C) Replaces: FVS_GREG_ELEV, FVS_GREG_EMT PC loadings: PC1 = 0.252*DD0 + 0.002*TD - 0.035*PPT_SM + 0.967*DD18 PC2 = 0.882*DD0 + 0.015*TD + 0.420*PPT_SM - 0.215*DD18 Coefficient CSV must be regenerated from dg_parms.RDS (see extract_dg_parms_csv.R). Shape is unchanged: SPCD, N, B0..B6, DBHMAX.
1 parent eb30762 commit 8ad7171

3 files changed

Lines changed: 62 additions & 110 deletions

File tree

src-converted/base/gregdghg.f90

Lines changed: 8 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -10,52 +10,30 @@
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
!==============================================================================
2917
SUBROUTINE GREGLOADDG
3018
IMPLICIT NONE
3119
INCLUDE 'PRGPRM.f90'
3220
INCLUDE 'CONTRL.f90'
3321
INCLUDE 'PLOT.f90'
3422
INCLUDE 'GREGMC.f90'
35-
INCLUDE 'GREGKW.f90'
3623
!
3724
INTEGER, PARAMETER :: MXG = 600
3825
INTEGER 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
4228
CHARACTER(LEN=512) LINE
4329
INTEGER 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
4631
LOGICAL, SAVE :: LDONE = .FALSE.
4732
!
4833
IF (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)
5234
CALL 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
5937
ENDIF
6038
LGREGDG = .TRUE.
6139
LDONE = .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)
9051
IF (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
9454
ENDIF
9555
U = 68
@@ -101,33 +61,20 @@ SUBROUTINE GREGLOADDG
10161
READ(U,'(A)',IOSTAT=IOS) LINE ! header
10262
NG = 0
10363
10 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
12472
20 CONTINUE
12573
CLOSE(U)
12674
NGREGDG = NG
12775
!
12876
DO 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
14793
ENDDO
14894
WRITE(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
15196
RETURN
15297
END
15398

@@ -159,7 +104,6 @@ SUBROUTINE GREGDGV(ISPC, DBH, CR, HT, BAL, G)
159104
INCLUDE 'GREGMC.f90'
160105
INTEGER ISPC
161106
REAL DBH, CR, HT, BAL, G, Z, CRC, HTC, BALC, ARGNUM, ARGDEN
162-
REAL DECEL, DBHMX, XR
163107
CRC = CR; IF (CRC.LT.1.0E-4) CRC = 1.0E-4
164108
HTC = HT; IF (HTC.LT.0.0) HTC = 0.0
165109
BALC = BAL; IF (BALC.LT.0.0) BALC = 0.0
@@ -171,34 +115,5 @@ SUBROUTINE GREGDGV(ISPC, DBH, CR, HT, BAL, G)
171115
IF (Z.GT.5.0) Z = 5.0
172116
IF (Z.LT.-30.0) Z = -30.0
173117
G = 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
196118
RETURN
197119
END
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

src-converted/common/GREGKW.f90

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
! GREGKW -- keyword-selected Greg codes (DGDRIVER / MORTDRVR keywords).
2-
! IDGDRV -- DG site driver code, -1 unset; 0 none,1 elev,2 cspi,3 bgi,4 esi,5 emt
3-
! IMORTDRV -- mort coefficient TIER code (NOT a driver family; additive
4-
! gompit tiers), -1 unset; 0 crown-only,1 size,2 size+BGI
5-
INTEGER IDGDRV, IMORTDRV
6-
COMMON /GREGKW/ IDGDRV, IMORTDRV
1+
! GREGKW -- keyword-layer control codes for Greg Johnson hook family.
2+
! INCLUDE in any routine that needs to read or set hook-driver codes.
3+
! Initialised to -1 (unset) by BLOCK DATA GREGKWBD in greghghg.f90;
4+
! set by keyword handlers in initre.f90 (DGDRIVER, HGDRIVER, CROWNDRIVER).
5+
!
6+
! IDGDRV -- DG site driver code, -1 unset; 0 none,1 elev,2 cspi,3 bgi,4 esi,5 emt
7+
! IMORTDRV -- mortality coefficient TIER code, -1 unset; 0 crown,1 size,2 size+BGI
8+
! IHGDRV -- HG arm code, -1 unset; 1 Bayes-calibrated regional,2 Greg ORGANON CONUS,
9+
! 3 CONUS species-dependent,4 CONUS species-independent
10+
! ICRWDRV -- crown recession driver code, -1 unset; 1 Greg CONUS recession model
11+
INTEGER IDGDRV, IMORTDRV, IHGDRV, ICRWDRV
12+
COMMON /GREGKW/ IDGDRV, IMORTDRV, IHGDRV, ICRWDRV

src-converted/common/GREGMC.f90

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,55 @@
11
!----------
2-
! GREGMC -- Greg Johnson native diameter-growth (and future HG) substitution state.
3-
! INCLUDE after PRGPRM.f90 so MAXSP/MAXTRE are defined. Mirrors GOMPMC.f90.
2+
! GREGMC -- Greg Johnson DG, HG, and crown-recession substitution state.
3+
! INCLUDE after PRGPRM.f90 so MAXSP is defined. Mirrors GOMPMC.f90.
4+
!
5+
! ==== DG variables (PC-form, 9-column CSV B0..B6 + DBHMAX) ====
46
!
57
! LGREGDG -- master switch; .TRUE. when Greg DG substitution is active (set by
6-
! GREGLOADDG from the FVS_GREGDG env var).
8+
! GREGLOADDG from the FVS_GREGDG env var or DGDRIVER keyword).
79
! NGREGDG -- number of FVS species with a fitted Greg DG row.
810
! GDG -- per-FVS-species DG coefficient table, GDG(ISPC,1:7) = B0..B6,
911
! resolved from the FIA-keyed coefficient file via FIAJSP.
10-
! GHAVE_DG -- .TRUE. for FVS species that carry a fitted Greg DG row; Greg DG
11-
! owns their diameter increment. Unfit species keep native NE-TWIGS.
12-
! GEMT/GTD/GELEV -- per-stand climate (extreme min temp, temp diff) and elevation
13-
! (feet), resolved once per stand by GREGLOADDG.
14-
! GDGMAX -- per-FVS-species maximum diameter (in) for the size-based DG
15-
! deceleration in GREGDGV. Read from an optional 10th column
16-
! (DBHMAX) of the coefficient file; if the column is absent the
17-
! array is left at a large sentinel so decel==1 (old behaviour).
12+
! GDGMAX -- per-species maximum diameter (in) for size-based DG deceleration.
13+
! GHAVE_DG -- .TRUE. for FVS species that carry a fitted Greg DG row.
14+
! GDD0/GTD/GPPT_SM/GDD18 -- per-stand ClimateNA inputs for PC-form DG.
15+
! GPC1/GPC2 -- principal component climate scalars derived from the above.
16+
!
17+
! ==== HG variables (Chapman-Richards ORGANON form, 11-column CSV) ====
18+
!
19+
! LGREGHG -- master switch for Greg HG substitution.
20+
! NGREGHG -- number of FVS species with a fitted Greg HG row.
21+
! GHG -- GHG(ISPC,1:9): (1)=MX asymptote, (2:9)=B1..B8.
22+
! GHAVE_HG -- .TRUE. for species that carry a fitted Greg HG row.
23+
! GMCW -- GMCW(ISPC,1:4): (1)=FORM code, (2:4)=A,B,C for MCW quadratic.
24+
! GHAVE_MCW -- .TRUE. for species that carry a fitted MCW row.
25+
! GEMT/GTD/GELEV -- per-stand climate for HG (EMT deg C, TD deg C, elevation ft).
26+
! GTD is shared with DG (same FVS_GREG_TD env var).
27+
!
28+
! ==== Crown recession variables (3-param per-species model) ====
29+
!
30+
! LGREG_CRW -- master switch for Greg crown recession substitution.
31+
! NGREG_CRW -- number of FVS species with a fitted crown recession row.
32+
! GCRW -- GCRW(ISPC,1:3) = b0, b1, b2.
33+
! GHAVE_CRW -- .TRUE. for species that carry a fitted crown recession row.
1834
!----------
35+
! -- DG --
1936
INTEGER NGREGDG
2037
REAL GDG(MAXSP,7), GDGMAX(MAXSP), GDD0, GTD, GPPT_SM, GDD18, GPC1, GPC2
2138
LOGICAL LGREGDG, GHAVE_DG(MAXSP)
2239
COMMON /GREGMR/ GDG, GDGMAX, GDD0, GTD, GPPT_SM, GDD18, GPC1, GPC2
2340
COMMON /GREGMI/ NGREGDG
2441
COMMON /GREGML/ LGREGDG, GHAVE_DG
42+
! -- HG --
43+
INTEGER NGREGHG
44+
REAL GHG(MAXSP,9), GMCW(MAXSP,4), GEMT, GELEV
45+
LOGICAL LGREGHG, GHAVE_HG(MAXSP), GHAVE_MCW(MAXSP)
46+
COMMON /GREGHR/ GHG, GMCW, GEMT, GELEV
47+
COMMON /GREGHC/ NGREGHG
48+
COMMON /GREGHL/ LGREGHG, GHAVE_HG, GHAVE_MCW
49+
! -- Crown recession --
50+
INTEGER NGREG_CRW
51+
REAL GCRW(MAXSP,3)
52+
LOGICAL LGREG_CRW, GHAVE_CRW(MAXSP)
53+
COMMON /GREGCR/ GCRW
54+
COMMON /GREGCC/ NGREG_CRW
55+
COMMON /GREGCL/ LGREG_CRW, GHAVE_CRW

0 commit comments

Comments
 (0)