use of gov.sandia.n2a.language.type.Instance in project n2a by frothga.
the class EquationSet method determineTypesEval.
public boolean determineTypesEval() {
boolean changed = false;
for (final Variable v : variables) {
if (v.hasAttribute("constant"))
continue;
// Don't change type for certain $variables.
if (v.name.equals("$init") || v.name.equals("$live") || v.name.equals("$p") || v.name.equals("$n") || (v.name.equals("$t") && v.order == 1))
continue;
Type value = null;
Instance instance = new Instance() {
// all AccessVariable objects will reach here first, and get back the Variable.type field
public Type get(VariableReference r) throws EvaluationException {
return r.variable.type;
}
};
for (EquationEntry e : v.equations) {
// However, scanning them all increase our chance of propagating correct values.
try {
Type temp = e.expression.eval(instance);
if (value == null || temp.betterThan(value))
value = temp;
}// This can happen due to type mismatch, and may be a temporary condition while values are propagating.
catch (Exception x) {
}
}
if (v.derivative != null) {
if (value == null) {
value = v.derivative.type;
} else if (v.derivative.type == null || value.betterThan(v.derivative.type)) {
v.derivative.type = value;
changed = true;
}
}
if (value == null) {
value = v.reference.variable.type;
} else if (v.reference.variable.type == null || value.betterThan(v.reference.variable.type)) {
v.reference.variable.type = value;
changed = true;
}
if (v != v.reference.variable && value != null && value.betterThan(v.type)) {
v.type = value;
changed = true;
}
}
for (EquationSet s : parts) {
if (s.determineTypesEval())
changed = true;
}
return changed;
}
use of gov.sandia.n2a.language.type.Instance in project n2a by frothga.
the class EquationSet method findConstantsEval.
protected boolean findConstantsEval() {
boolean changed = false;
for (Variable v : variables) {
if (v.simplify())
changed = true;
// "externalWrite" -- Regardless of the local math, a variable that gets written is not constant.
if (v.hasAny("constant", "initOnly", "externalWrite"))
continue;
if (// A variable with a derivative is usually not constant, with the following exceptions ...
v.derivative != null) {
// 1) Check for unconditional constant.
if (v.equations.size() == 1) {
EquationEntry e = v.equations.first();
if (// Must be unconditional. No exception for $init. (Non-integrated variables do get an exception for $init; see below.)
e.expression instanceof Constant && e.condition == null) {
changed = true;
v.addAttribute("constant");
v.removeDependencyOn(v.derivative);
v.derivative = null;
continue;
}
}
// 2a) Check for pure circular dependency.
Variable top = v;
while (// This single dependency must be the derivative.
top.uses != null && top.uses.size() == 1) {
if (top.derivative != null) {
top = top.derivative;
continue;
}
// Its single dependency is not a derivative, but could be anything else.
if (// This is a pure circular dependency.
top.uses.containsKey(v)) {
// Evaluate top. Initial value of v must be zero, because otherwise it would depend on other variables or be trapped above as an unconditional constant.
// We can only make this assumption here.
Instance instance = new Instance() {
public Scalar zero = new Scalar(0);
// all AccessVariable objects will reach here first.
public Type get(VariableReference r) throws EvaluationException {
return zero;
}
};
Type result = top.eval(instance);
if (result instanceof Scalar && ((Scalar) result).value == 0) {
changed = true;
top.addAttribute("constant");
// Should just be v, but there may be multiple references.
top.removeDependencies();
top.equations.clear();
EquationEntry e = new EquationEntry(top, "");
e.expression = new Constant(0);
top.add(e);
}
}
// And fall through to case 2. If top is immediately v.derivative, then it will be detached in this iteration.
break;
}
// 2) Check if derivative is constant zero.
if (!v.derivative.hasAttribute("constant"))
continue;
EquationEntry e = v.derivative.equations.first();
if (!((Constant) e.expression).value.isZero())
continue;
changed = true;
v.removeDependencyOn(v.derivative);
v.derivative = null;
if (v.equations.isEmpty()) {
// $t, $t', $index an $type are also added without equations.
if (v.name.equals("$t") && v.order < 2)
continue;
v.addAttribute("constant");
e = new EquationEntry(v, "");
e.expression = new Constant(0);
v.add(e);
// Already determined that v is constant, so done with it.
continue;
}
// v is now effectively an ordinary variable (no derivative) with equation(s), so fall through ...
}
if (v.equations.size() != 1) {
if (// Special cases for $variables
v.equations.isEmpty()) {
if (v.name.equals("$index")) {
// Check if $n has become constant 1, that is, if we have detected a singleton in later processing.
// In this case, $index should become constant 0.
Variable n = find(new Variable("$n"));
if (n != null && n.hasAttribute("constant")) {
if (n.equations.first().expression.getDouble() == 1) {
changed = true;
v.removeAttribute("initOnly");
v.addAttribute("constant");
v.unit = AbstractUnit.ONE;
v.equations = new TreeSet<EquationEntry>();
EquationEntry e = new EquationEntry(v, "");
e.expression = new Constant(0);
e.expression.unit = AbstractUnit.ONE;
v.add(e);
}
}
} else if (// $t'
v.name.equals("$t") && v.order == 1 && container != null) {
// Copy constant $t' from container.
Variable parentDt = container.find(v);
if (parentDt.hasAttribute("constant")) {
changed = true;
v.addAttribute("constant");
EquationEntry e = new EquationEntry(v, "");
v.add(e);
EquationEntry parentE = parentDt.equations.first();
e.expression = new Constant(parentE.expression.getDouble());
e.expression.unit = AbstractUnit.ONE;
}
}
}
continue;
}
// At this point, the variable satisfies most of the requirements to be constant.
// It has no external writers or derivatives, so only its single equation can change it.
// The remaining question is whether the equation is an unconditional constant.
EquationEntry e = v.equations.first();
// Notice that a constant equation conditioned on $init is effectively unconditional.
if (e.condition != null && !e.ifString.equals("$init"))
continue;
if (e.expression instanceof Constant) {
changed = true;
v.addAttribute("constant");
// in case it was $init
e.condition = null;
e.ifString = "";
}
}
for (EquationSet s : parts) {
if (s.findConstantsEval())
changed = true;
}
return changed;
}
use of gov.sandia.n2a.language.type.Instance in project n2a by frothga.
the class Population method finish.
public boolean finish(Simulator simulator) {
InternalBackendData bed = (InternalBackendData) equations.backendData;
// Capture $n before finalize, so we can compare it for changes.
double oldN = 0;
if (bed.populationCanResize)
oldN = ((Scalar) get(bed.n)).value;
// Finalize
for (Variable v : bed.globalBufferedExternal) setFinal(v, getFinal(v));
clearExternalWriteBuffers(bed.globalBufferedExternalWrite);
// Structural dynamics
if (bed.populationCanResize) {
// This is the finalized value of $n.
int newN = Math.max(0, (int) ((Scalar) get(bed.n)).value);
if (// $n shares control with other specials, so coordinate them.
bed.populationCanGrowOrDie) {
if (bed.n.derivative == null) {
if (// $n was explicitly changed, so its value takes precedence
newN != oldN)
// $n was explicitly changed, so its value takes precedence
simulator.resize(this, (int) newN);
else
// -1 means to update $n from this.n. This can only be done after other parts are finalized, as they may impose structural dynamics via $p or $type.
simulator.resize(this, -1);
} else // the rate of change in $n is pre-determined, so it relentlessly overrides any other structural dynamics
{
simulator.resize(this, newN);
}
} else // $n is the only kind of structural dynamics, so only do a resize() when needed
{
if (newN != n)
simulator.resize(this, newN);
}
}
if (equations.connectionBindings != null) {
// Check poll deadline.
boolean shouldConnect = false;
if (bed.poll >= 0) {
double pollDeadline = valuesFloat[bed.pollDeadline];
double t = simulator.currentEvent.t;
if (t >= pollDeadline)
shouldConnect = true;
}
// To limit work, only do this for shallow structures that don't require enumerating sub-populations.
if (!shouldConnect) {
for (ConnectionBinding target : equations.connectionBindings) {
InternalBackendData cbed = (InternalBackendData) target.endpoint.backendData;
if (cbed.singleton)
continue;
// Resolve binding
Instance current = this;
for (Object o : target.resolution) {
Resolver r = (Resolver) o;
if (r.shouldEnumerate(current))
break;
current = r.resolve(current);
}
if (current.equations != target.endpoint)
continue;
int firstborn = (int) current.valuesFloat[cbed.firstborn];
@SuppressWarnings("unchecked") int size = (int) ((List<Part>) current.valuesObject[cbed.instances]).size();
if (firstborn < size) {
shouldConnect = true;
break;
}
}
}
if (shouldConnect)
simulator.connect(this);
}
return true;
}
use of gov.sandia.n2a.language.type.Instance in project n2a by frothga.
the class SymbolStateVar1 method getDefinition.
@Override
public String getDefinition(XyceRenderer renderer) {
String translatedEq = renderer.change(eq.expression);
Variable v = eq.variable;
VariableReference r = v.reference;
if (// symbol is defined here; no += allowed within same part
r.index < 0) {
return Xyceisms.defineDiffEq(v.name, renderer.pi.hashCode(), translatedEq);
}
// This symbol refers to a symbol in another part. We don't re-define the
// variable, rather we create another diff eq that updates the existing one.
Instance target = (Instance) renderer.pi.valuesObject[r.index];
String thisVarname = r.variable.name + "_" + target.hashCode();
String eqName = v.name + "_" + renderer.pi.hashCode();
return Xyceisms.updateDiffEq(eqName, thisVarname, translatedEq);
}
use of gov.sandia.n2a.language.type.Instance in project n2a by frothga.
the class EventSpikeMulti method run.
public void run(Simulator simulator) {
setFlag();
for (Instance i : targets) simulator.integrate(i);
for (Instance i : targets) i.update(simulator);
for (Instance i : targets) {
boolean live = i.finish(simulator);
InternalBackendData bed = (InternalBackendData) i.equations.backendData;
for (Variable v : bed.eventReferences) ((Instance) i.valuesObject[v.reference.index]).finishEvent(v.reference.variable);
if (!live)
i.dequeue();
}
}
Aggregations