use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.
the class AccessVariable method determineExponent.
public void determineExponent(ExponentContext context) {
Variable v = reference.variable;
// Don't flag a change, because we are merely reflecting the current state of v.
exponent = v.exponent;
center = v.center;
}
use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.
the class Comparison method determineExponent.
public void determineExponent(ExponentContext context) {
operand0.determineExponent(context);
operand1.determineExponent(context);
if (operand0.exponent != UNKNOWN || operand1.exponent != UNKNOWN)
alignExponent(context);
int centerNew = MSB / 2;
int exponentNew = MSB - centerNew;
updateExponent(context, exponentNew, centerNew);
if (operand0 instanceof AccessVariable) {
Variable v = ((AccessVariable) operand0).reference.variable;
if (!v.hasAttribute("preexistent") && (v.bound == null || v.bound.centerPower() < operand1.centerPower())) {
v.bound = operand1;
// Signal that some change happened, though not necessarily to current variable (context.from).
context.changed = true;
}
}
if (operand1 instanceof AccessVariable) {
Variable v = ((AccessVariable) operand1).reference.variable;
if (!v.hasAttribute("preexistent") && (v.bound == null || v.bound.centerPower() < operand0.centerPower())) {
v.bound = operand0;
context.changed = true;
}
}
}
use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.
the class ChangeVariable method apply.
public void apply(String nameBefore, String nameAfter, boolean multi, boolean multiLast) {
NodePart parent = (NodePart) NodeBase.locateNode(path);
if (parent == null)
throw new CannotRedoException();
NodeVariable nodeBefore = (NodeVariable) parent.child(nameBefore);
if (nodeBefore == null)
throw new CannotRedoException();
PanelEquations pe = PanelModel.instance.panelEquations;
PanelEquationTree pet = parent.getTree();
FilteredTreeModel model = null;
if (pet != null)
model = (FilteredTreeModel) pet.tree.getModel();
NodeVariable nodeAfter;
boolean touchedBindings = false;
// Key paths to each variable that references this one.
List<List<String>> references = new ArrayList<List<String>>();
if (nameBefore.equals(nameAfter)) {
nodeAfter = nodeBefore;
// Same as valueAfter. Sub-tree is not relevant here.
nodeAfter.source.set(savedTree.get());
} else {
// Update database
// Move the subtree
MPart mparent = parent.source;
mparent.clear(nameBefore);
// Removes any reference changes in target node.
mparent.clear(nameAfter);
mparent.set(savedTree, nameAfter);
MPart newPart = (MPart) mparent.child(nameAfter);
MPart oldPart = (MPart) mparent.child(nameBefore);
// See ChangePart.apply() for a similar procedure.
try {
// "doc" is a collated model, so changes will also be made to references from inherited nodes.
// Such changes will be saved as an override.
MPart doc = pe.root.source;
// TODO: this is a potentially lengthy operation. For very large models, need to reduce load on EDT. Either maintain incremental compilation, or compile on separate thread.
EquationSet compiled = new EquationSet(doc);
compiled.name = doc.key();
List<String> vkeypath = new ArrayList<String>(path.subList(1, path.size()));
Variable vold;
Variable vnew;
if (oldPart == null) {
EquationSet p = (EquationSet) compiled.getObject(vkeypath);
vold = Variable.fromLHS(nameBefore);
vold.equations = new TreeSet<EquationEntry>();
if (nodeBefore.isBinding)
vold.equations.add(new EquationEntry(newPart.get()));
p.add(vold);
vkeypath.add(Variable.stripContextPrefix(nameAfter));
} else {
vkeypath.add(Variable.stripContextPrefix(nameBefore));
vold = (Variable) compiled.getObject(vkeypath);
vkeypath.set(vkeypath.size() - 1, nameAfter);
}
vnew = (Variable) compiled.getObject(vkeypath);
try {
// This will throw an AbortRun if any connection is not properly bound.
// However, not every connection binding necessarily leads to this variable.
compiled.resolveConnectionBindings();
} catch (Exception e) {
}
try {
compiled.resolveLHS();
} catch (Exception e) {
}
try {
// This will very likely throw an AbortRun exception to report unresolved variables.
// This will do no harm. All we need is that other equations resolve to this variable.
compiled.resolveRHS();
} catch (Exception e) {
}
prepareConnections(compiled);
List<Variable> users = new ArrayList<Variable>();
if (vold.usedBy != null) {
for (Object o : vold.usedBy) {
if (!(o instanceof Variable))
continue;
// On undo, don't touch savedTree or exposed node. They should return to their exact previous values.
if ((o == vnew || o == vold) && nameAfter.equals(this.nameBefore))
continue;
users.add((Variable) o);
}
}
// This kind of relationship is not generally reciprocal, so we must check uses as well as usedBy.
if (vold.uses != null) {
for (Variable v : vold.uses.keySet()) {
if (v.reference.variable == vold)
users.add(v);
}
}
vold.name = vnew.name;
vold.order = vnew.order;
for (Variable v : users) {
// Don't modify expression on variable line itself. Instead, assume the user edited it exactly as intended.
if (v == vnew && v.equations.size() == 1)
continue;
List<String> ref = v.getKeyPath();
MNode n = doc.child(ref.toArray());
String oldKey = n.key();
String newKey = changeReferences(vold, n, v);
if (// Handle a change in variable name.
!newKey.equals(oldKey)) {
NodeBase nb = pe.root.locateNodeFromHere(ref);
n.parent().move(oldKey, newKey);
ref.set(ref.size() - 1, newKey);
nb.source = (MPart) doc.child(ref.toArray());
}
// Queue GUI updates for nodes other than the primary ones.
if (v != vnew && v != vold)
references.add(ref);
}
} catch (Exception e) {
}
// Update GUI
nodeAfter = (NodeVariable) parent.child(nameAfter);
if (oldPart == null) {
if (nodeBefore.isBinding) {
if (parent.graph != null)
parent.connectionBindings.remove(nameBefore);
touchedBindings = true;
}
if (nodeAfter == null) {
nodeAfter = nodeBefore;
nodeAfter.source = newPart;
} else {
if (model == null)
FilteredTreeModel.removeNodeFromParentStatic(nodeBefore);
else
model.removeNodeFromParent(nodeBefore);
}
} else {
if (nodeAfter == null) {
int index = parent.getIndex(nodeBefore);
nodeAfter = new NodeVariable(newPart);
if (model == null)
FilteredTreeModel.insertNodeIntoUnfilteredStatic(nodeAfter, parent, index);
else
model.insertNodeIntoUnfiltered(nodeAfter, parent, index);
}
nodeBefore.build();
nodeBefore.filter();
if (nodeBefore.visible()) {
if (model != null)
model.nodeStructureChanged(nodeBefore);
} else {
parent.hide(nodeBefore, model);
}
}
}
nodeAfter.build();
nodeAfter.filter();
Set<PanelEquationTree> needAnimate = new HashSet<PanelEquationTree>();
if (pet != null) {
needAnimate.add(pet);
// Must be done before invalidateColumns(), because that function causes new columns to be fetched for renderer sizing.
pet.updateHighlights(pet.root, nameAfter);
parent.invalidateColumns(model);
TreeNode[] nodePath = nodeAfter.getPath();
pet.updateOrder(nodePath);
boolean killed = savedTree.get().equals("$kill");
boolean setSelection;
if (killed)
setSelection = !multi || multiLast;
else
setSelection = !multi;
pet.updateVisibility(nodePath, -2, setSelection);
if (multi && !killed)
pet.tree.addSelectionPath(new TreePath(nodePath));
}
for (List<String> ref : references) {
NodeVariable n = (NodeVariable) pe.root.locateNodeFromHere(ref);
if (n == null)
continue;
// Rebuild n, because equations and/or their conditions may have changed.
n.build();
n.findConnections();
n.filter();
if (// n's visibility won't change
n.visible()) {
PanelEquationTree subpet = n.getTree();
if (subpet == null)
continue;
JTree subtree = subpet.tree;
FilteredTreeModel submodel = (FilteredTreeModel) subtree.getModel();
NodeBase subparent = (NodeBase) n.getParent();
boolean added = needAnimate.add(subpet);
if (added)
subpet.updateHighlights(subpet.root, nameAfter);
else
subpet.updateHighlights(n, nameAfter);
subparent.invalidateColumns(null);
// Node will collapse if it was open. Don't worry about this.
submodel.nodeStructureChanged(n);
subpet.updateVisibility(n.getPath(), -2, false);
subparent.allNodesChanged(submodel);
}
}
for (PanelEquationTree ap : needAnimate) ap.animate();
if (parent.updateVariableConnections())
touchedBindings = true;
if (touchedBindings) {
parent.updateSubpartConnections();
// Update edges to pins, if present.
PanelEquationGraph peg = pe.panelEquationGraph;
if (parent.source.child("$metadata", "gui", "pin") != null) {
parent.updatePins();
peg.updatePins();
}
// Rebuild all edges on canvas, whether regular connection or pin.
peg.reconnect();
peg.repaint();
MPart mparent = parent.source;
if (mparent.root() == mparent)
PanelModel.instance.panelSearch.updateConnectors(mparent);
}
}
use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.
the class Population method integrate.
public void integrate(Simulator simulator, double dt) {
InternalBackendData bed = (InternalBackendData) equations.backendData;
for (Variable v : bed.globalIntegrated) {
double a = ((Scalar) get(v)).value;
double aa = ((Scalar) get(v.derivative)).value;
setFinal(v, new Scalar(a + aa * dt));
}
}
use of gov.sandia.n2a.eqset.Variable in project n2a by frothga.
the class Population method finish.
public boolean finish(Simulator simulator) {
InternalBackendData bed = (InternalBackendData) equations.backendData;
// Capture $n before finalize, so we can compare it for changes.
double oldN = 0;
if (bed.populationCanResize)
oldN = ((Scalar) get(bed.n)).value;
// Finalize
for (Variable v : bed.globalBufferedExternal) setFinal(v, getFinal(v));
clearExternalWriteBuffers(bed.globalBufferedExternalWrite);
// Structural dynamics
if (bed.populationCanResize) {
// This is the finalized value of $n.
int newN = Math.max(0, (int) ((Scalar) get(bed.n)).value);
if (// $n shares control with other specials, so coordinate them.
bed.populationCanGrowOrDie) {
if (bed.n.derivative == null) {
if (// $n was explicitly changed, so its value takes precedence
newN != oldN)
// $n was explicitly changed, so its value takes precedence
simulator.resize(this, (int) newN);
else
// -1 means to update $n from this.n. This can only be done after other parts are finalized, as they may impose structural dynamics via $p or $type.
simulator.resize(this, -1);
} else // the rate of change in $n is pre-determined, so it relentlessly overrides any other structural dynamics
{
simulator.resize(this, newN);
}
} else // $n is the only kind of structural dynamics, so only do a resize() when needed
{
if (newN != n)
simulator.resize(this, newN);
}
}
if (equations.connectionBindings != null) {
// Check poll deadline.
boolean shouldConnect = false;
if (bed.poll >= 0) {
double pollDeadline = valuesFloat[bed.pollDeadline];
double t = simulator.currentEvent.t;
if (t >= pollDeadline)
shouldConnect = true;
}
// To limit work, only do this for shallow structures that don't require enumerating sub-populations.
if (!shouldConnect) {
for (ConnectionBinding target : equations.connectionBindings) {
InternalBackendData cbed = (InternalBackendData) target.endpoint.backendData;
if (cbed.singleton)
continue;
// Resolve binding
Instance current = this;
for (Object o : target.resolution) {
Resolver r = (Resolver) o;
if (r.shouldEnumerate(current))
break;
current = r.resolve(current);
}
if (current.equations != target.endpoint)
continue;
int firstborn = (int) current.valuesFloat[cbed.firstborn];
@SuppressWarnings("unchecked") int size = (int) ((List<Part>) current.valuesObject[cbed.instances]).size();
if (firstborn < size) {
shouldConnect = true;
break;
}
}
}
if (shouldConnect)
simulator.connect(this);
}
return true;
}
Aggregations