use of gov.sandia.n2a.language.operator.Divide in project n2a by frothga.
the class Device method getDefinition.
// / Writes an instance-specific use of an internal device.
public String getDefinition(XyceRenderer renderer) {
StringBuilder result = new StringBuilder();
// Nodes that this device connects to
List<String> nodeNames = new ArrayList<String>();
for (int i = 0; i < varnames.size(); i++) {
Variable v = varnames.get(i);
if (v == ground) {
nodeNames.add("0");
} else if (v != empty) {
nodeNames.add(getInstanceVarname(v.reference, renderer.pi));
}
}
// Its specific parameter values will be based on first written part.
if (model == null) {
model = new HashMap<String, String>();
for (Entry<String, Variable> p : paramList.entrySet()) {
// TODO: select() can return null. Should we guard against it?
model.put(p.getKey(), renderer.change(p.getValue().select(renderer.pi).expression));
}
result.append(Xyceisms.defineModel(device.getDeviceTypeName(), device.getDeviceLevel(), modelName, model));
}
// Instance-specific parameters that override model
Map<String, String> instanceParams = new HashMap<String, String>();
for (Entry<String, Variable> p : paramList.entrySet()) {
Variable v = p.getValue();
if (v.global)
continue;
String name = p.getKey();
// TODO: select() can return null. Should we guard against it?
String value = renderer.change(v.select(renderer.pi).expression);
// no need to override model parameter if value is exactly the same
if (model.get(name).equals(value))
continue;
instanceParams.put(name, value);
}
result.append(Xyceisms.defineYDeviceWithModel(device.getDeviceTypeName(), eqSet.name, nodeNames, renderer.pi.hashCode(), modelName, instanceParams));
// Define inputs
for (Integer inputNode : inputs.keySet()) {
// Write a B device definition to update the node associated with the input
// For neurons, this assumes we want to add a current of the form I/C_m
// where the user specifies I and C_m is known.
// Not at all clear what it means to add current to synapse, which doesn't
// have a capacitance of its own, but this will allow adding a user-defined
// current I to a synapse node.
Variable v = inputs.get(inputNode);
AccessVariable av = new AccessVariable(v.reference);
Operator inputEq;
if (device.getDeviceTypeName().equals("neuron")) {
Divide d = new Divide();
d.operand0 = av;
av = new AccessVariable(paramList.get(device.getCapacitanceVar()).reference);
d.operand1 = av;
inputEq = d;
} else {
inputEq = av;
}
String eqName = Xyceisms.referenceVariable(v.name, renderer.pi.hashCode());
String instanceVarName = getInstanceVarname(v.reference, renderer.pi);
result.append(Xyceisms.updateDiffEq(eqName, instanceVarName, renderer.change(inputEq)));
}
return result.toString();
}
use of gov.sandia.n2a.language.operator.Divide in project n2a by frothga.
the class Variable method flattenExpressions.
public void flattenExpressions(Variable v) {
if (assignment != v.assignment && !(// This line and the next say that * and / are compatible with each other, so ignore that case.
(assignment == MULTIPLY && v.assignment == DIVIDE) || (assignment == DIVIDE && v.assignment == MULTIPLY))) {
Backend.err.get().println("WARNING: Flattened variable " + v.container.prefix() + "." + v.nameString() + " has different combining operator than target (" + container.prefix() + "." + nameString() + "). Resolving in favor of higher-precedence operator.");
v.assignment = assignment = Math.max(v.assignment, assignment);
}
if (v.assignment == REPLACE) {
// We want equations from the lower level to override any pre-existing equations in the upper level.
// Why? Because the lower-level equations represent an elaboration of the model, and are thus more specific.
// Note that Internal executes contained populations after the upper-level equations, so the contained
// populations take precedence even without flattening.
NavigableSet<EquationEntry> equations0 = equations;
equations = new TreeSet<EquationEntry>();
// First add the lower-level equations, so they take precedence.
for (EquationEntry e2 : v.equations) add(e2);
for (EquationEntry e0 : equations0) add(e0);
} else {
// For combiners, it is necessary to create new equations for every combination of conditions.
// Of course, unconditional equations and equations with matching conditions can be combined more directly.
// First step is to augment both equation sets with an unconditional form, if they lack it.
EquationEntry query = new EquationEntry(this, "");
EquationEntry e = find(query);
// expression and condition are null; we deal with this below
if (e == null)
add(query);
query = new EquationEntry(v, "");
e = v.find(query);
if (e == null)
v.add(query);
NavigableSet<EquationEntry> equations0 = equations;
equations = new TreeSet<EquationEntry>();
for (EquationEntry e0 : equations0) {
for (EquationEntry e1 : v.equations) {
if (// Condition strings are exactly the same. TODO: compare ASTs for actual logic equivalence.
e0.compareTo(e1) == 0) {
e = new EquationEntry(this, "");
e.condition = e0.condition;
} else if (e0.condition == null) {
// If so, then only those equations should be merged, so skip this one.
if (find(e1) != null)
continue;
e = new EquationEntry(this, "");
e.condition = e1.condition;
} else if (e1.condition == null) {
// Check if e0.condition exists in v.equations
if (v.find(e0) != null)
continue;
e = new EquationEntry(this, "");
e.condition = e0.condition;
} else {
e = new EquationEntry(this, "");
AND and = new AND();
e.condition = and;
and.operand0 = e0.condition;
and.operand1 = e1.condition;
}
if (e.condition != null)
e.ifString = e.condition.render();
// merge expressions
if (e0.expression == null) {
// which could also be null
e.expression = e1.expression;
} else if (e1.expression == null) {
e.expression = e0.expression;
} else // Both expressions exist
{
OperatorBinary op = null;
Function f = null;
switch(v.assignment) {
case ADD:
op = new Add();
break;
case MULTIPLY:
op = new Multiply();
break;
case DIVIDE:
op = new Divide();
break;
case MIN:
f = new Min();
break;
case MAX:
f = new Max();
break;
}
if (op != null) {
op.operand0 = e0.expression;
op.operand1 = e1.expression;
e.expression = op;
} else if (f != null) {
f.operands[0] = e0.expression;
f.operands[1] = e1.expression;
e.expression = f;
}
}
if (e.expression != null)
equations.add(e);
}
}
}
v.equations.clear();
}
Aggregations