Repository navigation
Bug/i86 annual reset catch - #88
Draft
jacobkasper wants to merge 1 commit into
Draft
jacobkasper wants to merge 1 commit into
jacobkasper wants to merge 1 commit into
Conversation
jacobkasper
force-pushed
the
bug/i86-annual-reset-catch
branch
from
September 29, 2026 16:05
2ae6a73 to
ce219b9
Compare
jacobkasper
marked this pull request as draft
September 29, 2026 16:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Justification
Fixes #86.
Problem.
OutCatchPerFishery.txtunder-reports catch for every fished species by one timestep's catch per year, so it disagrees withOutCatch.txt,OutCATCH.ncandOutTOTCATCH.nc, which agree with each other exactly. For cod (FCD) in our model the shortfall is 384–416 t per year, about 0.15% of annual catch. Anyone reconciling catch across these outputs, or using the per-fishery file for fleet-level analyses, gets figures that are systematically low.Cause.
bm->Catch[box][sp][nf][layer]is a per-step buffer. Catch is deposited during ecology inCalculate_Catch(atprocess.c), then drained intoTotCumCatch(plusCumCatch,TripCatchandTotCumBiCatch) and zeroed at the start of the next step's layer processing, inHarvest_Init_Layer_Arrays(atHarvest.c). Between timesteps the buffer therefore always holds the most recent step's catch.At the year boundary,
Harvest_Annual_Reset(atHarvestAnnual.c) zeroesbm->Catchwithout draining it, destroying the final step of each year.CatchSum(→OutCatch.txt) and the catch tracers (→ NetCDF) are incremented in the step the catch is taken, so they already include it;TotCumCatch(→OutCatchPerFishery.txt) never receives it.Fix. This PR adds
Harvest_Account_Catch_BuffertoatHarvest.c, next to the per-step drain it mirrors (sameisFishedand> 0.0guards, same accumulators). It is called inReport_Annual_Harvestimmediately beforeHarvest_Report_Annual_Stats, and adds the step still held in the buffer to the completed year,TotCumCatch[..][bm->thisyear - 1]; by that pointthisyearhas already been incremented in the annual block ofatlantismain.c.The function deliberately does not zero
bm->Catch.Harvest_Annual_Resetstill does that later in the same annual block, which stops the next per-step drain from counting the step again. As a result, every other routine that readsbm->Catch(management, economics) sees exactly the same values as before, and model dynamics are unaffected.The call is placed in
Report_Annual_Harvestrather than insideHarvest_Report_Annual_Statsbecause the latter is also called fromTextfile_Dumpat the end of a run, where adding the in-flight step would file it in the wrong year.Evidence
Symptom on unmodified code (
main,ab323c7), FCD, withOutCatchPerFishery.txtsummed over fisheries:Instrumented counters on unmodified code, FCD, in tonnes. Catch deposited into
bm->CatchmatchedCatchSumto 7 significant figures, and catch drained matchedTotCumCatchexactly (the> 0.0gate in the drain discards nothing):bm->CatchTotCumCatchEach year, the final timestep's catch is still in the buffer at the annual write, and the reset then destroys it, so every year is short by one step and the losses accumulate. The last row is a partial year: its 294.7 t is the step still in flight when the run ended.
At each annual write, the year's final step is still in the buffer; the reset then destroys it, so the gap grows by one timestep's catch per year. The day-799.5 value also includes the step in flight when the run ended.
With this PR (
dev,d693861, 800-day run),OutCatchPerFishery.txtsummed over fisheries matchesOutCatch.txtin every year, including the first:Differences for all fished species,
OutCatch.txtminusOutCatchPerFishery.txt(t):The largest relative difference for any species is 4.6e-7, the print precision of
OutCatchPerFishery.txt(%e, 7 significant figures).Related, not changed here
Harvest_Annual_Reset,bm->TotOldCumCatch[k][n] += TotCumCatch[k][n][bm->thisyear];runs afterbm->thisyear++, so it reads the new, empty year's bucket. The adjacent comment suggeststhisyear - 1was intended; this would affectbulkTACaccounting.Harvest_Skip_biology, the epibenthic block indexesbm->Catch[ij][sp][nf][k]withkleft over from the preceding layer loop.