1818# '@export
1919rpath <- function (Rpath.params , eco.name = NA , eco.area = 1 ) {
2020 # Need to define variables to eliminate check() note about no visible binding
21- Type <- Group <- DetInput <- ProdCons <- PB <- QB <- noB <- noEE <- alive <- NULL
21+ Type <- Group <- DetInput <- ProdCons <- PB <- QB <- noB <- noEE <- alive <- noPB <- NULL
2222 BEE <- Biomass <- Q <- BioAcc <- BioQB <- diag.a <- EEa <- B <- M0 <- NULL
2323 QBloss <- Unassim <- Ex <- NULL
2424
@@ -62,7 +62,9 @@ rpath <- function(Rpath.params, eco.name = NA, eco.area = 1) {
6262 model [is.na(DetInput ), DetInput : = 0 ]
6363
6464 # fill in GE(PQ), QB, or PB from other inputs
65- GE <- ifelse(is.na(model [, ProdCons ]), model [, PB / QB ], model [, ProdCons ])
65+ # KYA Aug 2025 - changed this logic so PC would be recalculated if PB and QB supplied
66+ # GE <- ifelse(is.na(model[, ProdCons]), model[, PB / QB], model[, ProdCons])
67+ GE <- ifelse(! is.na(model [, QB ]) & ! is.na(model [, PB ]), model [, PB / QB ], model [, ProdCons ])
6668 QB.1 <- ifelse(is.na(model [, QB ]), model [, PB / GE ], model [, QB ])
6769 PB.1 <- ifelse(is.na(model [, PB ]), model [, ProdCons * QB ], model [, PB ])
6870 model [, QB : = QB.1 ]
@@ -97,11 +99,16 @@ rpath <- function(Rpath.params, eco.name = NA, eco.area = 1) {
9799 model [, noEE : = 0 ]
98100 model [, alive : = 0 ]
99101 model [, BEE : = 0 ]
102+ model [, noPB : = 0 ]
100103 model [is.na(Biomass ), noB : = 1 ]
101104 model [is.na(EE ), noEE : = 1 ]
102105 model [Type < 2 , alive : = 1 ]
103- model [noB == 0 & noEE == 0 , BEE : = 1 ]
104-
106+ model [noB == 0 & noEE == 0 , BEE : = 1 ]
107+ model [BEE == 1 & is.na(PB ), noPB : = 1 ]
108+
109+ if (any(model $ Type == 0 & is.na(model $ QB ) & is.na(model $ ProdCons ))){
110+ stop(" A consumer is missing both QB and ProdCons - balance failed. Use check.rpath.params() to diagnose." )
111+ }
105112 # define detritus fate matrix
106113 detfate <- model [, (10 + 1 ): (10 + ndead ), with = F ]
107114 detdetfate <- model [Type == 2 , (10 + 1 ): (10 + ndead ), with = F ]
@@ -118,6 +125,7 @@ rpath <- function(Rpath.params, eco.name = NA, eco.area = 1) {
118125 # Set up A matrix
119126 living [noEE == 1 , diag.a : = Biomass * PB ]
120127 living [noEE == 0 , diag.a : = PB * EE ]
128+ living [noPB == 1 , diag.a : = Biomass * EE ] # this needs to be after noEE==0 case
121129
122130 # Special case where B and EE are known then need to solve for BA
123131 # living[BEE == 1, b := b - (Biomass * PB * EE)]
@@ -134,6 +142,11 @@ rpath <- function(Rpath.params, eco.name = NA, eco.area = 1) {
134142 A <- A - QBDCa
135143 # Switch flag back
136144 # living[BEE == 1, noB := 0]
145+
146+ # Check for any missing info that will prevent solving
147+ if (any(is.na(A ))){
148+ stop(" Model is missing parameters - can't be balanced. Use check.rpath.params() to diagnose." )
149+ }
137150
138151 # Generalized inverse does the actual solving
139152 # Invert A and multiple by b to get x (unknowns)
@@ -146,6 +159,9 @@ rpath <- function(Rpath.params, eco.name = NA, eco.area = 1) {
146159 living [, B : = x * noB ]
147160 living [is.na(Biomass ), Biomass : = B ]
148161
162+ living [, PBa : = x * noPB ]
163+ living [is.na(PB ), PB : = PBa ]
164+
149165 # detritus EE calcs
150166 living [, M0 : = PB * (1 - EE )]
151167 living [, QBloss : = QB ]
@@ -182,7 +198,7 @@ rpath <- function(Rpath.params, eco.name = NA, eco.area = 1) {
182198 inDetB <- model [(nliving + 1 ): (nliving + ndead ), Biomass ]
183199 DetPB <- ifelse(is.na(inDetPB ), Default_Detrital_PB , inDetPB )
184200 DetB <- ifelse(is.na(inDetB ), detinputs / DetPB , inDetB )
185- DetPB <- detinputs / DetB
201+ DetPB <- as.numeric( detinputs ) / DetB
186202
187203 # Trophic Level calcs
188204 b <- rep(1 , ngroups )
@@ -217,16 +233,20 @@ rpath <- function(Rpath.params, eco.name = NA, eco.area = 1) {
217233 # to match header file format (replacing NAs with 0.0s)
218234 Bplus <- c(living [, Biomass ], DetB , rep(0.0 , ngear ))
219235
220- PBplus <- model [, PB ]
221- PBplus [(nliving + 1 ): (nliving + ndead )] <- DetPB
236+ # PBplus <- model[, PB]
237+ # PBplus[(nliving + 1):(nliving + ndead)] <- DetPB
238+ PBplus <- c(living [,PB ],DetPB , rep(0.0 , ngear ))
222239 PBplus [is.na(PBplus )] <- 0.0
223240
224241 EEplus <- c(EE , rep(0.0 , ngear ))
225242
226243 QBplus <- model [, QB ]
244+ QBplus [is.na(QBplus ) & PBplus > 0.0 & ! (is.na(GE ) | is.nan(GE ) | is.infinite(GE ))] <-
245+ (PBplus / GE )[is.na(QBplus ) & PBplus > 0.0 & ! (is.na(GE ) | is.nan(GE ) | is.infinite(GE ))]
227246 QBplus [is.na(QBplus )] <- 0.0
228247
229- GE [is.na(GE )] <- 0.0
248+ GE <- PBplus / QBplus
249+ GE [is.na(GE ) | is.nan(GE ) | is.infinite(GE )] <- 0.0
230250
231251 RemPlus <- model [, totcatch ]
232252 RemPlus [is.na(RemPlus )] <- 0.0
@@ -337,6 +357,9 @@ rpath.stanzas <- function(Rpath.params){
337357 Group <- Biomass <- R <- NageS <- bs.denom <- bs <- qs.denom <- qs <- Cons <- NULL
338358 QB <- BAB <- Ex <- NULL
339359
360+ # Added Aug 2025 - if no stanzas, silently return original (prob no warning needed?)
361+ if (Rpath.params $ stanza $ NStanzaGroups == 0 ){return (Rpath.params )}
362+
340363 # Determine the total number of groups with multistanzas
341364 Nsplit <- Rpath.params $ stanza $ NStanzaGroups
342365 groupfile <- Rpath.params $ stanza $ stgroups
0 commit comments