Elements
An element holds the states of a system, such as an amount, a position, or a cell of a lattice. The domain of each
state is a tag, read from its StateSpec, and get_tags() of an element returns its domains. Every role of an
interaction lists the domains it accepts, so the domains of an element decide which interactions it can be bound to.
The table lists what each element class of the core declares. A subclass adds the states your interactions read, and
their domains with them.
| Element | States | Domains | Law kinds |
|---|---|---|---|
CompartmentElement |
n |
real |
none |
DeclaredElement |
from a subclass | from a subclass | none |
DensityElement |
f |
real |
none |
Element |
from a subclass | from a subclass | none |
FieldElement |
from a subclass | from a subclass | unknown until run |
GroupElement |
from a subclass | from a subclass | unknown until run |
LatticeElement |
from a subclass | from a subclass | unknown until run |
PatchElement |
tiles |
a whole structure | none |
PointElement |
x |
vector |
none |
WordElement |
axiom |
a whole structure | none |
A compatible element
A compartment holds a real amount, and the target of a RateInteraction accepts real states.
from skcomplex.core.components.elements import CompartmentElement
from skcomplex.core.components.interactions import RateInteraction
from skcomplex.core.components.system import System
from skcomplex.core.engine.runtime import simulate
tank = CompartmentElement('tank', n=10.0)
decay = RateInteraction('decay', target='tank', state='n', rate=lambda s: -0.5 * s.target.n)
sorted(tank.get_tags().domains)
trajectory = simulate(System(elements=[tank], interactions=[decay]), until=2)
round(trajectory.values('tank.n')[-1], 2)
['real']
3.68
An incompatible element
A switch that is on or off holds a boolean state. A rate does not change a boolean, so the system rejects the binding and names the domain.
from typing import Annotated
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
from skcomplex.core.components.elements import Element
from skcomplex.core.components.interactions import RateInteraction
from skcomplex.core.components.system import System
from skcomplex.core.engine.runtime import simulate
from skcomplex.core.errors import RoleElementError
from skcomplex.core.specs import StateSpec
class SwitchElement(Element):
def __init__(self, label, *, on: Annotated[int, StateSpec(FiniteEnumeratedSet([0, 1]))] = 0):
super().__init__(label)
self.on = on
switch = SwitchElement('switch')
sorted(switch.get_tags().domains)
flip = RateInteraction('flip', target='switch', state='on', rate=1.0)
try:
simulate(System(elements=[switch], interactions=[flip]), until=1)
except RoleElementError as error:
message = str(error)
message
assert "domain 'boolean'" in message
['boolean']
The role 'target' of 'flip' accepts the domains real, integer, complex, vector, but the element 'switch' bound to it has the state 'on' of the domain 'boolean'.