1function ctx = afterEventInit(sn)
2% CTX = AFTEREVENTINIT(SN)
3% Precomputes the loop-invariant setup of State.afterEvent so that hot
4% callers (e.g., the solver_ssa Gillespie loop, which re-evaluates every
5% synchronization at every step) avoid re-deriving it on each call.
7% IMPORTANT: ctx caches sn.nservers, sn.cap and sn.classcap. It must be
8% built AFTER any caller-side rewrite of these fields (solver_ssa rewrites
9% them in its preamble: Inf servers at delay
nodes and open-class cutoffs)
10% and AFTER sn_nonmarkov_toph, and the SAME sn must be passed to afterEvent
11% alongside ctx. Building ctx from a stale sn silently drops blocking and
12% server-count semantics.
14% Copyright (c) 2012-2026, Imperial College London
23ctx.phasessz = sn.phasessz;
24ctx.phaseshift = sn.phaseshift;
30ctx.classcap = sn.classcap;
32lldscaling = sn.lldscaling;
34 lldlimit = max(sum(sn.nclosedjobs),1);
35 lldscaling = ones(M,lldlimit);
37 lldlimit = size(lldscaling,2);
39ctx.lldscaling = lldscaling;
40ctx.lldlimit = lldlimit;
42% sn.cdscaling holds a
class-dependence handle only
for the stations that
43% declare one; the others are left empty (see getLimitedClassDependence), since
44% a constant 1
is not a valid
class-dependent RATE. The state machinery indexes
45% every station unconditionally, so fill the gaps with the neutral scaling here.
46cdscaling = sn.cdscaling;
48 cdscaling = cell(M,1);
52 if i > numel(cdscaling) || isempty(cdscaling{i})
53 cdscaling{i} = neutral;
56% Joint-dependence handles (sn.jdscaling, non-product-
form eta_i) are applied
57% by the same state machinery. cd and jd are evaluated identically, so fold
58% them into a single effective per-station handle eta_i(n)*beta_i(n) (scalar
59% .* vector broadcasts). For stations with only one of the two, the other
is
60% the neutral 1, so the product reproduces the single-mechanism
case exactly.
61jdscaling = sn.jdscaling;
64 if i <= numel(jdscaling) && ~isempty(jdscaling{i})
67 cdscaling{i} = @(ni) cdh(ni) .* jdh(ni);
71ctx.cdscaling = cdscaling;
73ctx.ismkvmod =
false(sn.nnodes,1);
74ctx.ismkvmodclass = cell(sn.nnodes,1);
77 ist = sn.nodeToStation(ind);
78 ctx.ismkvmod(ind) = any(sn.procid(ist,:)==ProcessType.MAP | sn.procid(ist,:)==ProcessType.MMPP2);
79 ismkvmodclass = zeros(R,1);
81 ismkvmodclass(r) = any(sn.procid(ist,r)==ProcessType.MAP | sn.procid(ist,r)==ProcessType.MMPP2);
83 ctx.ismkvmodclass{ind} = ismkvmodclass;