use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class EquationSet method addSpecials.
/**
* Add variables to equation set that are needed, but that the user should not normally define.
* Depends on results of: none
*/
public void addSpecials() {
for (EquationSet s : parts) {
s.addSpecials();
}
// force $init to exist
setInit(0);
Variable v = new Variable("$t", 0);
if (add(v)) {
v.equations = new TreeSet<EquationEntry>();
}
// $t'
v = new Variable("$t", 1);
if (add(v)) {
v.equations = new TreeSet<EquationEntry>();
}
if (// top-level model
container == null) {
// must have a termination condition
v = new Variable("$p", 0);
if (// but it doesn't
add(v)) {
try {
// limit sim time to 1 second, if not otherwise specified
String duration = getNamedValue("duration", "1");
v.add(new EquationEntry("$t<" + duration));
} catch (Exception parseError) {
try {
v.add(new EquationEntry("$t<1"));
}// This exception should never happen. We simply want to silence Java about it.
catch (Exception parseError2) {
}
}
}
}
// $live functions much the same as $init. See setInit().
v = new Variable("$live", 0);
if (add(v)) {
// default. Actual values should be set by setAttributeLive()
v.addAttribute("constant");
EquationEntry e = new EquationEntry(v, "");
e.expression = new Constant(new Scalar(1));
v.add(e);
}
v = new Variable("$type", 0);
if (add(v)) {
v.equations = new TreeSet<EquationEntry>();
}
if (connected || connectionBindings == null) {
v = new Variable("$index", 0);
if (add(v)) {
// most backends will set $index before processing init equations
v.addAttribute("initOnly");
v.equations = new TreeSet<EquationEntry>();
} else {
v = find(v);
}
// Force $index to exist for connection targets. Used for anti-indexing into list of instances.
if (connected)
v.addUser(this);
v = new Variable("$n", 0);
if (add(v)) {
// default. Actual values set by client code.
v.addAttribute("constant");
EquationEntry e = new EquationEntry(v, "");
e.expression = new Constant(new Scalar(1));
v.add(e);
}
}
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class EquationSet method getInit.
public boolean getInit() {
Variable init = find(new Variable("$init"));
if (init == null)
return false;
EquationEntry e = init.equations.first();
return ((Scalar) ((Constant) e.expression).value).value == 1.0;
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class EquationSet method setInit.
/**
* Change the value of the constant $init in the current equation set.
* Used to indicate if we are in the init phase or not.
*/
public void setInit(float value) {
Variable init = find(new Variable("$init"));
if (init == null) {
init = new Variable("$init", 0);
// TODO: should really be "initOnly", since it changes value during (at the end of) the init cycle.
init.addAttribute("constant");
EquationEntry e = new EquationEntry(init, "");
e.expression = new Constant(new Scalar(value));
init.add(e);
add(init);
} else {
EquationEntry e = init.equations.first();
((Scalar) ((Constant) e.expression).value).value = value;
}
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class JobC method generateStatic.
public void generateStatic(final EquationSet s, final StringBuilder result) {
for (EquationSet p : s.parts) generateStatic(p, result);
// Generate static definitions
final BackendDataC bed = (BackendDataC) s.backendData;
class CheckStatic extends Visitor {
public boolean global;
public boolean visit(Operator op) {
if (op instanceof Constant) {
Type m = ((Constant) op).value;
if (m instanceof Matrix) {
Matrix A = (Matrix) m;
int rows = A.rows();
int cols = A.columns();
String matrixName = "Matrix" + matrixNames.size();
matrixNames.put(op, matrixName);
if (rows == 3 && cols == 1)
result.append("Vector3 " + matrixName + " = Matrix<float>");
else
result.append("Matrix<float> " + matrixName);
result.append(" (\"" + A + "\");\n");
}
// Don't try to descend tree from here
return false;
}
if (op instanceof Function) {
Function f = (Function) op;
if (// We need to auto-generate the column name.
f instanceof Output && f.operands.length < 3) {
String stringName = "columnName" + stringNames.size();
stringNames.put(op, stringName);
if (global) {
bed.setGlobalNeedPath(s);
bed.globalColumns.add(stringName);
} else {
bed.setLocalNeedPath(s);
bed.localColumns.add(stringName);
}
}
// Detect functions that need static handles
if (f.operands.length > 0) {
Operator operand0 = f.operands[0];
if (operand0 instanceof Constant) {
Constant c = (Constant) operand0;
Type o = c.value;
if (o instanceof Text) {
String fileName = ((Text) o).value;
if (op instanceof ReadMatrix) {
if (!matrixNames.containsKey(fileName)) {
String matrixName = "Matrix" + matrixNames.size();
matrixNames.put(fileName, matrixName);
result.append("MatrixInput * " + matrixName + " = matrixHelper (\"" + fileName + "\");\n");
}
} else if (f instanceof Input) {
if (!inputNames.containsKey(fileName)) {
String inputName = "Input" + inputNames.size();
inputNames.put(fileName, inputName);
result.append("InputHolder * " + inputName + " = inputHelper (\"" + fileName + "\");\n");
}
} else if (f instanceof Output) {
if (!outputNames.containsKey(fileName)) {
String outputName = "Output" + outputNames.size();
outputNames.put(fileName, outputName);
result.append("OutputHolder * " + outputName + " = outputHelper (\"" + fileName + "\");\n");
}
}
}
} else // Dynamic file name (no static handle)
{
if (f instanceof ReadMatrix) {
matrixNames.put(op, "Matrix" + matrixNames.size());
stringNames.put(operand0, "fileName" + stringNames.size());
} else if (f instanceof Input) {
inputNames.put(op, "Input" + inputNames.size());
stringNames.put(operand0, "fileName" + stringNames.size());
} else if (f instanceof Output) {
outputNames.put(op, "Output" + outputNames.size());
stringNames.put(operand0, "fileName" + stringNames.size());
}
}
}
// Functions could be nested, so continue descent.
return true;
}
return true;
}
}
CheckStatic checkStatic = new CheckStatic();
for (Variable v : s.ordered) {
checkStatic.global = v.hasAttribute("global");
v.visit(checkStatic);
}
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class InternalBackendData method analyzeEvents.
public static void analyzeEvents(final EquationSet s, final List<EventTarget> eventTargets, final List<Variable> eventReferences) {
class EventVisitor extends Visitor {
public boolean found;
public boolean visit(Operator op) {
if (op instanceof Event) {
found = true;
Event de = (Event) op;
if (// this event has not yet been analyzed
de.eventType == null) {
final EventTarget et = new EventTarget(de);
int targetIndex = eventTargets.indexOf(et);
if (// event target already exists
targetIndex >= 0) {
de.eventType = eventTargets.get(targetIndex);
} else // we must create a new event target, or more properly, fill in the event target we just used as a query object
{
// Create an entry and save the index
targetIndex = eventTargets.size();
eventTargets.add(et);
de.eventType = et;
et.container = s;
// Determine edge type
if (de.operands.length < 3) {
et.edge = EventTarget.RISE;
} else if (de.operands[2] instanceof Constant) {
Constant c = (Constant) de.operands[2];
if (c.value instanceof Text) {
Text t = (Text) c.value;
if (t.value.equalsIgnoreCase("nonzero"))
et.edge = EventTarget.NONZERO;
else if (t.value.equalsIgnoreCase("change"))
et.edge = EventTarget.CHANGE;
else if (t.value.equalsIgnoreCase("fall"))
et.edge = EventTarget.FALL;
else
et.edge = EventTarget.RISE;
} else {
Backend.err.get().println("ERROR: event() edge type must be a string.");
throw new Backend.AbortRun();
}
} else {
Backend.err.get().println("ERROR: event() edge type must be constant.");
throw new Backend.AbortRun();
}
// Allocate auxiliary variable
if (de.operands[0] instanceof AccessVariable) {
AccessVariable av = (AccessVariable) de.operands[0];
VariableReference reference = av.reference;
Variable v = reference.variable;
// then the user has broken the rule that we can't see temporaries in other parts.
if (v.hasAttribute("temporary") && v.container != s) {
Backend.err.get().println("WARNING: Cannot be temporary due to event monitor: " + v.container.name + "." + v.nameString() + " from " + s.name);
v.removeAttribute("temporary");
}
// so fall through to the !trackOne case below.
if (!v.hasAttribute("temporary")) {
// ensure it's buffered, so we can detect change
v.addAttribute("externalRead");
et.trackOne = true;
// just a holder for the reference
et.track = new Variable();
et.track.reference = reference;
}
}
if (// Expression, so create auxiliary variable. Aux not needed for NONZERO, because no change detection.
!et.trackOne && et.edge != EventTarget.NONZERO) {
et.track = new Variable("eventAux" + targetIndex, 0);
et.track.type = new Scalar(0);
et.track.reference = new VariableReference();
et.track.reference.variable = et.track;
}
// Locate any temporaries for evaluation. TODO: for more efficiency, we could have separate lists of temporaries for the condition and delay operands
// Tie into the dependency graph using a phantom variable (which can go away afterward without damaging the graph).
final Variable phantom = new Variable("event");
phantom.uses = new IdentityHashMap<Variable, Integer>();
for (int i = 0; i < et.event.operands.length; i++) et.event.operands[i].visit(new Visitor() {
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
Variable v = av.reference.variable;
if (!phantom.uses.containsKey(v))
phantom.uses.put(v, 1);
return false;
}
return true;
}
});
// Scan all variables in equation set to see if we need them
for (Variable t : s.variables) {
if (t.hasAttribute("temporary") && phantom.dependsOn(t) != null)
et.dependencies.add(t);
}
// Note the default is already set to -1 (no care)
class DelayVisitor extends Visitor {
TreeSet<EquationSet> containers = new TreeSet<EquationSet>();
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
// could include the target part itself, if in fact we use local variables
containers.add(av.reference.variable.container);
return false;
}
return true;
}
}
DelayVisitor dv = new DelayVisitor();
if (de.operands.length >= 2) {
if (de.operands[1] instanceof Constant) {
Constant c = (Constant) de.operands[1];
et.delay = (float) ((Scalar) c.value).value;
if (et.delay < 0)
et.delay = -1;
} else {
// indicates that we need to evaluate delay at run time
et.delay = -2;
de.operands[1].visit(dv);
}
}
// Set up monitors in source parts
class ConditionVisitor extends Visitor {
TreeSet<EquationSet> containers = new TreeSet<EquationSet>();
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
Variable v = av.reference.variable;
EquationSet sourceContainer = v.container;
containers.add(sourceContainer);
// Set up monitors for values that can vary during update.
if (!v.hasAttribute("constant") && !v.hasAttribute("initOnly") && !et.monitors(sourceContainer)) {
EventSource es = new EventSource(sourceContainer, et);
// null means self-reference, a special case handled in Part
if (sourceContainer != s)
es.reference = av.reference;
et.sources.add(es);
}
return false;
}
return true;
}
}
ConditionVisitor cv = new ConditionVisitor();
de.operands[0].visit(cv);
// Special case for event with no references that vary
if (et.sources.isEmpty()) {
// We can avoid creating a self monitor if we know for certain that the event will never fire
boolean neverFires = false;
if (de.operands[0] instanceof Constant) {
if (et.edge == EventTarget.NONZERO) {
Type op0 = ((Constant) de.operands[0]).value;
if (op0 instanceof Scalar) {
neverFires = ((Scalar) op0).value == 0;
} else {
Backend.err.get().println("ERROR: Condition for event() must resolve to a number.");
throw new Backend.AbortRun();
}
} else {
neverFires = true;
}
}
if (!neverFires) {
EventSource es = new EventSource(s, et);
// This is a self-reference, so es.reference should be null.
et.sources.add(es);
}
}
// Determine if monitor needs to test every target, or if one representative target is sufficient
for (EventSource source : et.sources) {
// associated with any given source instance, so every target must be evaluated separately.
if (cv.containers.size() > 1)
source.testEach = true;
if (dv.containers.size() > 1 || (dv.containers.size() == 1 && dv.containers.first() != source.container))
source.delayEach = true;
}
}
}
}
return true;
}
}
EventVisitor eventVisitor = new EventVisitor();
for (Variable v : s.variables) {
eventVisitor.found = false;
v.visit(eventVisitor);
if ((eventVisitor.found || v.dependsOnEvent()) && v.reference.variable != v)
eventReferences.add(v);
}
}
Aggregations