use of gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget in project n2a by frothga.
the class Part method finish.
public boolean finish(Simulator simulator) {
InternalBackendData bed = (InternalBackendData) equations.backendData;
int populations = equations.parts.size();
for (int i = 0; i < populations; i++) ((Population) valuesObject[i]).finish(simulator);
if (bed.liveStorage == InternalBackendData.LIVE_STORED) {
// early-out if we are already dead, to avoid another call to die()
if (((Scalar) get(bed.live)).value == 0)
return false;
}
// Events
for (EventSource es : bed.eventSources) {
@SuppressWarnings("unchecked") List<Instance> monitors = (ArrayList<Instance>) valuesObject[es.monitorIndex];
if (monitors.size() == 0)
continue;
EventTarget eventType = es.target;
if (es.testEach) {
for (Instance i : monitors) {
if (i == null)
continue;
double delay = eventType.test(i, simulator);
// the trigger condition was not satisfied
if (delay < -1)
continue;
EventSpikeSingle spike;
if (// event was triggered, but timing is no-care
delay < 0) {
spike = new EventSpikeSingleLatch();
// queue immediately after current cycle, so latches get set for next full cycle
spike.t = simulator.currentEvent.t;
} else if (// process as close to current cycle as possible
delay == 0) {
// fully execute the event (not latch it)
spike = new EventSpikeSingle();
// queue immediately
spike.t = simulator.currentEvent.t;
} else {
// Is delay an quantum number of $t' steps?
double ratio = delay / event.dt;
int step = (int) Math.round(ratio);
if (Math.abs(ratio - step) < 1e-3) {
if (simulator.eventMode == Simulator.DURING)
spike = new EventSpikeSingleLatch();
else
spike = new EventSpikeSingle();
if (simulator.eventMode == Simulator.AFTER)
delay = (step + 1e-6) * event.dt;
else
delay = (step - 1e-6) * event.dt;
} else {
spike = new EventSpikeSingle();
}
spike.t = simulator.currentEvent.t + delay;
}
spike.eventType = eventType;
spike.target = i;
simulator.queueEvent.add(spike);
}
} else // All monitors share same condition, so only test one.
{
double delay = -2;
for (Instance i : monitors) {
if (i == null)
continue;
delay = eventType.test(i, simulator);
break;
}
// the trigger condition was not satisfied
if (delay < -1)
continue;
if (// Each target instance may require a different delay.
es.delayEach) {
for (Instance i : monitors) {
if (i == null)
continue;
// This results in one redundant eval, of first entry in monitors. Not clear if it's worth the work to avoid this.
delay = eventType.delay(i, simulator);
EventSpikeSingle spike;
if (delay < 0) {
spike = new EventSpikeSingleLatch();
spike.t = simulator.currentEvent.t;
} else if (delay == 0) {
spike = new EventSpikeSingle();
spike.t = simulator.currentEvent.t;
} else {
double ratio = delay / event.dt;
int step = (int) Math.round(ratio);
if (Math.abs(ratio - step) < 1e-3) {
if (simulator.eventMode == Simulator.DURING)
spike = new EventSpikeSingleLatch();
else
spike = new EventSpikeSingle();
if (simulator.eventMode == Simulator.AFTER)
delay = (step + 1e-6) * event.dt;
else
delay = (step - 1e-6) * event.dt;
} else {
spike = new EventSpikeSingle();
}
spike.t = simulator.currentEvent.t + delay;
}
spike.eventType = eventType;
spike.target = i;
simulator.queueEvent.add(spike);
}
} else // All delays are the same.
{
EventSpikeMulti spike;
if (delay < 0) {
spike = new EventSpikeMultiLatch();
spike.t = simulator.currentEvent.t;
} else if (delay == 0) {
spike = new EventSpikeMulti();
spike.t = simulator.currentEvent.t;
} else {
double ratio = delay / event.dt;
int step = (int) Math.round(ratio);
if (Math.abs(ratio - step) < 1e-3) {
if (simulator.eventMode == Simulator.DURING)
spike = new EventSpikeMultiLatch();
else
spike = new EventSpikeMulti();
if (simulator.eventMode == Simulator.AFTER)
delay = (step + 1e-6) * event.dt;
else
delay = (step - 1e-6) * event.dt;
} else {
spike = new EventSpikeMulti();
}
spike.t = simulator.currentEvent.t + delay;
}
spike.eventType = eventType;
// We don't copy the array, just keep a reference to it. What could go wrong with this?
// If a part dies and tries to remove itself from the list while it is being used to deliver spikes,
// then we could get a null pointer exception. Solution is to synchronize access to the list.
// If a connection is born while the spike is in flight, one could argue that it shouldn't
// receive it, but one could also argue that it should. In nature these two things (spikes
// and synapse creation) occur at vastly different timescales. Wouldn't a nascent synapse
// receive spikes even as it is forming?
spike.targets = monitors;
simulator.queueEvent.add(spike);
}
}
}
// Other stuff
if (bed.lastT != null)
setFinal(bed.lastT, new Scalar(simulator.currentEvent.t));
for (Variable v : bed.localBufferedExternal) setFinal(v, getFinal(v));
for (Integer i : bed.eventLatches) valuesFloat[i] = 0;
for (Variable v : bed.localBufferedExternalWrite) {
switch(v.assignment) {
case Variable.ADD:
// initial value is zero-equivalent (additive identity)
set(v, v.type);
break;
case Variable.MULTIPLY:
case Variable.DIVIDE:
// multiplicative identity
if (v.type instanceof Matrix)
set(v, ((Matrix) v.type).identity());
else
set(v, new Scalar(1));
break;
case Variable.MIN:
if (v.type instanceof Matrix)
set(v, ((Matrix) v.type).clear(Double.POSITIVE_INFINITY));
else
set(v, new Scalar(Double.POSITIVE_INFINITY));
break;
case Variable.MAX:
if (v.type instanceof Matrix)
set(v, ((Matrix) v.type).clear(Double.NEGATIVE_INFINITY));
else
set(v, new Scalar(Double.NEGATIVE_INFINITY));
break;
}
}
if (bed.type != null) {
int type = (int) ((Scalar) get(bed.type)).value;
if (type > 0) {
ArrayList<EquationSet> split = equations.splits.get(type - 1);
if (// Make sure $type != me. Otherwise it's a null operation
split.size() > 1 || split.get(0) != equations) {
// indicates that this instance is one of the resulting parts
boolean used = false;
int countParts = split.size();
for (int i = 0; i < countParts; i++) {
EquationSet other = split.get(i);
Scalar splitPosition = new Scalar(i + 1);
if (other == equations && !used) {
used = true;
setFinal(bed.type, splitPosition);
} else {
InternalBackendData otherBed = (InternalBackendData) other.backendData;
Part p = new Part(other, (Part) container);
// If this is a connection, keep the same bindings
Conversion conversion = bed.conversions.get(other);
if (conversion.bindings != null) {
for (int j = 0; j < conversion.bindings.length; j++) {
p.valuesObject[otherBed.endpoints + conversion.bindings[j]] = valuesObject[bed.endpoints + j];
}
}
event.enqueue(p);
p.resolve();
// accountable connections are updated here
p.init(simulator);
// Copy over variables
int count = conversion.from.size();
for (int v = 0; v < count; v++) {
Variable from = conversion.from.get(v);
Variable to = conversion.to.get(v);
p.setFinal(to, get(from));
}
// Set $type to be our position in the split
p.setFinal(otherBed.type, splitPosition);
}
}
if (!used) {
die();
return false;
}
}
}
}
if (equations.lethalP) {
double p;
if (bed.p.hasAttribute("temporary")) {
InstanceTemporaries temp = new InstanceTemporaries(this, simulator, false);
for (Variable v : bed.Pdependencies) {
Type result = v.eval(temp);
if (result != null && v.writeIndex >= 0)
temp.set(v, result);
}
Type result = bed.p.eval(temp);
if (result == null)
p = 1;
else
p = ((Scalar) result).value;
} else {
p = ((Scalar) get(bed.p)).value;
}
if (p == 0 || p < 1 && p < simulator.random.nextDouble()) {
die();
return false;
}
}
if (equations.lethalConnection) {
int count = equations.connectionBindings.size();
for (int i = 0; i < count; i++) {
if (!getPart(i).getLive()) {
die();
return false;
}
}
}
if (equations.lethalContainer) {
if (!((Part) container).getLive()) {
die();
return false;
}
}
return true;
}
use of gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget in project n2a by frothga.
the class Part method die.
public void die() {
// set $live to false, if it is stored in this part
InternalBackendData bed = (InternalBackendData) equations.backendData;
if (bed.liveStorage == InternalBackendData.LIVE_STORED) {
set(bed.live, new Scalar(0));
}
// update accountable endpoints
if (bed.count != null) {
int length = bed.count.length;
for (int i = 0; i < length; i++) {
if (bed.count[i] >= 0) {
Part p = (Part) valuesObject[bed.endpoints + i];
p.valuesFloat[bed.count[i]]--;
}
}
}
// Release event monitors
for (EventTarget et : bed.eventTargets) {
for (EventSource es : et.sources) {
// Don't bother with self-connection, since we are going away.
if (es.reference == null)
continue;
Part source = (Part) valuesObject[es.reference.index];
@SuppressWarnings("unchecked") ArrayList<Instance> monitors = (ArrayList<Instance>) source.valuesObject[es.monitorIndex];
int index = monitors.indexOf(this);
// Actually removing the element can cause a concurrent modification exception. Instead, the monitors array will get flushed next time an event processes it.
monitors.set(index, null);
}
}
((Population) container.valuesObject[bed.populationIndex]).remove(this);
}
use of gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget in project n2a by frothga.
the class JobC method generateDeclarations.
/**
* Declares all classes, along with their member variables and functions.
*
* For each part, generates two classes: one for the instances ("local")
* and one for the population as a whole ("global"). Within each class,
* declares buffer classes for integration and derivation, then member
* variables, and finally member functions as appropriate.
*/
public void generateDeclarations(EquationSet s, StringBuilder result) {
for (EquationSet p : s.parts) generateDeclarations(p, result);
BackendDataC bed = (BackendDataC) s.backendData;
// Population class header
result.append("class " + prefix(s) + "_Population : public Population\n");
result.append("{\n");
result.append("public:\n");
// Population buffers
if (bed.globalDerivative.size() > 0) {
result.append(" class Derivative\n");
result.append(" {\n");
result.append(" public:\n");
for (Variable v : bed.globalDerivative) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
result.append(" Derivative * next;\n");
result.append(" };\n");
result.append("\n");
}
if (bed.needGlobalPreserve) {
result.append(" class Preserve\n");
result.append(" {\n");
result.append(" public:\n");
for (Variable v : bed.globalIntegrated) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
for (Variable v : bed.globalDerivativePreserve) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
for (Variable v : bed.globalBufferedExternalWriteDerivative) {
result.append(" " + type(v) + " " + mangle("next_", v) + ";\n");
}
result.append(" };\n");
result.append("\n");
}
// Population variables
if (bed.n != null) {
result.append(" int n;\n");
}
if (bed.index != null) {
result.append(" int nextIndex;\n");
}
if (bed.globalDerivative.size() > 0) {
result.append(" Derivative * stackDerivative;\n");
}
if (bed.needGlobalPreserve) {
result.append(" Preserve * preserve;\n");
}
result.append(" " + prefix(s.container) + " * container;\n");
for (Variable v : bed.globalMembers) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
for (Variable v : bed.globalBufferedExternal) {
result.append(" " + type(v) + " " + mangle("next_", v) + ";\n");
}
for (String columnName : bed.globalColumns) {
result.append(" String " + columnName + ";\n");
}
result.append("\n");
// Population functions
if (bed.needGlobalCtor) {
result.append(" " + prefix(s) + "_Population ();\n");
}
if (bed.needGlobalDtor) {
result.append(" virtual ~" + prefix(s) + "_Population ();\n");
}
result.append(" virtual Part * create ();\n");
if (bed.index != null || bed.trackInstances) {
result.append(" virtual void add (Part * part);\n");
if (bed.trackInstances) {
result.append(" virtual void remove (Part * part);\n");
}
}
result.append(" virtual void init ();\n");
if (bed.globalIntegrated.size() > 0) {
result.append(" virtual void integrate ();\n");
}
if (bed.globalUpdate.size() > 0) {
result.append(" virtual void update ();\n");
}
if (bed.needGlobalFinalize) {
result.append(" virtual bool finalize ();\n");
}
if (bed.n != null) {
result.append(" virtual void resize (int n);\n");
}
if (bed.globalDerivativeUpdate.size() > 0) {
result.append(" virtual void updateDerivative ();\n");
}
if (bed.globalBufferedExternalDerivative.size() > 0) {
result.append(" virtual void finalizeDerivative ();\n");
}
if (bed.needGlobalPreserve) {
result.append(" virtual void snapshot ();\n");
result.append(" virtual void restore ();\n");
}
if (bed.globalDerivative.size() > 0) {
result.append(" virtual void pushDerivative ();\n");
result.append(" virtual void multiplyAddToStack (float scalar);\n");
result.append(" virtual void multiply (float scalar);\n");
result.append(" virtual void addToMembers ();\n");
}
if (s.connectionBindings != null) {
result.append(" virtual Population * getTarget (int i);\n");
if (bed.needK) {
result.append(" virtual int getK (int i);\n");
}
if (bed.needMax) {
result.append(" virtual int getMax (int i);\n");
}
if (bed.needMin) {
result.append(" virtual int getMin (int i);\n");
}
if (bed.needRadius) {
result.append(" virtual int getRadius (int i);\n");
}
}
if (bed.needGlobalPath) {
result.append(" virtual void path (String & result);\n");
}
// Population class trailer
result.append("};\n");
result.append("\n");
// -------------------------------------------------------------------
// Unit class
result.append("class " + prefix(s) + " : public PartTime\n");
result.append("{\n");
result.append("public:\n");
// Unit buffers
if (bed.localDerivative.size() > 0) {
result.append(" class Derivative\n");
result.append(" {\n");
result.append(" public:\n");
for (Variable v : bed.localDerivative) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
result.append(" Derivative * next;\n");
result.append(" };\n");
result.append("\n");
}
if (bed.needLocalPreserve) {
result.append(" class Preserve\n");
result.append(" {\n");
result.append(" public:\n");
for (Variable v : bed.localIntegrated) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
for (Variable v : bed.localDerivativePreserve) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
for (Variable v : bed.localBufferedExternalWriteDerivative) {
result.append(" " + type(v) + " " + mangle("next_", v) + ";\n");
}
result.append(" };\n");
result.append("\n");
}
// Unit variables
if (bed.localDerivative.size() > 0) {
result.append(" Derivative * stackDerivative;\n");
}
if (bed.needLocalPreserve) {
result.append(" Preserve * preserve;\n");
}
if (bed.pathToContainer == null) {
result.append(" " + prefix(s.container) + " * container;\n");
}
if (s.connectionBindings != null) {
for (ConnectionBinding c : s.connectionBindings) {
// we should be able to assume that s.container is non-null; ie: a connection should always operate in some larger container
result.append(" " + prefix(c.endpoint) + " * " + mangle(c.alias) + ";\n");
}
}
if (s.accountableConnections != null) {
for (EquationSet.AccountableConnection ac : s.accountableConnections) {
result.append(" int " + prefix(ac.connection) + "_" + mangle(ac.alias) + "_count;\n");
}
}
if (bed.refcount) {
result.append(" int refcount;\n");
}
if (bed.index != null) {
result.append(" int __24index;\n");
}
if (bed.lastT) {
// $lastT is for internal use only, so no need for __24 prefix.
result.append(" float lastT;\n");
}
for (Variable v : bed.localMembers) {
result.append(" " + type(v) + " " + mangle(v) + ";\n");
}
for (Variable v : bed.localBufferedExternal) {
result.append(" " + type(v) + " " + mangle("next_", v) + ";\n");
}
for (EquationSet p : s.parts) {
result.append(" " + prefix(p) + "_Population " + mangle(p.name) + ";\n");
}
for (String columnName : bed.localColumns) {
result.append(" String " + columnName + ";\n");
}
for (EventSource es : bed.eventSources) {
result.append(" std::vector<Part *> " + "eventMonitor_" + prefix(es.target.container) + ";\n");
}
for (EventTarget et : bed.eventTargets) {
if (et.track != null && et.track.name.startsWith("eventAux")) {
result.append(" float " + et.track.name + ";\n");
}
if (et.timeIndex >= 0) {
result.append(" float eventTime" + et.timeIndex + ";\n");
}
}
if (!bed.flagType.isEmpty()) {
// This should come last, because it can affect alignment.
result.append(" " + bed.flagType + " flags;\n");
}
result.append("\n");
// Unit functions
if (bed.needLocalCtor || s.parts.size() > 0) {
result.append(" " + prefix(s) + " ();\n");
}
if (bed.needLocalDtor) {
result.append(" virtual ~" + prefix(s) + " ();\n");
}
if (bed.localMembers.size() > 0) {
result.append(" virtual void clear ();\n");
}
if (s.container == null) {
result.append(" virtual void setPeriod (float dt);\n");
}
if (bed.needLocalDie) {
result.append(" virtual void die ();\n");
}
if (bed.localReference.size() > 0) {
result.append(" virtual void enterSimulation ();\n");
}
result.append(" virtual void leaveSimulation ();\n");
if (bed.refcount) {
result.append(" virtual bool isFree ();\n");
}
if (bed.needLocalInit || s.parts.size() > 0) {
result.append(" virtual void init ();\n");
}
if (bed.localIntegrated.size() > 0 || s.parts.size() > 0) {
result.append(" virtual void integrate ();\n");
}
if (bed.localUpdate.size() > 0 || s.parts.size() > 0) {
result.append(" virtual void update ();\n");
}
if (bed.needLocalFinalize || s.parts.size() > 0) {
result.append(" virtual bool finalize ();\n");
}
if (bed.localDerivativeUpdate.size() > 0 || s.parts.size() > 0) {
result.append(" virtual void updateDerivative ();\n");
}
if (bed.localBufferedExternalDerivative.size() > 0 || s.parts.size() > 0) {
result.append(" virtual void finalizeDerivative ();\n");
}
if (bed.needLocalPreserve || s.parts.size() > 0) {
result.append(" virtual void snapshot ();\n");
result.append(" virtual void restore ();\n");
}
if (bed.localDerivative.size() > 0 || s.parts.size() > 0) {
result.append(" virtual void pushDerivative ();\n");
result.append(" virtual void multiplyAddToStack (float scalar);\n");
result.append(" virtual void multiply (float scalar);\n");
result.append(" virtual void addToMembers ();\n");
}
if (bed.live != null && !bed.live.hasAttribute("constant")) {
result.append(" virtual float getLive ();\n");
}
if (s.connectionBindings == null) {
if (bed.xyz != null) {
result.append(" virtual void getXYZ (Vector3 & xyz);\n");
}
} else {
if (bed.p != null) {
result.append(" virtual float getP ();\n");
}
if (bed.hasProjectFrom || bed.hasProjectTo) {
result.append(" virtual void project (int i, int j, Vector3 & xyz);\n");
}
result.append(" virtual void setPart (int i, Part * part);\n");
result.append(" virtual Part * getPart (int i);\n");
}
if (bed.eventTargets.size() > 0) {
result.append(" virtual bool eventTest (int i);\n");
if (bed.needLocalEventDelay) {
result.append(" virtual float eventDelay (int i);\n");
}
result.append(" virtual void setLatch (int i);\n");
if (bed.eventReferences.size() > 0) {
result.append(" virtual void finalizeEvent ();\n");
}
}
if (bed.accountableEndpoints.size() > 0) {
result.append(" virtual int getCount (int i);\n");
}
if (bed.needLocalPath) {
result.append(" virtual void path (String & result);\n");
}
// Conversions
Set<Conversion> conversions = s.getConversions();
for (Conversion pair : conversions) {
EquationSet source = pair.from;
EquationSet dest = pair.to;
result.append(" void " + mangle(source.name) + "_2_" + mangle(dest.name) + " (" + mangle(source.name) + " * from, int " + mangle("$type") + ");\n");
}
// Unit class trailer
result.append("};\n");
result.append("\n");
}
use of gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget in project n2a by frothga.
the class Part method init.
/**
* Note: specifically for Parts, call resolve() before calling init(). This is to
* accommodate the connection process, which must probe values in a part (which
* may include references) before calling init().
*/
public void init(Simulator simulator) {
InstanceTemporaries temp = new InstanceTemporaries(this, simulator, true);
// update $n and assign $index
((Population) container.valuesObject[temp.bed.populationIndex]).insert(this);
// Note: these do not require resolve(). Instead, they access their target directly through the endpoints array.
if (temp.bed.count != null) {
int length = temp.bed.count.length;
for (int i = 0; i < length; i++) {
if (temp.bed.count[i] >= 0) {
Part p = (Part) valuesObject[temp.bed.endpoints + i];
p.valuesFloat[temp.bed.count[i]]++;
}
}
}
// force $live to be set before anything else
if (temp.bed.liveStorage == InternalBackendData.LIVE_STORED)
set(temp.bed.live, new Scalar(1));
for (Variable v : temp.bed.localInitSpecial) {
Type result = v.eval(temp);
if (result != null && v.writeIndex >= 0)
temp.set(v, result);
// Note that some valuesObject entries may be left null. This is OK, because Instance.get() will return
// a zero-equivalent value if it finds null. Ditto for non-$variables below.
}
for (Variable v : temp.bed.localBufferedSpecial) {
temp.setFinal(v, temp.getFinal(v));
}
if (temp.bed.lastT != null)
temp.setFinal(temp.bed.lastT, new Scalar(simulator.currentEvent.t));
// non-$variables
for (Variable v : temp.bed.localInitRegular) {
Type result = v.eval(temp);
if (result != null && v.writeIndex >= 0)
temp.set(v, result);
}
for (Variable v : temp.bed.localBufferedRegular) {
temp.setFinal(v, temp.getFinal(v));
}
// v.type should be pre-loaded with zero-equivalent values
for (Variable v : temp.bed.localBufferedExternalWrite) set(v, v.type);
// Request event monitors
for (EventTarget et : temp.bed.eventTargets) {
for (EventSource es : et.sources) {
Part source;
if (es.reference == null)
source = this;
else
source = (Part) valuesObject[es.reference.index];
@SuppressWarnings("unchecked") ArrayList<Instance> monitors = (ArrayList<Instance>) source.valuesObject[es.monitorIndex];
monitors.add(this);
}
}
int populations = equations.parts.size();
for (int i = 0; i < populations; i++) ((Population) valuesObject[i]).init(simulator);
}
use of gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget in project n2a by frothga.
the class BackendDataC method analyzeEvents.
public void analyzeEvents(final EquationSet s) {
InternalBackendData.analyzeEvents(s, eventTargets, eventReferences);
int eventIndex = 0;
for (EventTarget et : eventTargets) {
et.valueIndex = eventIndex;
// Force multiple sources to generate only one event in a given cycle
if (et.sources.size() > 1 && et.edge == EventTarget.NONZERO) {
et.timeIndex = eventIndex;
}
for (EventSource es : et.sources) {
BackendDataC sourceBed = (BackendDataC) es.container.backendData;
sourceBed.eventSources.add(es);
}
eventIndex++;
}
}
Aggregations