use of gov.sandia.n2a.language.AccessVariable 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.AccessVariable 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;
if ((v.name.startsWith("$") || v.name.contains(".$")) && !v.name.startsWith("$up."))
continue;
Type value;
if (// and v is not "constant", but that is covered above
v.derivative != null) {
// this should exist, so no need to verify result
value = find(new Variable(v.name, v.order + 1)).type;
} else {
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;
}
};
// can return null if no equation's condition is true
value = v.eval(instance);
}
if (value != null && value.betterThan(v.reference.variable.type)) {
v.reference.variable.type = value;
// convenience, so that a reference knows its type, not merely its target
v.type = value;
changed = true;
}
}
for (EquationSet s : parts) {
if (s.determineTypesEval())
changed = true;
}
return changed;
}
use of gov.sandia.n2a.language.AccessVariable in project n2a by frothga.
the class EquationSet method dump.
public String dump(boolean showNamespace, String prefix) {
Renderer renderer;
if (showNamespace) {
class Prefixer extends Renderer {
public boolean render(Operator op) {
if (!(op instanceof AccessVariable))
return false;
AccessVariable av = (AccessVariable) op;
if (av.reference == null || av.reference.variable == null) {
result.append("<unresolved!>" + av.name);
} else {
result.append("<" + av.reference.variable.container.prefix() + ">" + av.reference.variable.nameString());
}
return true;
}
}
renderer = new Prefixer();
} else {
renderer = new Renderer();
}
renderer.result.append(prefix + name + "\n");
prefix = prefix + " ";
if (connectionBindings != null) {
for (ConnectionBinding c : connectionBindings) {
renderer.result.append(prefix + c.alias + " = ");
EquationSet s = c.endpoint;
if (showNamespace) {
renderer.result.append("<");
if (s.container != null) {
renderer.result.append(s.container.prefix());
}
renderer.result.append(">");
}
renderer.result.append(s.name + "\n");
}
}
for (Variable v : variables) {
if (// If no equations, then this is an implicit variable, so no need to list here.
v.equations.size() > 0) {
renderer.result.append(prefix + v.nameString());
renderer.result.append(" =" + v.combinerString());
if (v.equations.size() == 1) {
renderer.result.append(" ");
v.equations.first().render(renderer);
renderer.result.append("\n");
} else {
renderer.result.append("\n");
for (EquationEntry e : v.equations) {
renderer.result.append(prefix + " ");
e.render(renderer);
renderer.result.append("\n");
}
}
}
}
for (EquationSet e : parts) {
renderer.result.append(e.dump(showNamespace, prefix));
}
return renderer.result.toString();
}
use of gov.sandia.n2a.language.AccessVariable 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;
}
use of gov.sandia.n2a.language.AccessVariable in project n2a by frothga.
the class ExportJob method analyze.
/**
* Find references to $index in connection endpoints, and set up info for ConnectionContext.
*/
public void analyze(EquationSet s) {
for (EquationSet p : s.parts) analyze(p);
for (final Variable v : s.variables) {
Visitor visitor = new Visitor() {
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
VariableReference r = ((AccessVariable) op).reference;
Variable rv = r.variable;
if (rv.container != v.container && !r.resolution.isEmpty()) {
Object o = r.resolution.get(r.resolution.size() - 1);
if (o instanceof ConnectionBinding) {
ConnectionBinding c = (ConnectionBinding) o;
// This is somewhat of a hack, but ConnectionContext assumes the mappings A->0 and B->1.
if (c.alias.equals("A"))
r.index = 0;
if (c.alias.equals("B"))
r.index = 1;
}
}
}
return true;
}
};
v.visit(visitor);
}
}
Aggregations