Search in sources :

Example 61 with Operator

use of gov.sandia.n2a.language.Operator in project n2a by frothga.

the class EquationSet method findLethalVariables.

public void findLethalVariables() {
    for (EquationSet s : parts) {
        s.findLethalVariables();
    }
    // Determine if $n can decrease
    Variable n = find(new Variable("$n"));
    if (n != null) {
        for (EquationEntry e : n.equations) {
            // Even if each expression is constant, $n could still change during operation if it is a multi-conditional.
            if (e.condition != null && !(e.condition instanceof Constant)) {
                lethalN = true;
                break;
            }
            if (!(e.expression instanceof Constant)) {
                lethalN = true;
                break;
            }
        }
    }
    // Conservatively, assume any order of derivative could decrease $n.
    if (find(new Variable("$n", 1)) != null)
        lethalN = true;
    // Determine if $p has an assignment less than 1
    Variable p = find(new Variable("$p"));
    if (p != null) {
        // Determine if any equation is capable of setting $p to something besides 1
        ReplacePhaseIndicators replacePhase = new ReplacePhaseIndicators();
        for (EquationEntry e : p.equations) {
            if (e.expression.isScalar() && e.expression.getDouble() >= 1)
                continue;
            // If this occurs anywhere but connect, then $p is lethal.
            if (e.condition != null) {
                replacePhase.init = 1;
                Operator test = e.condition.deepCopy().transform(replacePhase).simplify(p, true);
                if (// Does not fire during init phase
                test.isScalar() && test.getDouble() == 0) {
                    replacePhase.init = 0;
                    test = e.condition.deepCopy().transform(replacePhase).simplify(p, true);
                    // Does not fire during update phase
                    if (test.isScalar() && test.getDouble() == 0)
                        continue;
                }
            }
            lethalP = true;
            break;
        }
    }
    if (find(new Variable("$p", 1)) != null)
        lethalP = true;
    // Determine if any splits kill this part
    for (// my splits are the parts I can split into
    ArrayList<EquationSet> split : // my splits are the parts I can split into
    splits) {
        if (!split.contains(this)) {
            lethalType = true;
            break;
        }
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) Constant(gov.sandia.n2a.language.Constant)

Example 62 with Operator

use of gov.sandia.n2a.language.Operator in project n2a by frothga.

the class EquationSet method purgeInitOnlyTemporary.

/**
 *        findInitOnly() propagates the "initOnly" attribute through temporaries, but the final
 *        attribute set of a variable cannot contain both, as they are mutually contradictory.
 *        "initOnly" requires storage, while "temporary" forbids it. We give "temporary"
 *        precedence, because we prioritize memory efficiency over time efficiency.
 */
public void purgeInitOnlyTemporary() {
    for (EquationSet p : parts) p.purgeInitOnlyTemporary();
    for (Variable v : variables) {
        if (v.hasAll("temporary", "initOnly")) {
            v.removeAttribute("initOnly");
            // If there are no regular update equations, then convert init equations into
            // regular update equations, because their values would continue to hold if the
            // variable were stored.
            // Test for presence of regular update equations.
            // See findInitOnlyRecursive() for similar code.
            boolean firesDuringUpdate = false;
            ReplacePhaseIndicators replacePhase = new ReplacePhaseIndicators();
            replacePhase.init = 0;
            for (EquationEntry e : v.equations) {
                if (e.condition == null) {
                    firesDuringUpdate = true;
                    break;
                } else {
                    Operator test = e.condition.deepCopy().transform(replacePhase).simplify(v, true);
                    if (!test.isScalar() || test.getDouble() != 0) {
                        firesDuringUpdate = true;
                        break;
                    }
                }
            }
            // See Variable.simplify() for similar code.
            if (!firesDuringUpdate) {
                class ReplaceInit implements Transformer {

                    public Operator transform(Operator op) {
                        if (op instanceof AccessVariable) {
                            AccessVariable av = (AccessVariable) op;
                            if (av.name.equals("$init"))
                                return new Constant(1);
                        }
                        return null;
                    }
                }
                ;
                ReplaceInit replaceInit = new ReplaceInit();
                TreeSet<EquationEntry> nextEquations = new TreeSet<EquationEntry>();
                for (EquationEntry e : v.equations) {
                    e.condition = e.condition.transform(replaceInit).simplify(v, false);
                    e.ifString = e.condition.render();
                    if (e.condition.isScalar()) {
                        // but only one will remain after adding to nextEquations.
                        if (// Will always fire.
                        e.condition.getDouble() != 0) {
                            e.condition = null;
                            e.ifString = "";
                            nextEquations.add(e);
                        }
                    } else {
                        nextEquations.add(e);
                    }
                }
                v.equations = nextEquations;
            }
        }
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) Transformer(gov.sandia.n2a.language.Transformer) AccessVariable(gov.sandia.n2a.language.AccessVariable) Constant(gov.sandia.n2a.language.Constant) TreeSet(java.util.TreeSet)

Example 63 with Operator

use of gov.sandia.n2a.language.Operator in project n2a by frothga.

the class EquationSet method findExternal.

/**
 *        Marks variables with "externalRead" and "externalWrite", as needed.
 *        Determines whether an external write should be evaluated in the local or global context.
 *        Depends on results of:
 *            resolveLHS(), resolveRHS() -- Establishes references and dependencies between variables.
 *            flatten() -- Changes references and dependencies. In some cases, folds expressions together so dependencies go away.
 */
public void findExternal() {
    for (EquationSet p : parts) p.findExternal();
    class Externalizer implements Visitor {

        Variable v;

        boolean allGlobal;

        public boolean visit(Operator op) {
            if (op instanceof AccessVariable) {
                AccessVariable av = (AccessVariable) op;
                Variable target = av.reference.variable;
                if (// v references something other than itself, which implies that the target is outside this equation set.
                target.container != v.container) {
                    target.addAttribute("externalRead");
                    target.removeAttribute("temporary");
                }
                if (!target.hasAny("global", "constant"))
                    allGlobal = false;
            }
            return true;
        }
    }
    Externalizer externalizer = new Externalizer();
    for (Variable v : variables) {
        externalizer.v = v;
        externalizer.allGlobal = true;
        v.visit(externalizer);
        // for convenience
        Variable vr = v.reference.variable;
        if (vr != v) {
            v.addAttribute("reference");
            vr.addAttribute("externalWrite");
            vr.removeAttribute("temporary");
            if (externalizer.allGlobal && !v.hasAttribute("local") && vr.hasAttribute("global")) {
                v.addAttribute("global");
                v.convertToGlobal();
            }
        }
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) AccessVariable(gov.sandia.n2a.language.AccessVariable) Visitor(gov.sandia.n2a.language.Visitor)

Example 64 with Operator

use of gov.sandia.n2a.language.Operator in project n2a by frothga.

the class EquationSet method determinePoll.

/**
 *        Checks if connection requires polling.
 *        The result is a metadata tag on $p. If the tag exists, polling is required and the tag gives the time period
 *        (0 for every cycle, >0 for quantity of time to complete one poll).
 *        The user can specify this tag ahead of time. Specifying -1 will suppress polling even if it is required.
 *        Specifying poll >= 0 will not force polling if it is not required. Instead, the tag will be cleared by this function.
 *        Depends on results of: findInitOnly()
 *        Must be run before purgeInitOnlyTemporary(), because that function removes information critical for our processing.
 *        findConnectionMatrix() will clear the metadata tag if it succeeds, because that kind of connection is a one-time process,
 *        no need for polling.
 */
public void determinePoll() {
    for (EquationSet s : parts) s.determinePoll();
    if (connectionBindings == null)
        return;
    Variable p = find(new Variable("$p"));
    if (p == null)
        return;
    // Look up metadata to determine polling period.
    // Default is full poll every cycle. After determinePoll() finishes, the default will be no polling. This simplifies later processing.
    String pollString = p.metadata.getOrDefault("0", "poll");
    double pollValue = new UnitValue(pollString).get();
    if (// Don't do analysis if polling is suppressed in any case.
    pollValue < 0) {
        p.metadata.clear("poll");
        return;
    }
    List<EquationEntry> fires = new ArrayList<EquationEntry>();
    // All equations in "fires" return 0 or 1.
    boolean firesBoolean = true;
    ReplacePhaseIndicators replacePhase = new ReplacePhaseIndicators();
    // And other indicators are 0
    replacePhase.connect = 1;
    for (EquationEntry e : p.equations) {
        // Assume a condition always fires, unless we can prove it does not.
        boolean couldFire = true;
        boolean alwaysFires = true;
        if (e.condition != null) {
            Operator test = e.condition.deepCopy().transform(replacePhase).simplify(p, true);
            if (test.isScalar())
                couldFire = alwaysFires = test.getDouble() != 0;
            else
                alwaysFires = false;
        }
        if (couldFire) {
            fires.add(e);
            Operator expression = e.expression.deepCopy().transform(replacePhase).simplify(p, true);
            if (expression.isScalar()) {
                double value = expression.getDouble();
                if (value != 0 && value != 1)
                    firesBoolean = false;
            } else {
                firesBoolean = false;
            }
        }
        if (alwaysFires)
            break;
    }
    if (// $p has default value (1 at connect)
    fires.isEmpty()) {
        p.metadata.clear("poll");
        return;
    }
    boolean needsPoll;
    if (fires.size() > 1) {
        // Multiple connect conditions means unpredictable, so needs polling.
        // The exception is if $p is initOnly and all equations are either 0 or 1.
        // In that case, polling is unneeded because the existence of the part is
        // already known at init time.
        System.out.println("fires " + fires.size() + " " + prefix());
        needsPoll = !p.hasAttribute("initOnly") || !firesBoolean;
    } else {
        // Determine if the single expression for $p requires polling.
        // The possibilities for NOT polling are:
        // * a Scalar that is either 1 or 0
        // * a boolean expression that depends on nothing more than initOnly variables
        // Everything else requires polling. For example:
        // * a Scalar in (0,1) -- requires random draw
        // * a boolean expression that can vary during regular updates
        EquationEntry e = fires.get(0);
        if (e.expression.isScalar()) {
            double value = e.expression.getDouble();
            needsPoll = value > 0 && value < 1;
        } else {
            // The default is to poll, unless we can prove that we don't need to.
            needsPoll = true;
            VisitInitOnly visitor = new VisitInitOnly();
            if (e.condition != null)
                e.condition.visit(visitor);
            if (visitor.isInitOnly)
                e.expression.visit(visitor);
            if (visitor.isInitOnly) {
                // We have an initOnly equation. Now determine if the result is in (0,1).
                // The only values we can be sure about are logical results, which are exactly 1 or 0, and therefore not in (0,1).
                needsPoll = !(e.expression instanceof OperatorLogical);
            }
        }
    }
    if (needsPoll) {
        // If poll is not otherwise specified, then do full poll at every cycle.
        if (p.metadata.child("poll") == null)
            p.metadata.set("0", "poll");
    } else {
        p.metadata.clear("poll");
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) ArrayList(java.util.ArrayList) UnitValue(gov.sandia.n2a.language.UnitValue) OperatorLogical(gov.sandia.n2a.language.OperatorLogical)

Example 65 with Operator

use of gov.sandia.n2a.language.Operator in project n2a by frothga.

the class EquationSet method findInitOnlyRecursive.

public boolean findInitOnlyRecursive() {
    boolean changed = false;
    for (EquationSet s : parts) {
        if (s.findInitOnlyRecursive())
            changed = true;
    }
    ReplacePhaseIndicators replacePhase = new ReplacePhaseIndicators();
    VisitInitOnly visitor = new VisitInitOnly();
    for (final Variable v : variables) {
        // unless it can be established that the value does not change after the init cycle of the target.
        if (v.hasAny("initOnly", "constant", "dummy", "externalWrite", "reference"))
            continue;
        // Count equations
        int firesDuringInit = 0;
        int firesDuringUpdate = 0;
        // If we have a single update equation, then we may still be initOnly if it depends only on constants or other initOnly variables. Save the update equation for analysis.
        EquationEntry update = null;
        EquationEntry init = null;
        for (EquationEntry e : v.equations) {
            // unless we can be absolutely certain it will not.
            if (e.condition == null) {
                firesDuringInit++;
                firesDuringUpdate++;
                update = e;
                init = e;
            } else {
                // The following tests do simplification of the expression, rather than substitution
                // with a fake Instance. We don't really know the values of variables until runtime.
                // To be completely certain of an expression's value, it must reduce to a Scalar using only
                // values that we can know now (specifically, the state of the phase indicators).
                // init
                replacePhase.init = 1;
                Operator test = e.condition.deepCopy().transform(replacePhase).simplify(v, true);
                if (!test.isScalar() || test.getDouble() != 0) {
                    firesDuringInit++;
                    init = e;
                }
                // update
                replacePhase.init = 0;
                test = e.condition.deepCopy().transform(replacePhase).simplify(v, true);
                if (!test.isScalar() || test.getDouble() != 0) {
                    firesDuringUpdate++;
                    update = e;
                }
            }
        }
        // Used in the last case below.
        int count = v.equations.size();
        if (firesDuringUpdate == 0) {
            if (firesDuringInit > 0 && v.derivative == null) {
                v.addAttribute("initOnly");
                changed = true;
            }
        } else if (// last chance to be "initOnly": must be exactly one equation that is not a combining operator
        firesDuringUpdate == 1 && firesDuringInit == 1 && update == init && v.assignment == Variable.REPLACE) {
            // Determine if our single update equation depends only on constants and initOnly variables
            visitor.isInitOnly = true;
            if (update.condition != null)
                update.condition.visit(visitor);
            if (visitor.isInitOnly)
                update.expression.visit(visitor);
            if (visitor.isInitOnly) {
                v.addAttribute("initOnly");
                changed = true;
            }
        } else if (count > 0 && firesDuringInit == count && firesDuringUpdate == count) {
            visitor.isInitOnly = true;
            for (EquationEntry e : v.equations) e.visit(visitor);
            if (visitor.isInitOnly) {
                v.addAttribute("initOnly");
                changed = true;
            }
        }
        if (firesDuringUpdate > 0 && v.derivative != null && !v.hasAttribute("initOnly"))
            v.addAttribute("updates");
        else
            v.removeAttribute("updates");
    }
    return changed;
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable)

Aggregations

Operator (gov.sandia.n2a.language.Operator)104 AccessVariable (gov.sandia.n2a.language.AccessVariable)41 Constant (gov.sandia.n2a.language.Constant)37 Visitor (gov.sandia.n2a.language.Visitor)26 Variable (gov.sandia.n2a.eqset.Variable)17 ArrayList (java.util.ArrayList)16 Type (gov.sandia.n2a.language.Type)14 Scalar (gov.sandia.n2a.language.type.Scalar)14 Output (gov.sandia.n2a.language.function.Output)13 EquationSet (gov.sandia.n2a.eqset.EquationSet)12 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)10 Input (gov.sandia.n2a.language.function.Input)10 Text (gov.sandia.n2a.language.type.Text)10 Matrix (gov.sandia.n2a.language.type.Matrix)9 TreeSet (java.util.TreeSet)9 ReadMatrix (gov.sandia.n2a.language.function.ReadMatrix)8 Add (gov.sandia.n2a.language.operator.Add)8 BuildMatrix (gov.sandia.n2a.language.BuildMatrix)7 Event (gov.sandia.n2a.language.function.Event)7 Instance (gov.sandia.n2a.language.type.Instance)7