Skip to content

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'.