use of gov.sandia.n2a.language.type.Scalar 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.type.Scalar in project n2a by frothga.
the class EquationSet method resolveRHS.
public void resolveRHS(LinkedList<String> unresolved) {
for (EquationSet s : parts) {
s.resolveRHS(unresolved);
}
class Resolver extends Transformer {
public Variable from;
public LinkedList<String> unresolved;
public String fromName() {
String result = from.container.prefix();
if (!result.isEmpty())
result += ".";
return result + from.nameString();
}
public Operator transform(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
Variable query = new Variable(av.getName(), av.getOrder());
query.reference = new VariableReference();
EquationSet dest = resolveEquationSet(query, false);
if (dest == null) {
unresolved.add(av.name + "\t" + fromName());
} else {
query.reference.variable = dest.find(query);
if (query.reference.variable == null) {
if (query.name.equals("(connection)")) {
// create a phantom variable. TODO: should this be an attribute instead?
query.reference.variable = new Variable("(connection)");
// the container itself is really the target
query.reference.variable.container = dest;
// because instance variables are bound before the part is put into service, and remain constant for its entire life
query.reference.variable.addAttribute("initOnly");
// TODO: when $connect() is implemented, instances should become first class variables in the equation set, and this circular reference will be created by resolveLHS()
query.reference.variable.reference = query.reference;
} else if (// accountable endpoint
query.name.equals("$count")) {
if (dest.accountableConnections == null)
dest.accountableConnections = new TreeSet<AccountableConnection>();
String alias = av.name.split("\\.", 2)[0];
AccountableConnection ac = new AccountableConnection(EquationSet.this, alias);
if (!dest.accountableConnections.add(ac))
ac = dest.accountableConnections.floor(ac);
if (ac.count == null) {
// Create a fully-functional variable.
// However, it never gets formally added to dest, because dest should never evaluate it.
// Rather, it is maintained by the backend's connection system.
ac.count = new Variable(prefix() + ".$count");
ac.count.type = new Scalar(0);
ac.count.container = dest;
ac.count.equations = new TreeSet<EquationEntry>();
query.reference.variable = ac.count;
query.reference.variable.reference = query.reference;
} else {
query.reference.variable = ac.count;
}
} else {
unresolved.add(av.name + "\t" + fromName());
}
} else {
Variable target = query.reference.variable;
from.addDependencyOn(target);
if (from.container != target.container) {
target.addAttribute("externalRead");
if (target.hasAttribute("temporary")) {
Backend.err.get().println("WARNING: Variable " + target.container.prefix() + "." + target.nameString() + " has an external read, so cannot be temporary.");
target.removeAttribute("temporary");
}
}
}
}
av.reference = query.reference;
return av;
}
if (op instanceof Split) {
Split split = (Split) op;
int count = split.names.length;
split.parts = new ArrayList<EquationSet>(count);
for (int i = 0; i < count; i++) {
String temp = split.names[i];
EquationSet part = container.parts.floor(new EquationSet(temp));
if (part.name.equals(temp))
split.parts.add(part);
else
unresolved.add(temp + "\t" + fromName());
}
}
return null;
}
}
Resolver resolver = new Resolver();
for (Variable v : variables) {
resolver.from = v;
resolver.unresolved = unresolved;
v.transform(resolver);
}
}
use of gov.sandia.n2a.language.type.Scalar 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.type.Scalar in project n2a by frothga.
the class AccessVariable method simplify.
public Operator simplify(Variable from) {
// unresolved!
if (reference == null || reference.variable == null)
return this;
Variable v = reference.variable;
// specifically prevent $init and $live from being replaced by a Constant
if (v.name.equals("$init") || v.name.equals("$live"))
return this;
// A variable may locally evaluate to a constant, yet be subject to change from outside equations.
if (v.hasAttribute("externalWrite"))
return this;
if (v.equations.size() != 1)
return this;
EquationEntry e = v.equations.first();
if (e.expression == null)
return this;
if (e.condition != null) {
if (!(e.condition instanceof Constant))
return this;
// Check for nonzero constant
Type value = ((Constant) e.condition).value;
// This second condition should be eliminated by Variable.simplify(), but until it is, don't do anything here.
if (!(value instanceof Scalar) || ((Scalar) value).value == 0)
return this;
}
if (e.expression instanceof Constant) {
from.removeDependencyOn(v);
from.changed = true;
return e.expression;
}
// Attempt to simplify expression, and maybe get a Constant
Variable p = from;
while (p != null) {
// can't simplify, because we've already visited this variable
if (p == v)
return this;
p = p.visited;
}
v.visited = from;
e.expression = e.expression.simplify(v);
if (e.expression instanceof Constant) {
from.removeDependencyOn(v);
from.changed = true;
return e.expression;
}
if (// Our variable is simply an alias for another variable, so grab the other variable instead.
e.expression instanceof AccessVariable) {
AccessVariable av = (AccessVariable) e.expression;
Variable v2 = av.reference.variable;
if (v2 == v)
return this;
// Can't reference a temporary outside the current equation set.
if (v2.hasAttribute("temporary") && v2.container != from.container)
return this;
// Note: Folding an aliased variable will very likely remove one or more steps of delay in the movement of values through an equation set.
// This might go against the user's intention. The folding can be blocked by adding a condition
reference = av.reference;
name = av.reference.variable.nameString();
from.removeDependencyOn(v);
from.addDependencyOn(v2);
from.changed = true;
}
return this;
}
use of gov.sandia.n2a.language.type.Scalar in project n2a by frothga.
the class BuildMatrix method eval.
public Type eval(Instance context) throws EvaluationException {
int columns = operands.length;
if (columns == 0)
return new MatrixDense();
int rows = operands[0].length;
if (rows == 0)
return new MatrixDense();
Matrix result = new MatrixDense(rows, columns);
for (int c = 0; c < columns; c++) {
for (int r = 0; r < rows; r++) {
if (operands[c][r] == null) {
result.set(r, c, 0);
} else {
Type o = operands[c][r].eval(context);
if (o instanceof Scalar)
result.set(r, c, ((Scalar) o).value);
else if (o instanceof Text)
result.set(r, c, Double.valueOf(((Text) o).value));
else if (o instanceof Matrix)
result.set(r, c, ((Matrix) o).get(0, 0));
else
throw new EvaluationException("Can't construct matrix element from the given type.");
}
}
}
return result;
}
Aggregations