use of gov.sandia.n2a.language.AccessVariable in project n2a by frothga.
the class Output method isStringExpression.
/**
* Determines if the given operator is a string expression.
* This is the case if any operator it depends on is a string.
* If an operand is a variable, then its equations must contain a string.
*/
public static boolean isStringExpression(Variable v, Operator op) {
class StringVisitor extends Visitor {
boolean foundString;
Variable from;
public StringVisitor(Variable from) {
this.from = from;
from.visited = null;
}
public boolean visit(Operator op) {
if (op instanceof Constant) {
Constant c = (Constant) op;
if (c.value instanceof Text)
foundString = true;
return false;
}
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
Variable v = av.reference.variable;
// Prevent infinite recursion
Variable p = from;
while (p != null) {
if (p == v)
return false;
p = p.visited;
}
v.visited = from;
from = v;
v.visit(this);
from = v.visited;
return false;
}
// no reason to dig any further
if (foundString)
return false;
// Add is the only operator that can propagate string values. All other operators and functions return scalars or matrices.
return op instanceof Add;
}
}
StringVisitor visitor = new StringVisitor(v);
op.visit(visitor);
return visitor.foundString;
}
use of gov.sandia.n2a.language.AccessVariable in project n2a by frothga.
the class XyceBackend method generateNetlist.
public void generateNetlist(MNode job, Simulator simulator, FileWriter writer) throws Exception {
Population toplevel = (Population) simulator.wrapper.valuesObject[0];
XyceRenderer renderer = new XyceRenderer(simulator);
// Header
writer.append(toplevel.equations.name + "\n");
writer.append("\n");
writer.append("* seed: " + job.get("$metadata", "seed") + "\n");
writer.append(".tran 0 " + job.get("$metadata", "duration") + "\n");
// Equations
for (Instance i : simulator) {
if (i == simulator.wrapper)
continue;
writer.append("\n");
writer.append("* " + i + "\n");
renderer.pi = i;
renderer.exceptions = null;
XyceBackendData bed = (XyceBackendData) i.equations.backendData;
if (bed.deviceSymbol != null) {
writer.append(bed.deviceSymbol.getDefinition(renderer));
}
InstanceTemporaries temp = new InstanceTemporaries(i, simulator, false, bed.internal);
for (final Variable v : i.equations.variables) {
// Compute variable v
// TODO: how to switch between multiple conditions that can be true during normal operation? IE: how to make Xyce code conditional?
// Perhaps gate each condition (through a transistor?) and sum them at a single node.
// e can be null
EquationEntry e = v.select(temp);
Symbol def = bed.equationSymbols.get(e);
if (def == null)
continue;
writer.append(def.getDefinition(renderer));
// Trace
class TraceFinder extends Visitor {
List<Operator> traces = new ArrayList<Operator>();
public boolean visit(Operator op) {
if (op instanceof Output) {
traces.add(((Output) op).operands[0]);
return false;
}
return true;
}
}
TraceFinder traceFinder = new TraceFinder();
e.expression.visit(traceFinder);
for (Operator trace : traceFinder.traces) {
// We don't know if contents is .func, expression or a node, so always wrap in braces.
writer.append(".print tran {");
if (trace instanceof AccessVariable) {
AccessVariable av = (AccessVariable) trace;
writer.append(renderer.change(av.reference));
} else // trace is an expression
{
if (// this trace wraps the entire equation
e.expression instanceof Output && ((Output) e.expression).operands[0] == trace) {
// simply print the LHS variable, similar to the AccessVariable case above
writer.append(renderer.change(v.reference));
} else {
// arbitrary expression
writer.append(renderer.change(trace));
}
}
// one .print line per variable
writer.append("}\n");
}
}
}
// Trailer
writer.append(".end\n");
}
use of gov.sandia.n2a.language.AccessVariable in project n2a by frothga.
the class XyceRenderer method render.
public boolean render(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
result.append(change(av.reference));
return true;
}
// IE: they are not an ongoing source of randomness during execution.
if (op instanceof Uniform) {
Uniform u = (Uniform) op;
if (u.operands.length > 0) {
int dimension = (int) Math.round(((Scalar) u.operands[0].eval(pi)).value);
if (dimension != 1)
System.err.println("WARNING: Xyce does not support multivariate form of uniform()");
}
result.append("rand()");
return true;
}
if (op instanceof Gaussian) {
Gaussian g = (Gaussian) op;
if (g.operands.length > 0) {
int dimension = (int) Math.round(((Scalar) g.operands[0].eval(pi)).value);
if (dimension != 1)
System.err.println("WARNING: Xyce does not support multivariate form of gaussian()");
}
result.append("agauss(0,6,6)");
return true;
}
if (op instanceof Power) {
Power p = (Power) op;
result.append("(");
p.operand0.render(this);
result.append(") ** (");
p.operand1.render(this);
result.append(")");
return true;
}
return false;
}
use of gov.sandia.n2a.language.AccessVariable in project n2a by frothga.
the class EquationSet method resolveConnectionBindings.
/**
* Scan for equations that look and smell like connection bindings.
* A binding equation has these characteristics:
* <ul>
* <li>Only one equation on the variable.
* <li>Unconditional (conditional bindings are not permitted)
* <li>No operators, only a name on RHS that appears like a variable name.
* <li>Both LHS and RHS are order 0 (not derivatives)
* <li>No variable in the current equation set matches the name.
* </ul>
* $up is permitted. The explicit name of a higher container may also be used.
* $connect should not appear. It should have been overwritten during construction.
* If $connect does appear, bindings are incomplete, which is an error.
*/
public void resolveConnectionBindings(LinkedList<String> unresolved) throws Exception {
// need to use an iterator here, so we can remove variables from the set
Iterator<Variable> it = variables.iterator();
while (it.hasNext()) {
Variable v = it.next();
// Detect instance variables
if (v.order > 0)
continue;
if (v.equations.size() != 1)
continue;
if (v.assignment != Variable.REPLACE)
continue;
EquationEntry ee = v.equations.first();
if (ee.condition != null)
continue;
if (!(ee.expression instanceof AccessVariable))
continue;
AccessVariable av = (AccessVariable) ee.expression;
if (av.getOrder() > 0)
continue;
if (find(new Variable(av.getName())) != null)
continue;
// Resolve connection endpoint to a specific equation set
ConnectionBinding result = new ConnectionBinding();
if (!resolveConnectionBinding(av.name, result)) {
// Only report simple names here, to minimize confusion.
if (!av.name.contains("."))
unresolved.add(prefix() + "." + v.nameString() + " --> " + av.name);
continue;
}
// Could be a variable or prefix referring to an already-found connection.
if (result.endpoint == null)
continue;
// Store connection binding
if (connectionBindings == null)
connectionBindings = new ArrayList<ConnectionBinding>();
result.alias = v.name;
result.index = connectionBindings.size();
connectionBindings.add(result);
result.endpoint.connected = true;
// Should no longer be in the equation list, as there is nothing further to compute.
it.remove();
}
// The population reached in the first descent needs to be tracked.
if (connectionBindings != null) {
for (ConnectionBinding c : connectionBindings) {
int last = c.resolution.size() - 1;
for (int i = 1; i < last; i++) {
Object o0 = c.resolution.get(i - 1);
if (!(o0 instanceof EquationSet))
continue;
Object o1 = c.resolution.get(i);
if (!(o1 instanceof EquationSet))
continue;
Object o2 = c.resolution.get(i + 1);
if (!(o2 instanceof EquationSet))
continue;
EquationSet s0 = (EquationSet) o0;
EquationSet s1 = (EquationSet) o1;
EquationSet s2 = (EquationSet) o2;
if (// double descent
s1.container == s0 && s2.container == s1) {
s1.needInstanceTracking = true;
}
}
}
}
// Descend to child parts after resolving parent. This order is necessary to support nested connections.
for (EquationSet s : parts) {
s.resolveConnectionBindings(unresolved);
}
}
use of gov.sandia.n2a.language.AccessVariable in project n2a by frothga.
the class EquationSet method determineDuration.
/**
* Infers length of simulation based on contents of equation set, particularly
* an expression for top-level $p that involves $t.
* Depends on results of: determineTypes() -- to set up Variable.type member with usable values
*/
public void determineDuration() {
Variable p = find(new Variable("$p", 0));
if (p != null && p.equations.size() == 1) {
Operator expression = p.equations.first().expression;
Operator variable = null;
Operator value = null;
if (// only true if expression is not null
expression instanceof LT || expression instanceof LE) {
OperatorBinary comparison = (OperatorBinary) expression;
variable = comparison.operand0;
value = comparison.operand1;
} else if (expression instanceof GT || expression instanceof GE) {
OperatorBinary comparison = (OperatorBinary) expression;
variable = comparison.operand1;
value = comparison.operand0;
}
if (variable instanceof AccessVariable && ((AccessVariable) variable).name.equals("$t")) {
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;
}
};
Type result = value.eval(instance);
if (result instanceof Scalar)
setNamedValue("duration", new Double(((Scalar) result).value).toString());
}
}
}
Aggregations