use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class JobC method prepareDynamicObjects.
/**
* Build complex sub-expressions into a single local variable that can be referenced by the equation.
*/
public void prepareDynamicObjects(Operator op, final CRenderer context, final boolean init, final String pad) throws Exception {
// Pass 1 -- Strings and matrix expressions
Visitor visitor1 = new Visitor() {
public boolean visit(Operator op) {
if (op instanceof BuildMatrix) {
BuildMatrix m = (BuildMatrix) op;
int rows = m.getRows();
int cols = m.getColumns();
String matrixName = "Matrix" + matrixNames.size();
matrixNames.put(m, matrixName);
if (rows == 3 && cols == 1)
context.result.append(pad + "Vector3 " + matrixName + ";\n");
else
context.result.append(pad + "Matrix<float> " + matrixName + " (" + rows + ", " + cols + ");\n");
for (int r = 0; r < rows; r++) {
if (cols == 1) {
context.result.append(pad + matrixName + "[" + r + "] = ");
m.operands[0][r].render(context);
context.result.append(";\n");
} else {
for (int c = 0; c < cols; c++) {
context.result.append(pad + matrixName + "(" + r + "," + c + ") = ");
m.operands[c][r].render(context);
context.result.append(";\n");
}
}
}
return false;
}
if (op instanceof Add) {
Add a = (Add) op;
String stringName = stringNames.get(a);
if (stringName != null) {
context.result.append(pad + "String " + stringName + ";\n");
for (Operator o : flattenAdd(a)) {
context.result.append(pad + stringName + " += ");
o.render(context);
context.result.append(";\n");
}
return false;
}
}
return true;
}
};
op.visit(visitor1);
// Pass 2 -- Input functions
Visitor visitor2 = new Visitor() {
public boolean visit(Operator op) {
if (op instanceof ReadMatrix) {
ReadMatrix r = (ReadMatrix) op;
if (!(r.operands[0] instanceof Constant)) {
String matrixName = matrixNames.get(r);
String stringName = stringNames.get(r.operands[0]);
context.result.append(pad + "MatrixInput * " + matrixName + " = matrixHelper (" + stringName + ");\n");
}
return false;
}
if (op instanceof Input) {
Input i = (Input) op;
if (!(i.operands[0] instanceof Constant)) {
String inputName = inputNames.get(i);
String stringName = stringNames.get(i.operands[0]);
context.result.append(pad + "InputHolder * " + inputName + " = inputHelper (" + stringName + ");\n");
if (!context.global) {
context.result.append(pad + inputName + "->epsilon = " + resolve(context.bed.dt.reference, context, false) + " / 1000;\n");
}
// Detect time flag
String mode = "";
if (i.operands.length > 3) {
// just assuming it's a constant string
mode = i.operands[3].toString();
} else if (i.operands[1] instanceof Constant) {
Constant c = (Constant) i.operands[1];
if (c.value instanceof Text)
mode = c.toString();
}
if (mode.contains("time")) {
context.result.append(pad + inputName + "->time = true;\n");
}
}
// I/O functions can be nested
return true;
}
if (op instanceof Output) {
Output o = (Output) op;
if (!(o.operands[0] instanceof Constant)) {
String outputName = outputNames.get(o);
String stringName = stringNames.get(o.operands[0]);
context.result.append(pad + "OutputHolder * " + outputName + " = outputHelper (" + stringName + ");\n");
// Detect raw flag
if (o.operands.length > 3) {
Operator op3 = o.operands[3];
if (op3 instanceof Constant) {
if (op3.toString().contains("raw")) {
context.result.append(pad + outputName + "->raw = true;\n");
}
}
}
}
return true;
}
return true;
}
};
op.visit(visitor2);
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class EquationSet method findInitOnlyRecursive.
public boolean findInitOnlyRecursive() {
boolean changed = false;
for (EquationSet s : parts) {
if (s.findInitOnlyRecursive())
changed = true;
}
ReplaceInit replaceInit = new ReplaceInit();
for (final Variable v : variables) {
// Note: some variables get tagged "initOnly" by other means, so don't re-process
if (v.hasAny(new String[] { "initOnly", "constant", "dummy" }))
continue;
// Count equations
int firesDuringInit = 0;
int firesDuringUpdate = 0;
// If we have a single update equation, then we may still be initOnly if it depends only on constants or other initOnly variables. Save the update equation for analysis.
EquationEntry update = null;
for (EquationEntry e : v.equations) {
if (e.condition == null) {
firesDuringInit++;
firesDuringUpdate++;
update = e;
} else {
// init
replaceInit.init = 1;
replaceInit.live = 1;
Operator test = e.condition.deepCopy().transform(replaceInit).simplify(v);
boolean fires = true;
if (test instanceof Constant) {
Constant c = (Constant) test;
if (c.value instanceof Scalar && ((Scalar) c.value).value == 0)
fires = false;
}
if (fires)
firesDuringInit++;
// update
replaceInit.init = 0;
replaceInit.live = 1;
test = e.condition.deepCopy().transform(replaceInit).simplify(v);
fires = true;
if (test instanceof Constant) {
Constant c = (Constant) test;
if (c.value instanceof Scalar && ((Scalar) c.value).value == 0)
fires = false;
}
if (fires) {
firesDuringUpdate++;
update = e;
}
}
}
if (firesDuringUpdate == 0) {
if (firesDuringInit > 0 && v.derivative == null) {
v.addAttribute("initOnly");
changed = true;
}
} else if (// last chance to be "initOnly": must be exactly one equation that is not a combining operator
firesDuringUpdate == 1 && v.assignment == Variable.REPLACE) {
// Determine if our single update equation depends only on constants and initOnly variables
class VisitInitOnly extends Visitor {
// until something falsifies it
boolean isInitOnly = true;
public boolean visit(Operator op) {
if (isInitOnly) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
// constant has already been replaced. Therefore, only the "initOnly" attribute matters here.
if (av.reference == null || av.reference.variable == null)
isInitOnly = false;
Variable r = av.reference.variable;
if (!r.hasAttribute("initOnly"))
isInitOnly = false;
// Also verify that the variables we depend on are available during the appropriate phase of init
if (// Note that temporaries are always available.
isInitOnly && !r.hasAttribute("temporary")) {
if (// we are a $variable, so we can only depend on $index and $init
v.name.startsWith("$")) {
if (!"$index,$init,$live".contains(r.name))
isInitOnly = false;
} else // we are a regular variable, so can only depend on $variables
{
if (!r.name.startsWith("$"))
isInitOnly = false;
}
}
} else if (op instanceof Function) {
Function f = (Function) op;
if (!f.canBeInitOnly())
isInitOnly = false;
}
}
return isInitOnly;
}
}
VisitInitOnly visitor = new VisitInitOnly();
if (update.condition != null)
update.condition.visit(visitor);
if (visitor.isInitOnly) {
update.expression.visit(visitor);
if (visitor.isInitOnly) {
v.addAttribute("initOnly");
changed = true;
}
}
}
if (firesDuringUpdate > 0 && v.derivative != null && !v.hasAttribute("initOnly"))
v.addAttribute("updates");
else
v.removeAttribute("updates");
}
return changed;
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class EquationSet method findLethalVariables.
public void findLethalVariables() {
for (EquationSet s : parts) {
s.findLethalVariables();
}
// Determine if $n can decrease
Variable n = find(new Variable("$n"));
if (n != null) {
for (EquationEntry e : n.equations) {
// Even if each expression is constant, $n could still change during operation if it is a multi-conditional.
if (e.condition != null && !(e.condition instanceof Constant)) {
lethalN = true;
break;
}
if (!(e.expression instanceof Constant)) {
lethalN = true;
break;
}
}
}
// Determine if $p has an assignment less than 1
Variable p = find(new Variable("$p"));
if (p != null) {
// Determine if any equation is capable of setting $p to something besides 1
ReplaceInit replaceInit = new ReplaceInit();
for (EquationEntry e : p.equations) {
if (e.expression instanceof Constant) {
Type value = ((Constant) e.expression).value;
if (value instanceof Scalar) {
if (((Scalar) value).value == 1.0)
continue;
}
}
// Check if condition fires during init phase
if (e.condition != null) {
replaceInit.init = 1;
replaceInit.live = 1;
Operator test = e.condition.deepCopy().transform(replaceInit).simplify(p);
if (test instanceof Constant) {
Constant c = (Constant) test;
if (// Does not fire during init phase
c.value instanceof Scalar && ((Scalar) c.value).value == 0) {
// Check if condition fires during update phase
replaceInit.init = 0;
test = e.condition.deepCopy().transform(replaceInit).simplify(p);
if (test instanceof Constant) {
c = (Constant) test;
// Does not fire during update phase
if (c.value instanceof Scalar && ((Scalar) c.value).value == 0)
continue;
}
}
}
}
lethalP = true;
break;
}
}
// Determine if any splits kill this part
for (// my splits are the parts I can split into
ArrayList<EquationSet> split : // my splits are the parts I can split into
splits) {
if (!split.contains(this)) {
lethalType = true;
break;
}
}
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class EquationSet method findConstantsEval.
protected boolean findConstantsEval() {
boolean changed = false;
for (EquationSet s : parts) {
if (s.findConstantsEval())
changed = true;
}
for (Variable v : variables) {
if (v.simplify())
changed = true;
// If this already has a "constant" tag, it was specially added so presumably correct.
if (v.hasAttribute("constant"))
continue;
// Regardless of the local math, a variable that gets written is not constant.
if (v.hasAttribute("externalWrite"))
continue;
if (v.equations.size() != 1)
continue;
EquationEntry e = v.equations.first();
if (e.condition != null)
continue;
if (e.expression instanceof Constant) {
v.addAttribute("constant");
changed = true;
}
}
return changed;
}
use of gov.sandia.n2a.language.Constant in project n2a by frothga.
the class Variable method simplify.
public boolean simplify() {
if (equations == null)
return false;
changed = false;
TreeSet<EquationEntry> nextEquations = new TreeSet<EquationEntry>();
TreeSet<EquationEntry> alwaysTrue = new TreeSet<EquationEntry>();
for (EquationEntry e : equations) {
if (e.expression != null) {
e.expression = e.expression.simplify(this);
}
if (e.condition != null) {
e.condition = e.condition.simplify(this);
e.ifString = e.condition.render();
}
if (e.condition instanceof Constant) {
Constant c = (Constant) e.condition;
if (c.value instanceof Scalar) {
double value = ((Scalar) c.value).value;
if (value == 0) {
// Drop equation because it will never fire.
changed = true;
continue;
}
alwaysTrue.add(e);
}
} else if (e.ifString.isEmpty() && e.expression instanceof AccessVariable && ((AccessVariable) e.expression).reference.variable == this) {
// Drop this default equation because it is redundant. Simulator always copies value to next cycle when no equation fires.
changed = true;
continue;
}
nextEquations.add(e);
}
if (// Default equation will never be included in alwaysTrue.
alwaysTrue.size() == 1) {
changed = true;
equations = alwaysTrue;
// Make the equation unconditional, since it always fires anyway.
EquationEntry e = equations.first();
e.condition = null;
e.ifString = "";
} else {
equations = nextEquations;
}
return changed;
}
Aggregations