Search in sources :

Example 11 with VariableReference

use of gov.sandia.n2a.eqset.VariableReference in project n2a by frothga.

the class SymbolStateVar1 method getDefinition.

@Override
public String getDefinition(XyceRenderer renderer) {
    String translatedEq = renderer.change(eq.expression);
    Variable v = eq.variable;
    VariableReference r = v.reference;
    if (// symbol is defined here; no += allowed within same part
    r.index < 0) {
        return Xyceisms.defineDiffEq(v.name, renderer.pi.hashCode(), translatedEq);
    }
    // This symbol refers to a symbol in another part. We don't re-define the
    // variable, rather we create another diff eq that updates the existing one.
    Instance target = (Instance) renderer.pi.valuesObject[r.index];
    String thisVarname = r.variable.name + "_" + target.hashCode();
    String eqName = v.name + "_" + renderer.pi.hashCode();
    return Xyceisms.updateDiffEq(eqName, thisVarname, translatedEq);
}
Also used : Variable(gov.sandia.n2a.eqset.Variable) VariableReference(gov.sandia.n2a.eqset.VariableReference) Instance(gov.sandia.n2a.language.type.Instance)

Example 12 with VariableReference

use of gov.sandia.n2a.eqset.VariableReference in project n2a by frothga.

the class InternalBackendData method analyzeEvents.

public static void analyzeEvents(EquationSet s, List<EventTarget> eventTargets, List<Variable> eventReferences, List<Delay> delays) {
    class EventVisitor implements Visitor {

        public boolean found;

        public boolean visit(Operator op) {
            if (op instanceof Delay) {
                delays.add((Delay) op);
            } else if (op instanceof Event) {
                found = true;
                Event de = (Event) op;
                if (// this event has not yet been analyzed
                de.eventType == null) {
                    final EventTarget et = new EventTarget(de);
                    int targetIndex = eventTargets.indexOf(et);
                    if (// event target already exists
                    targetIndex >= 0) {
                        de.eventType = eventTargets.get(targetIndex);
                    } else // we must create a new event target, or more properly, fill in the event target we just used as a query object
                    {
                        // Create an entry and save the index
                        targetIndex = eventTargets.size();
                        eventTargets.add(et);
                        de.eventType = et;
                        et.container = s;
                        // Determine edge type
                        if (de.operands.length < 3) {
                            et.edge = EventTarget.RISE;
                        } else if (de.operands[2] instanceof Constant) {
                            Constant c = (Constant) de.operands[2];
                            if (c.value instanceof Text) {
                                Text t = (Text) c.value;
                                if (t.value.equalsIgnoreCase("nonzero"))
                                    et.edge = EventTarget.NONZERO;
                                else if (t.value.equalsIgnoreCase("change"))
                                    et.edge = EventTarget.CHANGE;
                                else if (t.value.equalsIgnoreCase("fall"))
                                    et.edge = EventTarget.FALL;
                                else
                                    et.edge = EventTarget.RISE;
                            } else {
                                Backend.err.get().println("ERROR: event() edge type must be a string.");
                                throw new Backend.AbortRun();
                            }
                        } else {
                            Backend.err.get().println("ERROR: event() edge type must be constant.");
                            throw new Backend.AbortRun();
                        }
                        // Allocate auxiliary variable
                        if (de.operands[0] instanceof AccessVariable) {
                            AccessVariable av = (AccessVariable) de.operands[0];
                            VariableReference reference = av.reference;
                            Variable v = reference.variable;
                            // then the user has broken the rule that we can't see temporaries in other parts.
                            if (v.hasAttribute("temporary") && v.container != s) {
                                Backend.err.get().println("WARNING: Cannot be temporary due to event monitor: " + v.fullName() + " from " + s.name);
                                v.removeAttribute("temporary");
                            }
                            // so fall through to the !trackOne case below.
                            if (!v.hasAttribute("temporary")) {
                                // ensure it's buffered, so we can detect change
                                v.addAttribute("externalRead");
                                et.trackOne = true;
                                // just a holder for the reference
                                et.track = new Variable("");
                                et.track.reference = reference;
                            }
                        }
                        if (// Expression, so create auxiliary variable. Aux not needed for NONZERO, because no change detection.
                        !et.trackOne && et.edge != EventTarget.NONZERO) {
                            et.track = new Variable("$eventAux" + targetIndex);
                            et.track.container = s;
                            et.track.type = new Scalar(0);
                            et.track.reference = new VariableReference();
                            et.track.reference.variable = et.track;
                            // Make executable so it can be directly evaluated during the init cycle.
                            et.track.equations = new TreeSet<EquationEntry>();
                            EquationEntry ee = new EquationEntry(et.track, "");
                            et.track.equations.add(ee);
                            ee.expression = et.event.operands[0].deepCopy();
                            ee.expression.addDependencies(et.track);
                        }
                        // Locate any temporaries for evaluation.
                        // Tie into the dependency graph using a phantom variable (which can go away afterward without damaging the graph).
                        // TODO: for more efficiency, we could have separate lists of temporaries for the condition and delay operands
                        // TODO: for more efficiency, cut off search for temporaries along a given branch of the tree at the first non-temporary.
                        final Variable phantom = new Variable("event");
                        phantom.uses = new IdentityHashMap<Variable, Integer>();
                        phantom.container = s;
                        et.event.visit(new Visitor() {

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    Variable v = av.reference.variable;
                                    if (v.hasAttribute("temporary") && !phantom.uses.containsKey(v))
                                        phantom.uses.put(v, 1);
                                    return false;
                                }
                                return true;
                            }
                        });
                        // Scan all variables in equation set to see if we need them
                        for (Variable t : s.ordered) {
                            if (t.hasAttribute("temporary") && phantom.dependsOn(t) != null)
                                et.dependencies.add(t);
                        }
                        // Note the default is already set to -1 (no care)
                        class DelayVisitor implements Visitor {

                            TreeSet<EquationSet> containers = new TreeSet<EquationSet>();

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    // could include the target part itself, if in fact we use local variables
                                    containers.add(av.reference.variable.container);
                                    return false;
                                }
                                return true;
                            }
                        }
                        DelayVisitor dv = new DelayVisitor();
                        if (de.operands.length >= 2) {
                            if (de.operands[1] instanceof Constant) {
                                Constant c = (Constant) de.operands[1];
                                et.delay = (float) ((Scalar) c.value).value;
                                if (et.delay < 0)
                                    et.delay = -1;
                            } else {
                                // indicates that we need to evaluate delay at run time
                                et.delay = -2;
                                de.operands[1].visit(dv);
                            }
                        }
                        // Set up monitors in source parts
                        class ConditionVisitor implements Visitor {

                            TreeSet<EquationSet> containers = new TreeSet<EquationSet>();

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    Variable v = av.reference.variable;
                                    EquationSet sourceContainer = v.container;
                                    containers.add(sourceContainer);
                                    // Set up monitors for values that can vary during update.
                                    if (!v.hasAttribute("constant") && !v.hasAttribute("initOnly") && !et.monitors(sourceContainer)) {
                                        EventSource es = new EventSource(sourceContainer, et);
                                        // null means self-reference, a special case handled in Part
                                        if (sourceContainer != s)
                                            es.reference = av.reference;
                                        et.sources.add(es);
                                    }
                                    return false;
                                }
                                return true;
                            }
                        }
                        ConditionVisitor cv = new ConditionVisitor();
                        de.operands[0].visit(cv);
                        // Special case for event with no references that vary
                        if (et.sources.isEmpty()) {
                            // We can avoid creating a self monitor if we know for certain that the event will never fire
                            boolean neverFires = false;
                            if (de.operands[0] instanceof Constant) {
                                if (et.edge == EventTarget.NONZERO) {
                                    Type op0 = ((Constant) de.operands[0]).value;
                                    if (op0 instanceof Scalar) {
                                        neverFires = ((Scalar) op0).value == 0;
                                    } else {
                                        Backend.err.get().println("ERROR: Condition for event() must resolve to a number.");
                                        throw new Backend.AbortRun();
                                    }
                                } else {
                                    neverFires = true;
                                }
                            }
                            if (!neverFires) {
                                EventSource es = new EventSource(s, et);
                                // This is a self-reference, so es.reference should be null.
                                et.sources.add(es);
                            }
                        }
                        // Determine if monitor needs to test every target, or if one representative target is sufficient
                        for (EventSource source : et.sources) {
                            // associated with any given source instance, so every target must be evaluated separately.
                            if (cv.containers.size() > 1)
                                source.testEach = true;
                            if (dv.containers.size() > 1 || (dv.containers.size() == 1 && dv.containers.first() != source.container))
                                source.delayEach = true;
                        }
                    }
                }
            }
            return true;
        }
    }
    EventVisitor eventVisitor = new EventVisitor();
    for (Variable v : s.variables) {
        eventVisitor.found = false;
        v.visit(eventVisitor);
        if ((eventVisitor.found || v.dependsOnEvent()) && v.reference.variable != v)
            eventReferences.add(v);
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) EquationSet(gov.sandia.n2a.eqset.EquationSet) AccessVariable(gov.sandia.n2a.language.AccessVariable) Variable(gov.sandia.n2a.eqset.Variable) AccessVariable(gov.sandia.n2a.language.AccessVariable) VariableReference(gov.sandia.n2a.eqset.VariableReference) Visitor(gov.sandia.n2a.language.Visitor) Constant(gov.sandia.n2a.language.Constant) IdentityHashMap(java.util.IdentityHashMap) Text(gov.sandia.n2a.language.type.Text) Delay(gov.sandia.n2a.language.function.Delay) Scalar(gov.sandia.n2a.language.type.Scalar) Type(gov.sandia.n2a.language.Type) Backend(gov.sandia.n2a.plugins.extpoints.Backend) TreeSet(java.util.TreeSet) Event(gov.sandia.n2a.language.function.Event) EquationEntry(gov.sandia.n2a.eqset.EquationEntry)

Example 13 with VariableReference

use of gov.sandia.n2a.eqset.VariableReference in project n2a by frothga.

the class SumSquares method determineExponent.

public void determineExponent(ExponentContext context) {
    // This function is related to both Norm and Power. See those classes for similar processing.
    // A
    Operator op0 = operands[0];
    op0.determineExponent(context);
    // Determine number of elements in A
    Instance instance = new Instance() {

        // all AccessVariable objects will reach here first, and get back the Variable.type field
        public Type get(VariableReference r) throws EvaluationException {
            return r.variable.type;
        }
    };
    Matrix A = (Matrix) op0.eval(instance);
    int Asize = A.rows() * A.columns();
    if (op0.exponent != UNKNOWN) {
        // log2(Asize)
        int shift = (int) Math.floor(Math.log(Asize) / Math.log(2));
        int centerNew = MSB / 2;
        int exponentNew = op0.centerPower() * 2 + shift + MSB - centerNew;
        updateExponent(context, exponentNew, centerNew);
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) Matrix(gov.sandia.n2a.language.type.Matrix) VariableReference(gov.sandia.n2a.eqset.VariableReference) Instance(gov.sandia.n2a.language.type.Instance)

Example 14 with VariableReference

use of gov.sandia.n2a.eqset.VariableReference in project n2a by frothga.

the class Instance method resolve.

public void resolve(TreeSet<VariableReference> references) {
    for (VariableReference r : references) {
        Instance result = this;
        Object last = r.resolution.get(r.resolution.size() - 1);
        for (Object o : r.resolution) {
            result = ((Resolver) o).resolve(result);
            if (// Resolution is done and this is a global variable.
            o == last && r.variable.global) {
                if (result instanceof Part) {
                    // Need to locate our population.
                    InternalBackendData bed = (InternalBackendData) result.equations.backendData;
                    result = (Instance) result.container.valuesObject[bed.populationIndex];
                }
            } else {
                if (result instanceof Population) {
                    // Need to drill down to an instance of the population.
                    // This is only possible with a singleton.
                    InternalBackendData bed = (InternalBackendData) result.equations.backendData;
                    if (!bed.singleton) {
                        Backend.err.get().println("ERROR: Ambiguous reference to " + result.equations.prefix());
                        throw new Backend.AbortRun();
                    }
                    result = (Instance) result.valuesObject[bed.instances];
                }
            }
        }
        valuesObject[r.index] = result;
    }
}
Also used : VariableReference(gov.sandia.n2a.eqset.VariableReference) Part(gov.sandia.n2a.backend.internal.Part) Population(gov.sandia.n2a.backend.internal.Population) InternalBackendData(gov.sandia.n2a.backend.internal.InternalBackendData)

Aggregations

VariableReference (gov.sandia.n2a.eqset.VariableReference)14 Variable (gov.sandia.n2a.eqset.Variable)9 AccessVariable (gov.sandia.n2a.language.AccessVariable)9 EquationSet (gov.sandia.n2a.eqset.EquationSet)7 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)6 Operator (gov.sandia.n2a.language.Operator)6 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)5 Scalar (gov.sandia.n2a.language.type.Scalar)5 TreeSet (java.util.TreeSet)5 Constant (gov.sandia.n2a.language.Constant)3 Visitor (gov.sandia.n2a.language.Visitor)3 Instance (gov.sandia.n2a.language.type.Instance)3 EventSource (gov.sandia.n2a.backend.internal.InternalBackendData.EventSource)2 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)2 Conversion (gov.sandia.n2a.eqset.EquationSet.Conversion)2 UnresolvedVariable (gov.sandia.n2a.eqset.EquationSet.UnresolvedVariable)2 Type (gov.sandia.n2a.language.Type)2 Event (gov.sandia.n2a.language.function.Event)2 Output (gov.sandia.n2a.language.function.Output)2 Matrix (gov.sandia.n2a.language.type.Matrix)2