use of gov.sandia.n2a.language.Operator in project n2a by frothga.
the class Multiply method simplify.
public Operator simplify(Variable from) {
Operator result = super.simplify(from);
if (result != this)
return result;
// This will be reversed below if we don't actually make a change.
from.changed = true;
if (operand0 instanceof Constant) {
Type c0 = ((Constant) operand0).value;
if (c0 instanceof Scalar) {
double value = ((Scalar) c0).value;
if (value == 1)
return operand1;
if (value == 0) {
operand1.releaseDependencies(from);
return new Constant(new Scalar(0));
}
}
} else if (operand1 instanceof Constant) {
Type c1 = ((Constant) operand1).value;
if (c1 instanceof Scalar) {
double value = ((Scalar) c1).value;
if (value == 1)
return operand0;
if (value == 0) {
operand0.releaseDependencies(from);
return new Constant(new Scalar(0));
}
}
}
from.changed = false;
return this;
}
use of gov.sandia.n2a.language.Operator in project n2a by frothga.
the class MultiplyElementwise method simplify.
public Operator simplify(Variable from) {
Operator result = super.simplify(from);
if (result != this)
return result;
// This will be reversed below if we don't actually make a change.
from.changed = true;
if (operand0 instanceof Constant) {
Type c0 = ((Constant) operand0).value;
if (c0 instanceof Scalar) {
double value = ((Scalar) c0).value;
if (value == 1)
return operand1;
}
} else if (operand1 instanceof Constant) {
Type c1 = ((Constant) operand1).value;
if (c1 instanceof Scalar) {
double value = ((Scalar) c1).value;
if (value == 1)
return operand0;
}
}
from.changed = false;
return this;
}
use of gov.sandia.n2a.language.Operator 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.Operator 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.Operator in project n2a by frothga.
the class XyceBackendData method analyze.
public void analyze(EquationSet s) {
if (Device.isXyceDevice(s)) {
deviceSymbol = new Device(s);
}
class ContainsOperator extends Visitor {
@SuppressWarnings("rawtypes")
public Class targetClass;
boolean found;
public boolean visit(Operator op) {
if (found)
return false;
if (op.getClass().equals(targetClass)) {
found = true;
return false;
}
return true;
}
public boolean check(EquationEntry e) {
found = false;
e.expression.visit(this);
return found;
}
}
ContainsOperator containsPulse = new ContainsOperator();
containsPulse.targetClass = Pulse.class;
ContainsOperator containsSinewave = new ContainsOperator();
containsSinewave.targetClass = Sinewave.class;
ContainsVariable containsT = new ContainsVariable(new Variable("$t", 0));
for (Variable v : s.variables) {
// in a static (no structural dynamics) simulation, no $variable needs to be computed at runtime
if (v.name.startsWith("$"))
continue;
// Constants are already subbed in. "initOnly" values are defined during init cycle, and can now be subbed during code generation.
if (v.hasAttribute("constant") || v.hasAttribute("initOnly"))
continue;
for (EquationEntry eq : v.equations) {
// don't need to write out equations defining dynamics already defined by a device
if (Device.isXyceDevice(s) && Device.ignoreEquation(eq))
continue;
Symbol handler = null;
if (eq.variable.order > 1) {
Backend.err.get().println("Support for higher order differential equations not implemented yet (" + eq + ")");
throw new Backend.AbortRun();
} else if (eq.variable.order == 1) {
handler = new SymbolStateVar1(eq);
} else // The following are all order 0
if (containsPulse.check(eq)) {
handler = new SymbolPulse(eq);
} else if (containsSinewave.check(eq)) {
handler = new SymbolSinewave(eq);
} else // TODO: this doesn't seem like an adequate test. Why would having a $t be the only reason to generate a zero-order symbol?
if (containsT.check(eq.expression)) {
handler = new SymbolStateVar0(eq);
} else if (isExplicitInit(eq)) {
handler = new SymbolConstantIC(eq);
} else {
// The RHS expression depends on state variables, so we create a netlist .func for it.
handler = new SymbolFunc(eq);
}
equationSymbols.put(eq, handler);
// May set the handler for v several times, but only the last one is kept. Multiple handlers should agree on symbol for reference. Better yet is to handle multiple equations together.
variableSymbols.put(v.name, handler);
}
}
}
Aggregations