Skip to content

setPredKernel(reset = TRUE) leaves a stale explicit kernel, corrupting getTrophicLevel() #608

Description

@gustavdelius

setPredKernel(reset = TRUE) leaves a stale explicit kernel in the slot, corrupting getTrophicLevel()

Two different tests are used to answer the same question, "is the predation kernel stored explicitly?":

  • !is.null(comment(params@pred_kernel)) — R/project_methods.R:311, :667, R/summary_methods.R:175, R/diffusion.R:140
  • length(dim(params@pred_kernel)) > 1 — encounter_kernel(), R/setPredKernel.R:419

reset = TRUE clears the comment (R/setPredKernel.R:148) and recomputes the ft_pred_kernel_* arrays, but never shrinks params@pred_kernel back. After a thaw the two tests therefore disagree: the rate functions take the FFT path with the freshly computed kernel, while encounter_kernel() still returns the stale explicit array.

getTrophicLevel() uses both. Its numerator is a trophic-level-weighted copy of the encounter integral built from encounter_kernel(), and its denominator is the consumption from getEncounter(). The comment at R/summary_methods.R:378 states the requirement explicitly: the ratio is only a trophic level if the two use the same quadrature. After a reset they do not.

library(mizer)
p  <- NS_params
p3 <- setPredKernel(setPredKernel(p, pred_kernel = pred_kernel(p) * 2),
                    reset = TRUE)

getTrophicLevel(p3)[1, 1]   #> 4.503
getTrophicLevel(p)[1, 1]    #> 2.752
max(abs(getTrophicLevel(p3) - getTrophicLevel(p)))   #> 24.6

getEncounter(p3) is numerically identical to getEncounter(p), so the model itself is fine — it is the reported trophic levels that are wrong, silently. pred_kernel(p3) also still returns the discarded doubled kernel, i.e. the accessor reports a kernel the model is not using.

Suggested fix

Give the question one answer. Either have reset = TRUE shrink params@pred_kernel back to its placeholder so dim and comment cannot disagree, or route all five sites through a single internal predicate. The first is cheaper and also fixes the accessor.

Related to #505: the same attribute is serving as both the freeze flag and the runtime dispatch key, which is why a second discriminator appeared in the first place.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugcoreIssue relates to the mizer core

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions