Search in sources :

Example 41 with Variable

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;
}
Also used : Variable(gov.sandia.n2a.eqset.Variable)

Example 42 with Variable

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;
        }
    }
}
Also used : Variable(gov.sandia.n2a.eqset.Variable)

Example 43 with Variable

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);
    }
}
Also used : MPart(gov.sandia.n2a.eqset.MPart) AccessVariable(gov.sandia.n2a.language.AccessVariable) NodeVariable(gov.sandia.n2a.ui.eq.tree.NodeVariable) Variable(gov.sandia.n2a.eqset.Variable) PanelEquationGraph(gov.sandia.n2a.ui.eq.PanelEquationGraph) ArrayList(java.util.ArrayList) PanelEquations(gov.sandia.n2a.ui.eq.PanelEquations) MNode(gov.sandia.n2a.db.MNode) NodeBase(gov.sandia.n2a.ui.eq.tree.NodeBase) TreeNode(javax.swing.tree.TreeNode) ArrayList(java.util.ArrayList) List(java.util.List) EquationEntry(gov.sandia.n2a.eqset.EquationEntry) PanelEquationTree(gov.sandia.n2a.ui.eq.PanelEquationTree) FilteredTreeModel(gov.sandia.n2a.ui.eq.FilteredTreeModel) HashSet(java.util.HashSet) EquationSet(gov.sandia.n2a.eqset.EquationSet) CannotRedoException(javax.swing.undo.CannotRedoException) NodeVariable(gov.sandia.n2a.ui.eq.tree.NodeVariable) CannotRedoException(javax.swing.undo.CannotRedoException) JTree(javax.swing.JTree) TreePath(javax.swing.tree.TreePath) NodePart(gov.sandia.n2a.ui.eq.tree.NodePart)

Example 44 with Variable

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));
    }
}
Also used : Variable(gov.sandia.n2a.eqset.Variable) Scalar(gov.sandia.n2a.language.type.Scalar)

Example 45 with Variable

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;
}
Also used : Variable(gov.sandia.n2a.eqset.Variable) Instance(gov.sandia.n2a.language.type.Instance) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) Scalar(gov.sandia.n2a.language.type.Scalar)

Aggregations

Variable (gov.sandia.n2a.eqset.Variable)63 AccessVariable (gov.sandia.n2a.language.AccessVariable)38 EquationSet (gov.sandia.n2a.eqset.EquationSet)25 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)20 Scalar (gov.sandia.n2a.language.type.Scalar)18 Operator (gov.sandia.n2a.language.Operator)17 ArrayList (java.util.ArrayList)17 Type (gov.sandia.n2a.language.Type)12 Visitor (gov.sandia.n2a.language.Visitor)12 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)11 MNode (gov.sandia.n2a.db.MNode)9 VariableReference (gov.sandia.n2a.eqset.VariableReference)9 Constant (gov.sandia.n2a.language.Constant)9 MPart (gov.sandia.n2a.eqset.MPart)7 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)6 Output (gov.sandia.n2a.language.function.Output)6 FilteredTreeModel (gov.sandia.n2a.ui.eq.FilteredTreeModel)6 List (java.util.List)6 IncommensurableException (javax.measure.IncommensurableException)6 UnconvertibleException (javax.measure.UnconvertibleException)6