Skip to content

Fix(#87): add box-level discard and rec-catch tracers once per box - #91

Open
jacobkasper wants to merge 1 commit into
devfrom
bug/i87-tracer-discards-per-layer
Open

jacobkasper wants to merge 1 commit into
devfrom
bug/i87-tracer-discards-per-layer

Conversation

@jacobkasper

Copy link
Copy Markdown
Collaborator

Justification

Fixes #87.

Problem. Discards in OutTOTCATCH.nc (Tot_*_Discards) and OutCATCH.nc (*_Discard_FC*) are overstated relative to OutDiscard.txt. In our model, haddock (FHA) discards in the NetCDF output are about 44% too high in every year. Tot_*_RecCatch is built the same way and is affected by the same mechanism. These tracers are output only, so model dynamics are unaffected, but anyone reading discards or recreational catch from the NetCDF files (for example in R post-processing) gets inflated values that don't match the text outputs.

Cause. Harvest_Update_Total_Catch (atHarvest.c) is called once per water-column layer (from Water_Column_Box) and again from EpibenthicBox. The catch tracers read bm->Catch[box][sp][nf][layer], which is layer-indexed, so adding them per layer is correct. But bm->Discards[box][sp][nf] and bm->RecCatch[box][sp][nf] have no layer index: they accumulate as the box's layers are processed, and the running box total is added to the tracers at every layer call. The inflation factor lies between 1 and the number of layers in the box, depending on how discards are distributed vertically.

Fix. The tracer loop is split in two:

  • catch tracers (CaughtByFisheryTracers, totCatchTracer) are still added per layer, exactly as before;
  • discard and rec-catch tracers (DiscardedByFisheryTracers, totDiscardsTracer, totRecCatchTracer) are added once per box: at layer 0 in the water-column call, which is the last layer processed (the existing effort-tracer block relies on the same fact, if (!bm->current_layer && (habitat == WC))), and for epibenthic invertebrates (non-vertebrate, habitatType != WC) in the EPIFAUNA call.

Only output tracers change.

Evidence

OutDiscard.txt is written from CatchSum[sp][tscodiscard_id], which receives exactly the same increments as bm->Discards (in Harvest_Do_Fishing_And_ByCatch and in the dependent-discards code in atecology.c), so it is a valid reference.

FHA, Tot_FHA_Discards summed over boxes divided by OutDiscard.txt, 800-day runs on dev (d693861):

Day Before With this PR
365 1.443 1.000
730 1.442 1.000

The "before" run was dev with #86 applied, which changes only the OutCatchPerFishery.txt accounting and doesn't touch these tracers. An earlier 10-year run on main (ab323c7) gave 1.441–1.447 in every year before the change and 1.000 in every year after it. That also confirms layer 0 is processed last in each box; otherwise the ratio would fall below 1.

The catch tracers are unaffected: the largest difference between Tot_*_Catch (summed over boxes) and OutCatch.txt, over all species and years, is 4.7e-7 t in both builds, which is the print precision of OutCatch.txt. OutCatch.txt and OutDiscard.txt are identical between the two builds.

Not tested

  • The epibenthic branch: our model has no fished invertebrates.
  • Recreational catch: our model has no recreational catch.

Related, not changed here

  • Avg_Catch_Sze_FC* has the long name "Total effort of fishery ...", copied from the effort variable.
  • OutRecCatch.txt is built from bm->TotCumRecCatch, which Harvest_Init_Box_Arrays fills with bm->TotCumRecCatch[sp][ij] += bm->RecCatch[ij][sp][ij]; inside a loop over fisheries n, i.e. using the box index ij in both fishery slots. If the second dimension of TotCumRecCatch is fisheries (as its summation in writeAnnCatch implies), then for any recreational fishery this reads and writes out of bounds for boxes ≥ K_num_fisheries. Possibly worth its own issue.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Other change (if none of the other choices apply)

Further comments

  • I've created an issue
  • This is NA

No change to inputs, parameters or intended behaviour; the NetCDF discard and rec-catch output now agrees with the text outputs.

Reviewer instructions:

  1. Build this branch and dev.
  2. Run any model with fishing and discards for a little over two years, e.g. tstop 800 day, with toutstart, toutinc and toutfinc at 365 day.
  3. In each output folder:
library(ncdf4)
od <- read.table("OutDiscard.txt", header = TRUE)
oc <- read.table("OutCatch.txt",   header = TRUE)
sp <- setdiff(names(od), "Time")

nc <- nc_open("OutTOTCATCH.nc")
t_day   <- round(nc$dim$t$vals / 86400, 1)
box_sum <- function(v) if (v %in% names(nc$var)) colSums(ncvar_get(nc, v)) else rep(NA, length(t_day))
nc_dis   <- sapply(sp, \(s) box_sum(paste0("Tot_", s, "_Discards")))
nc_catch <- sapply(sp, \(s) box_sum(paste0("Tot_", s, "_Catch")))
nc_close(nc)

keep      <- t_day > 0 & t_day %% 365 == 0
txt_dis   <- as.matrix(od[match(t_day[keep], od$Time), sp])
txt_catch <- as.matrix(oc[match(t_day[keep], oc$Time), sp])
has_dis   <- colSums(txt_dis) > 0

# Discards: NetCDF / OutDiscard.txt, for species with discards
round(cbind(Time = t_day[keep], nc_dis[keep, has_dis, drop = FALSE] / txt_dis[, has_dis, drop = FALSE]), 3)
# Catch: largest |NetCDF - OutCatch.txt| over all species and years
max(abs(nc_catch[keep, ] - txt_catch), na.rm = TRUE)
  1. Confirm the model output is unchanged: diff <dev_run>/OutCatch.txt <branch_run>/OutCatch.txt and the same for OutDiscard.txt should both report no differences.

Expected:

  • dev: ratios above 1 for species with discards (about 1.44 for FHA in our model; the factor depends on each species' vertical distribution).
  • This branch: 1.000 for every species with discards.
  • Both builds: the catch difference at print precision (about 1e-6 t or less).

Reviewers with a model that has fished invertebrates with discards, or a recreational fishery, could usefully run the same check, since those branches couldn't be tested here.

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