-
Notifications
You must be signed in to change notification settings - Fork 6
Elements
Elements are the building blocks of a DNF simulation. Every entity in the system — neural fields, kernels, stimuli, couplings, noise sources — is an Element.
#include "elements/element.h"
#include "elements/element_factory.h"All elements inherit from dnf_composer::element::Element. The interface that every element must implement:
void init(); // initialize buffers and state
void step(double t, double deltaT); // advance one time step
std::shared_ptr<Element> clone() const; // deep copy
std::string toString() const; // human-readable description
// Resize the element to new spatial dimensions.
// All component buffers are reassigned and init() is called automatically.
// Note: this does NOT remove connections — call removeInputs()/removeOutputs()
// first if connected elements have a different size (Simulation::changeDimensions
// handles this automatically).
void changeDimensions(const ElementDimensions& newDimensions);Every element is identified and dimensioned by ElementCommonParameters, which bundles two structs:
struct ElementIdentifiers {
int uniqueIdentifier; // auto-assigned integer ID
std::string uniqueName; // human-readable name (your label + auto ID suffix)
ElementLabel label; // enum: NEURAL_FIELD, GAUSS_KERNEL, ...
};You typically construct it with just a name string:
ElementIdentifiers id{ "my field" };struct ElementDimensions {
int x_max; // number of discrete positions (field size)
double d_x; // spatial step size
int size; // x_max / d_x (computed)
};ElementDimensions dims{ 100, 1.0 }; // 100 positions, step 1.0ElementCommonParameters params{
ElementIdentifiers{ "my field" },
ElementDimensions{ 100, 1.0 }
};Shorthand constructors are also available:
ElementCommonParameters{ "my field" } // default dims (100, 1.0)
ElementCommonParameters{ "my field", 200 } // x_max = 200, d_x = 1.0
ElementCommonParameters{ "my field", dims } // explicit dimsThe ElementLabel enum identifies element types and is used by ElementFactory:
| Label | String | Type |
|---|---|---|
NEURAL_FIELD |
"neural field" |
NeuralField |
GAUSS_STIMULUS |
"gauss stimulus" |
GaussStimulus |
GAUSS_KERNEL |
"gauss kernel" |
GaussKernel |
MEXICAN_HAT_KERNEL |
"mexican hat kernel" |
MexicanHatKernel |
OSCILLATORY_KERNEL |
"oscillatory kernel" |
OscillatoryKernel |
ASYMMETRIC_GAUSS_KERNEL |
"asymmetric gauss kernel" |
AsymmetricGaussKernel |
NORMAL_NOISE |
"normal noise" |
NormalNoise |
FIELD_COUPLING |
"field coupling" |
FieldCoupling |
GAUSS_FIELD_COUPLING |
"gauss field coupling" |
GaussFieldCoupling |
BOOST_STIMULUS |
"boost stimulus" |
BoostStimulus |
MEMORY_TRACE |
"memory trace" |
MemoryTrace |
RESIZE |
"resize" |
Resize |
RESIZE_2D |
"resize 2d" |
Resize2D |
COLLAPSE |
"collapse" |
Collapse |
EXPAND |
"expand" |
Expand |
Each element above also has a 2D counterpart (e.g. NEURAL_FIELD_2D, GAUSS_KERNEL_2D).
There are two equivalent ways to create an element.
The type-safe approach used by the examples and most application code — parameters are checked at compile time:
auto field = std::make_shared<element::NeuralField>(
ElementCommonParameters{ ElementIdentifiers{"name"}, dims },
NeuralFieldParameters{ tau, restingLevel, SigmoidFunction(0.0, 10.0) }
);Creates any registered element from its ElementLabel enum, returning a base Element pointer. Useful when the element type is selected at runtime or loaded from a file (this is the path the JSON loader uses):
ElementFactory factory;
auto field = factory.createElement(
element::NEURAL_FIELD,
ElementCommonParameters{ ElementIdentifiers{"name"}, dims },
NeuralFieldParameters{ tau, restingLevel, SigmoidFunction(0.0, 10.0) }
);A default-parameter overload is also available:
auto field = factory.createElement(element::NEURAL_FIELD);Each element exposes its internal state as named std::vector<double> buffers called components. Components are the bridge between elements and the visualization system.
// Read a component (returns a copy)
std::vector<double> act = element->getComponent("activation");
// Get a live pointer (no copy — use carefully)
std::vector<double>* ptr = element->getComponentPtr("activation");
// List all available component names
std::vector<std::string> names = element->getComponentList();Common component names:
| Component | Elements that have it |
|---|---|
"activation" |
NeuralField |
"output" |
All elements |
"input" |
NeuralField, kernels |
"weights" |
FieldCoupling, GaussFieldCoupling
|
Elements are connected in a directed graph. Each connection specifies a source element and the component of that source to read from.
// Connect elementB's "output" into elementA
elementA->addInput(elementB);
// Connect a specific component
elementA->addInput(elementB, "activation");
// Remove connections
elementA->removeInput("elementB name");
elementA->removeInputs(); // remove all
// Query connections
bool connected = elementA->hasInput("elementB name", "output");
auto inputs = elementA->getInputs(); // vector of shared_ptr
auto inputMap = elementA->getInputsAndComponents(); // map: element -> component name
auto outputs = elementA->getOutputs();Each step() call accumulates all registered input components into the element's "input" buffer before computing its own dynamics.
int id = element->getUniqueIdentifier();
std::string name = element->getUniqueName();
ElementLabel label = element->getLabel();
int size = element->getSize(); // number of positions
double stepSize = element->getStepSize(); // d_x
ElementCommonParameters cp = element->getElementCommonParameters();