Skip to content

DG expand: wire Greg DG hook into NE variant (PC form, DGGD/PTBALT call site)#107

Open
holoros wants to merge 13 commits into
mainfrom
feat/dg-ne
Open

DG expand: wire Greg DG hook into NE variant (PC form, DGGD/PTBALT call site)#107
holoros wants to merge 13 commits into
mainfrom
feat/dg-ne

Conversation

@holoros

@holoros holoros commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Wires the Greg Johnson DG hook (GREGDGV/GREGLOADDG) into the NE variant and updates all shared files to the PC-form equations, matching the pattern established by #103 (SN), #104 (PN), #105 (EM), #106 (WC).

Changes

  • src-converted/common/GREGMC.f90 — replace GEMT/GELEV with GDD0/GTD/GPPT_SM/GDD18/GPC1/GPC2 in COMMON /GREGMR/
  • src-converted/base/gregdghg.f90 — GREGDGV drops ELEV/EMT args; GREGLOADDG reads DD0/TD/PPT_SM/DD18 env vars and computes PC1/PC2
  • src-converted/common/GREGKW.f90 — COMMON /GREGKW/ include needed by gregdghg.f90
  • src-converted/ne/dgf.f90 — update CALL GREGDGV to drop GELEV, GEMT (NE uses DGGD and PTBALT(I))
  • config/greg_dg_coefficients.csv — regenerated from dg_parms.RDS in PC form (83 spp; SPCD 653 dropped, non-convergence)

Runtime env vars

FVS_GREGDG=1 (enable hook, unchanged), FVS_GREG_DD0, FVS_GREG_TD, FVS_GREG_PPT_SM, FVS_GREG_DD18 (replace ELEV/EMT)

Verification

FVSne built on Cardinal with gcc/12.3.0; gregdgv_ and gregloaddg_ confirmed linked (2 syms).

Notes

Do not merge without Greg Johnson sign-off (matches policy on #103-106). SPCD 653 excluded from CSV; Greg flagged as known.

holoros added 13 commits July 3, 2026 12:05
Add DGDRIVER (slot 149) and MORTDRVR (150; 8-char FVS limit on MORTDRIVER)
to the base keyword TABLE (keywds.f90). initre.f90 handlers mirror the
GOMPMORT/GOMPON pattern: read the driver code into the new /GREGKW/ common
(IDGDRV,IMORTDRV; defaults DG=cspi(2), mort=bgi(3), matching config_loader).
GREGLOADDG consults IDGDRV. GREGKW.f90 common + GREGKWBD block data init to -1.
Compiles clean (FVSne, 0 failures); keywords present in binary; gregkwbd_ linked.
Per-driver coefficient-file resolution is the documented downstream step.
Extends the Greg DG native hook to CS and LS for the in-engine 3-arm A/B.
Adapted the ne/dgf.f90 hook to each variant vars (LS also needed VARCOM.f90
for PTBALT). Added ../base/gregdghg.f90 to FVScs/FVSls sourceLists (was NE-only,
caused undefined gregloaddg_/gregdgv_ at link). Hook stays non-default (env/keyword
gated). A/B result: hook wins NE, marginal CS, LOSES LS (over-predicts).
… + wc

LS bug: ls/dgf.f90 passed PTBALT(I) to GREGDGV but LS never populates PTBALT at
DG time (no BADIST) so it was 0 -> competition term vanished -> over-predict.
Fix: pass the local BAL. LS hook now RMSE 0.1222 (native 0.1212), bias -0.005
(native -0.020): competitive, not a loss. The LS over-shoot was a wiring bug,
not coefficient scale.
DGDRIVER: GREGLOADDG now resolves the coef file from the keyword code (1=deployed,
2=refit) and self-activates the hook; env-var fallback kept. Validated end to end.
nc/wc: hook wired (+ gregdghg.f90 in their sourceLists). A/B: WC hook wins
(0.1154 vs 0.1182); NC hook over-predicts (native already well-calibrated).
Landscape: hook helps where native under-predicts, hurts where native is calibrated.
IE/SN/AK hook wired (local BAL, no LS-style zero-BAL). Confirming A/B: IE CONFIRM
(hook 0.0973, bias +0.0003), AK CONFIRM (provisional, n=11), SN REFUTE (native
under-predicts but hook overshoots +0.083 -> keep native). DGDRIVER policy
deployed: config/dg_hook_policy.json + config_loader.dg_hook_policy/dgdriver_keyword,
opt-in (tag byte-identical). HOOK confirmed: ne,cs,ls,wc,ie (+ak provisional);
NATIVE: rest incl SN. BAKUZIS GATE FLAG: hook runs away in DBH long-term (no
max-size asymptote); short-interval prediction only until a DG deceleration is added.
GREGDGV: logistic size-decel (onset 85% of per-species DBHMAX from FIA p99, new
GDGMAX array in GREGMC). Long-term QMD plateaus 19-31 in at 200yr (was 28-50,
native 13-31); site ordering/monotonicity intact; short-interval NE A/B preserved
(0.2135 vs 0.2123). Backward compatible (sentinel if no DBHMAX col). Hook coef set
greg_dg_coefficients_refit_decel.csv (refit + DBHMAX). Policy: Bakuzis caveat
RESOLVED, AK CONFIRMED (34 plots). Hook now validated short AND long horizon.
… policy

OP hook wired (correct local BAL, verified) but the confirming A/B REFUTES the
hook-on call: bias improves ~25% but RMSE worsens (0.1354 vs native 0.1313),
trades bias for variance. Policy: OP=NATIVE (like SN). dg_hook_policy.json updated
(OP native, confirmed set ne/cs/ls/wc/ie/ak, mortality status note). Mortality
size-extension kept as an artifact (needs all morts.f90 callers updated before merge).
eta = b0 + b1*(cr+.01)^b2 + b3*cch^b4 + b5*log(DBH) + b6*BGI; GB->7 cols (GOMPMC);
GOMPLOAD reads 6th/7th cols backward-compatible (5-col=Greg crown-only default,
6=+size, 7=+BGI); BGI per-stand via FVS_GOMP_BGI. All 21 morts.f90 callers pass
DBH(I). NE 4-arm: native 0.755/crown 0.451/size 0.434/size+BGI 0.422 (AUC 0.662).
Crown-only (Greg source form) stays default; size/BGI opt-in. Build verified in
worktree (ne/ca/sn exit 0, identical source).
…riant size+BGI policy

MORTDRVR/MORTDRIVER previously carried a 0-5 driver-family scheme
(0=none,1=elev,2=cspi,3=bgi,4=esi,5=emt) copied from DGDRIVER. That never
matched what merged into the engine: GOMPSURV is an additive TIER
structure (crown-only 5-coef -> +size 6-coef -> +size+BGI 7-coef), not a
swappable single driver. Redefine MORTDRVR/IMORTDRV to select the tier:
0=crown-only (default, unchanged behavior), 1=size, 2=size+BGI.

- src-converted/vbase/initre.f90: option 150 handler rewritten for the
  0/1/2 tier scheme, bare keyword defaults to the recommended tier
  (size+BGI); new echo format names the tier instead of the driver family.
- src-converted/common/GREGKW.f90: IMORTDRV comment corrected to describe
  the tier scheme; -1 unset sentinel unchanged for both codes.
- src-converted/base/gompmort.f90: GOMPLOAD includes GREGKW.f90 and logs
  the keyword-selected tier (reproducibility-logging only, matching the
  DGDRIVER precedent -- actual tier selection is still via the
  FVS_GOMPIT_COEF file path).
- config/mort_hook_policy.json: per-variant size+BGI policy from the
  6-variant 4-arm A/B (native/crown-only/size/size+BGI) on held-out FIA
  remeasurement pairs. size+BGI wins on log-loss and AUC in all six
  confirmed variants (ne, cs, ls, wc, ie, ak); size-only is retained but
  not recommended standalone. ak flagged low-confidence (33-plot sample).
- config/config_loader.py: mort_hook_policy()/mortdriver_keyword()
  helpers mirroring dg_hook_policy()/dgdriver_keyword().

Rebuilt FVSne (0 build failures); smoke-tested MORTDRVR in the keyword
table, the new tier echo string, and gregkwbd_ link via strings/nm.
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.
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant