To Node or Not to Node - laser-base/laser-core GitHub Wiki

(lost draft to crash so saving as I go now)

Node-as-Container vs Node-as-Attribute

In our disease ABMs, all agents exist in a place (or node) at any given moment. This node can either be a container, such that each node contains a number of individuals, or a property of an individual. Which approach is "better" remains to be determined.

Nodes as Containers

In EMOD, the top-level object or container is the Simulation. The Simulation will contain 1 to N nodes. Each node contains 1 to N Individuals (or agents). Individuals can move between nodes (migration). All transmission occurs within a node. Parallelization can then be done by processing nodes separately, within a given timestep.

Nodes as Properties

In LASER, we have the option of treating nodes as "just another" property of an individual/agent. There are pros and cons of having the the entire population in a single set of vectors. Migration is done as simply updating the node id of agents. Operations which are node-agnostic can be done on the entire population at once. Operations which are node-wise can be done using node masks and for loops.

Pros & Cons

At time of writing, Chris' prototype uses the "EMOD approach" and treats each node as a Community, and each node or Community is processed in a top-level for loop. Jonathan's prototype uses the alternate approach and explores working with nodes as a property.

Some operations are node-agnostic. Such as:

  • Initiate, progress (and recover from) infections.
  • Progress immunities (in case of immune decay).
  • Progress ages.
  • Progress interventions.

Some operations are inherently node-specific:

  • Transmission

Some operations can be node-agnostic or node-specific depending on whether we have node-level heterogeneities:

  • Fertility
  • Mortality (Nigeria might have different mortality rates by location, but England & Wales in the 50 might not).

Even things like migration which relate to nodes can be done population-wide by creating a population-level vector first.

Migration

A big impact of this choice is on migration. If we home each node population separately, migration requires removing (or perma-masking) agents from one contiguous set of vectors and inserting them into another one. This is kind of directly violative of the approach we're trying to pursue here. Having the entire population in a single block means that migration is just updating a value of some agents and has no impact on memory.