Search in sources :

Example 6 with Scalar

use of gov.sandia.n2a.language.type.Scalar in project n2a by frothga.

the class InternalBackendData method analyze.

public void analyze(final EquationSet s) {
    System.out.println(s.name);
    if (s.connectionBindings != null) {
        // Note that populations have already been allocated in the constructor.
        endpoints = countLocalObject;
        countLocalObject += s.connectionBindings.size();
    }
    for (// we want the sub-lists to be ordered correctly
    Variable v : // we want the sub-lists to be ordered correctly
    s.ordered) {
        String className = "null";
        if (v.type != null)
            className = v.type.getClass().getSimpleName();
        System.out.println("  " + v.nameString() + " " + v.attributeString() + " " + className);
        if (v.name.equals("$index"))
            index = v;
        else if (v.name.equals("$init"))
            init = v;
        else if (v.name.equals("$live"))
            live = v;
        else if (v.name.equals("$n") && v.order == 0)
            n = v;
        else if (v.name.equals("$p") && v.order == 0)
            p = v;
        else if (v.name.equals("$type"))
            type = v;
        else if (v.name.equals("$xyz") && v.order == 0)
            xyz = v;
        else if (v.name.equals("$t")) {
            if (v.order == 0)
                t = v;
            else if (v.order == 1)
                dt = v;
        }
        if (v.hasAttribute("global")) {
            v.global = true;
            v.visit(new Visitor() {

                public boolean visit(Operator op) {
                    if (op instanceof AccessVariable) {
                        AccessVariable av = (AccessVariable) op;
                        if (av.reference.resolution.size() > 0)
                            addReferenceGlobal(av.reference, s);
                        return false;
                    }
                    if (op instanceof Output) {
                        Output o = (Output) op;
                        if (o.operands.length < 3) {
                            o.index = countGlobalObject++;
                            namesGlobalObject.add("columnName" + o.index);
                        }
                        // Continue descent, because parameters of output() may contain variable references
                        return true;
                    }
                    return true;
                }
            });
            if (// eliminate non-computed values, unless they refer to a variable outside the immediate equation set
            !v.hasAny(new String[] { "constant", "accessor", "readOnly" }) || v.hasAll(new String[] { "constant", "reference" })) {
                boolean initOnly = v.hasAttribute("initOnly");
                boolean updates = !initOnly && v.equations.size() > 0 && (v.derivative == null || v.hasAttribute("updates"));
                if (updates)
                    globalUpdate.add(v);
                if (v.hasAttribute("reference")) {
                    addReferenceGlobal(v.reference, s);
                } else {
                    boolean temporary = v.hasAttribute("temporary");
                    if (!temporary || v.hasUsers())
                        globalInit.add(v);
                    if (!temporary && !v.hasAttribute("dummy")) {
                        if (!v.hasAttribute("preexistent"))
                            globalMembers.add(v);
                        boolean external = false;
                        if (v.hasAttribute("externalWrite") || v.assignment != Variable.REPLACE) {
                            external = true;
                            globalBufferedExternalWrite.add(v);
                        }
                        if (external || (v.hasAttribute("externalRead") && updates)) {
                            external = true;
                            globalBufferedExternal.add(v);
                        }
                        if (external || v.hasAttribute("cycle")) {
                            globalBuffered.add(v);
                            if (!external) {
                                globalBufferedInternal.add(v);
                                if (!initOnly)
                                    globalBufferedInternalUpdate.add(v);
                            }
                        }
                    }
                }
            }
        } else // local
        {
            v.visit(new Visitor() {

                public boolean visit(Operator op) {
                    if (op instanceof AccessVariable) {
                        AccessVariable av = (AccessVariable) op;
                        if (av.reference.resolution.size() > 0)
                            addReferenceLocal(av.reference, s);
                        return false;
                    }
                    if (op instanceof Output) {
                        Output o = (Output) op;
                        if (o.operands.length < 3) {
                            o.index = countLocalObject++;
                            namesLocalObject.add("columnName" + o.index);
                        }
                        // Continue descent, because parameters of output() may contain variable references
                        return true;
                    }
                    return true;
                }
            });
            if (!v.hasAny(new String[] { "constant", "accessor", "readOnly" }) || v.hasAll(new String[] { "constant", "reference" })) {
                boolean initOnly = v.hasAttribute("initOnly");
                boolean updates = !initOnly && v.equations.size() > 0 && (v.derivative == null || v.hasAttribute("updates"));
                if (updates)
                    localUpdate.add(v);
                if (v.hasAttribute("reference")) {
                    addReferenceLocal(v.reference, s);
                } else {
                    boolean temporary = v.hasAttribute("temporary");
                    if (!temporary || v.hasUsers()) {
                        if (v.name.startsWith("$") || (temporary && v.neededBySpecial())) {
                            if (!v.name.equals("$index") && !v.name.equals("$live"))
                                localInitSpecial.add(v);
                        } else {
                            localInitRegular.add(v);
                        }
                    }
                    if (!temporary && !v.hasAttribute("dummy")) {
                        if (!v.hasAttribute("preexistent"))
                            localMembers.add(v);
                        boolean external = false;
                        if (v.hasAttribute("externalWrite") || v.assignment != Variable.REPLACE) {
                            external = true;
                            localBufferedExternalWrite.add(v);
                        }
                        if (external || (v.hasAttribute("externalRead") && updates)) {
                            external = true;
                            localBufferedExternal.add(v);
                        }
                        if (external || v.hasAttribute("cycle")) {
                            if (v.name.startsWith("$"))
                                localBufferedSpecial.add(v);
                            else
                                localBufferedRegular.add(v);
                            if (// v got here only by being a "cycle", not "externalRead" or "externalWrite"
                            !external) {
                                localBufferedInternal.add(v);
                                if (!initOnly)
                                    localBufferedInternalUpdate.add(v);
                            }
                        }
                    }
                }
            }
        }
    }
    for (// we need these to be in order by differential level, not by dependency
    Variable v : // we need these to be in order by differential level, not by dependency
    s.variables) {
        if (v.derivative != null && !v.hasAny(new String[] { "constant", "initOnly" })) {
            if (v.hasAttribute("global"))
                globalIntegrated.add(v);
            else
                localIntegrated.add(v);
        }
    }
    populationCanGrowOrDie = s.lethalP || s.lethalType || s.canGrow();
    if (n != null) {
        populationCanResize = globalMembers.contains(n);
        // See EquationSet.forceTemporaryStorageForSpecials() for a related issue.
        if (!populationCanResize && populationCanGrowOrDie && n.hasUsers()) {
            Backend.err.get().println("WARNING: $n can change (due to structural dynamics) but it was detected as a constant. Equations that depend on $n may give incorrect results.");
        }
    }
    if (index != null) {
        indexNext = countGlobalFloat++;
        namesGlobalFloat.add("indexNext");
        indexAvailable = countGlobalObject++;
        namesGlobalObject.add("indexAvailable");
    }
    if (// track instances
    s.connected || s.needInstanceTracking || populationCanResize) {
        // The reason populationCanResize forces use of the instances array is to enable pruning of parts when $n decreases.
        instances = countGlobalObject++;
        namesGlobalObject.add("instances");
        if (// in addition, track newly created instances
        s.connected) {
            firstborn = countGlobalFloat++;
            namesGlobalFloat.add("firstborn");
            newborn = countLocalFloat++;
            namesLocalFloat.add("newborn");
        }
    }
    if (p != null) {
        Pdependencies = new ArrayList<Variable>();
        for (Variable t : s.ordered) {
            if (t.hasAttribute("temporary") && p.dependsOn(t) != null) {
                Pdependencies.add(t);
            }
        }
    }
    populationIndex = 0;
    if (// check for null specifically to guard against the Wrapper equation set (which is not fully constructed)
    s.container != null && s.container.parts != null) {
        for (EquationSet p : s.container.parts) {
            if (p == s)
                break;
            populationIndex++;
        }
    }
    if (// connection-specific stuff
    s.connectionBindings != null) {
        int size = s.connectionBindings.size();
        // endpoints is allocated at the top of this function, because it is needed for reference handling in the variable analysis loop
        projectDependencies = new Object[size];
        projectReferences = new Object[size];
        count = new int[size];
        k = new Variable[size];
        max = new Variable[size];
        min = new Variable[size];
        project = new Variable[size];
        radius = new Variable[size];
        for (int i = 0; i < s.connectionBindings.size(); i++) {
            ConnectionBinding c = s.connectionBindings.get(i);
            count[i] = -1;
            k[i] = s.find(new Variable(c.alias + ".$k"));
            max[i] = s.find(new Variable(c.alias + ".$max"));
            min[i] = s.find(new Variable(c.alias + ".$min"));
            project[i] = s.find(new Variable(c.alias + ".$project"));
            radius[i] = s.find(new Variable(c.alias + ".$radius"));
            if (c.endpoint.accountableConnections != null) {
                AccountableConnection query = new AccountableConnection(s, c.alias);
                AccountableConnection ac = c.endpoint.accountableConnections.floor(query);
                if (// Only true if this endpoint is accountable.
                ac.equals(query)) {
                    // Allocate space for counter in target part
                    InternalBackendData endpointBed = (InternalBackendData) c.endpoint.backendData;
                    count[i] = endpointBed.countLocalFloat++;
                    endpointBed.namesLocalFloat.add(s.prefix() + ".$count");
                    if (// $count is referenced explicitly, so need to finish setting it up
                    ac.count != null) {
                        ac.count.readIndex = ac.count.writeIndex = count[i];
                    }
                }
            }
            // Note that countLocalObject has already been incremented above
            namesLocalObject.add(c.alias);
            if (project[i] != null) {
                ArrayList<Variable> dependencies = new ArrayList<Variable>();
                // Always assign, even if empty.
                projectDependencies[i] = dependencies;
                for (Variable t : s.ordered) {
                    if (t.hasAttribute("temporary") && project[i].dependsOn(t) != null) {
                        dependencies.add(t);
                    }
                }
                final TreeSet<VariableReference> references = new TreeSet<VariableReference>(referenceComparator);
                class ProjectVisitor extends Visitor {

                    public boolean visit(Operator op) {
                        if (op instanceof AccessVariable) {
                            AccessVariable av = (AccessVariable) op;
                            if (av.reference.resolution.size() > 0)
                                references.add(av.reference);
                            return false;
                        }
                        return true;
                    }
                }
                ProjectVisitor visitor = new ProjectVisitor();
                project[i].visit(visitor);
                for (Variable v : dependencies) v.visit(visitor);
                if (references.size() > 0)
                    projectReferences[i] = references;
            }
            c.resolution = translateResolution(c.resolution, s);
        }
    }
    // Locals
    for (Variable v : localMembers) {
        // in the type array rather than the float array.
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.readIndex = v.writeIndex = countLocalFloat++;
            namesLocalFloat.add(v.nameString());
        } else {
            v.readIndex = v.writeIndex = countLocalObject++;
            namesLocalObject.add(v.nameString());
        }
    }
    for (Variable v : localBufferedExternal) {
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = countLocalFloat++;
            namesLocalFloat.add("next_" + v.nameString());
        } else {
            v.writeIndex = countLocalObject++;
            namesLocalObject.add("next_" + v.nameString());
        }
    }
    for (Variable v : localBufferedInternal) {
        v.writeTemp = true;
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = countLocalTempFloat++;
            namesLocalTempFloat.add("next_" + v.nameString());
        } else {
            v.writeIndex = countLocalTempObject++;
            namesLocalTempObject.add("next_" + v.nameString());
        }
    }
    // Globals
    for (Variable v : globalMembers) {
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.readIndex = v.writeIndex = countGlobalFloat++;
            namesGlobalFloat.add(v.nameString());
        } else {
            v.readIndex = v.writeIndex = countGlobalObject++;
            namesGlobalObject.add(v.nameString());
        }
    }
    for (Variable v : globalBufferedExternal) {
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = countGlobalFloat++;
            namesGlobalFloat.add("next_" + v.nameString());
        } else {
            v.writeIndex = countGlobalObject++;
            namesGlobalObject.add("next_" + v.nameString());
        }
    }
    for (Variable v : globalBufferedInternal) {
        v.writeTemp = true;
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = countGlobalTempFloat++;
            namesGlobalTempFloat.add("next_" + v.nameString());
        } else {
            v.writeIndex = countGlobalTempObject++;
            namesGlobalTempObject.add("next_" + v.nameString());
        }
    }
    // fully temporary values
    for (Variable v : s.variables) {
        if (!v.hasAttribute("temporary"))
            continue;
        v.readTemp = v.writeTemp = true;
        if (v.hasAttribute("global")) {
            if (v.type instanceof Scalar && v.reference.variable == v) {
                v.readIndex = v.writeIndex = countGlobalTempFloat++;
                namesGlobalTempFloat.add(v.nameString());
            } else {
                v.readIndex = v.writeIndex = countGlobalTempObject++;
                namesGlobalTempObject.add(v.nameString());
            }
        } else {
            if (v.type instanceof Scalar && v.reference.variable == v) {
                v.readIndex = v.writeIndex = countLocalTempFloat++;
                namesLocalTempFloat.add(v.nameString());
            } else {
                v.readIndex = v.writeIndex = countLocalTempObject++;
                namesLocalTempObject.add(v.nameString());
            }
        }
    }
    if (live.hasAttribute("constant"))
        liveStorage = LIVE_CONSTANT;
    else if (live.hasAttribute("accessor"))
        liveStorage = LIVE_ACCESSOR;
    else
        // $live is "initOnly"
        liveStorage = LIVE_STORED;
    for (VariableReference r : localReference) r.resolution = translateResolution(r.resolution, s);
    for (VariableReference r : globalReference) r.resolution = translateResolution(r.resolution, s);
    // Type conversions
    String[] forbiddenAttributes = new String[] { "global", "constant", "accessor", "reference", "temporary", "dummy", "preexistent" };
    for (EquationSet target : s.getConversionTargets()) {
        if (s.connectionBindings == null) {
            if (target.connectionBindings != null)
                throw new EvaluationException("Can't change $type from compartment to connection.");
        } else {
            if (target.connectionBindings == null)
                throw new EvaluationException("Can't change $type from connection to compartment.");
        }
        Conversion conversion = new Conversion();
        conversions.put(target, conversion);
        // Match variables
        for (Variable v : target.variables) {
            if (v.name.equals("$type"))
                continue;
            if (v.hasAny(forbiddenAttributes))
                continue;
            Variable v2 = s.find(v);
            if (v2 != null && v2.equals(v)) {
                conversion.to.add(v);
                conversion.from.add(v2);
            }
        }
        // Match connection bindings
        if (// Since we checked above, we know that target is also a connection.
        s.connectionBindings != null) {
            conversion.bindings = new int[s.connectionBindings.size()];
            int i = 0;
            for (ConnectionBinding c : s.connectionBindings) {
                conversion.bindings[i] = -1;
                int j = 0;
                for (ConnectionBinding d : target.connectionBindings) {
                    if (c.alias.equals(d.alias)) {
                        conversion.bindings[i] = j;
                        break;
                    }
                    j++;
                }
                // Note: ALL bindings must match. There is no other mechanism for initializing the endpoints.
                if (conversion.bindings[i] < 0)
                    throw new EvaluationException("Unfulfilled connection binding during $type change.");
                i++;
            }
        }
    // TODO: Match populations?
    // Currently, any contained populations do not carry over to new instance. Instead, it must create them from scratch.
    }
}
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) Visitor(gov.sandia.n2a.language.Visitor) AccessVariable(gov.sandia.n2a.language.AccessVariable) AccountableConnection(gov.sandia.n2a.eqset.EquationSet.AccountableConnection) VariableReference(gov.sandia.n2a.eqset.VariableReference) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) ArrayList(java.util.ArrayList) EvaluationException(gov.sandia.n2a.language.EvaluationException) Scalar(gov.sandia.n2a.language.type.Scalar) TreeSet(java.util.TreeSet) Output(gov.sandia.n2a.language.function.Output)

Example 7 with Scalar

use of gov.sandia.n2a.language.type.Scalar in project n2a by frothga.

the class InternalBackendData method analyzeLastT.

/**
 *        Determine if time of last integration must be stored.
 *        Note: global (population) variables are integrated at same time as container using its dt value.
 *        Thus, we only handle local variables here.
 */
public void analyzeLastT(EquationSet s) {
    boolean hasIntegrated = localIntegrated.size() > 0;
    for (EquationSet p : s.parts) {
        if (hasIntegrated)
            break;
        hasIntegrated = ((InternalBackendData) p.backendData).globalIntegrated.size() > 0;
    }
    boolean dtCanChange = dt != null && dt.equations.size() > 0 && !dt.hasAttribute("initOnly");
    if (hasIntegrated && (eventTargets.size() > 0 || dtCanChange)) {
        lastT = new Variable("$lastT");
        lastT.readIndex = lastT.writeIndex = countLocalFloat++;
        namesLocalFloat.add(lastT.nameString());
        lastT.type = new Scalar(0);
    }
}
Also used : EquationSet(gov.sandia.n2a.eqset.EquationSet) AccessVariable(gov.sandia.n2a.language.AccessVariable) Variable(gov.sandia.n2a.eqset.Variable) Scalar(gov.sandia.n2a.language.type.Scalar)

Example 8 with Scalar

use of gov.sandia.n2a.language.type.Scalar in project n2a by frothga.

the class InternalBackendData method analyzeEvents.

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

        public boolean found;

        public boolean visit(Operator op) {
            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.container.name + "." + v.nameString() + " 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, 0);
                            et.track.type = new Scalar(0);
                            et.track.reference = new VariableReference();
                            et.track.reference.variable = et.track;
                        }
                        // Locate any temporaries for evaluation. TODO: for more efficiency, we could have separate lists of temporaries for the condition and delay operands
                        // Tie into the dependency graph using a phantom variable (which can go away afterward without damaging the graph).
                        final Variable phantom = new Variable("event");
                        phantom.uses = new IdentityHashMap<Variable, Integer>();
                        for (int i = 0; i < et.event.operands.length; i++) et.event.operands[i].visit(new Visitor() {

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    Variable v = av.reference.variable;
                                    if (!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.variables) {
                            if (t.hasAttribute("temporary") && phantom.dependsOn(t) != null)
                                et.dependencies.add(t);
                        }
                        // Note the default is already set to -1 (no care)
                        class DelayVisitor extends 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 extends 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) AccessVariable(gov.sandia.n2a.language.AccessVariable) Variable(gov.sandia.n2a.eqset.Variable) Visitor(gov.sandia.n2a.language.Visitor) Constant(gov.sandia.n2a.language.Constant) Scalar(gov.sandia.n2a.language.type.Scalar) TreeSet(java.util.TreeSet) EquationSet(gov.sandia.n2a.eqset.EquationSet) AccessVariable(gov.sandia.n2a.language.AccessVariable) VariableReference(gov.sandia.n2a.eqset.VariableReference) Text(gov.sandia.n2a.language.type.Text) Backend(gov.sandia.n2a.plugins.extpoints.Backend) Type(gov.sandia.n2a.language.Type) Event(gov.sandia.n2a.language.function.Event)

Example 9 with Scalar

use of gov.sandia.n2a.language.type.Scalar in project n2a by frothga.

the class Part method finish.

public boolean finish(Simulator simulator) {
    InternalBackendData bed = (InternalBackendData) equations.backendData;
    int populations = equations.parts.size();
    for (int i = 0; i < populations; i++) ((Population) valuesObject[i]).finish(simulator);
    if (bed.liveStorage == InternalBackendData.LIVE_STORED) {
        // early-out if we are already dead, to avoid another call to die()
        if (((Scalar) get(bed.live)).value == 0)
            return false;
    }
    // Events
    for (EventSource es : bed.eventSources) {
        @SuppressWarnings("unchecked") List<Instance> monitors = (ArrayList<Instance>) valuesObject[es.monitorIndex];
        if (monitors.size() == 0)
            continue;
        EventTarget eventType = es.target;
        if (es.testEach) {
            for (Instance i : monitors) {
                if (i == null)
                    continue;
                double delay = eventType.test(i, simulator);
                // the trigger condition was not satisfied
                if (delay < -1)
                    continue;
                EventSpikeSingle spike;
                if (// event was triggered, but timing is no-care
                delay < 0) {
                    spike = new EventSpikeSingleLatch();
                    // queue immediately after current cycle, so latches get set for next full cycle
                    spike.t = simulator.currentEvent.t;
                } else if (// process as close to current cycle as possible
                delay == 0) {
                    // fully execute the event (not latch it)
                    spike = new EventSpikeSingle();
                    // queue immediately
                    spike.t = simulator.currentEvent.t;
                } else {
                    // Is delay an quantum number of $t' steps?
                    double ratio = delay / event.dt;
                    int step = (int) Math.round(ratio);
                    if (Math.abs(ratio - step) < 1e-3) {
                        if (simulator.eventMode == Simulator.DURING)
                            spike = new EventSpikeSingleLatch();
                        else
                            spike = new EventSpikeSingle();
                        if (simulator.eventMode == Simulator.AFTER)
                            delay = (step + 1e-6) * event.dt;
                        else
                            delay = (step - 1e-6) * event.dt;
                    } else {
                        spike = new EventSpikeSingle();
                    }
                    spike.t = simulator.currentEvent.t + delay;
                }
                spike.eventType = eventType;
                spike.target = i;
                simulator.queueEvent.add(spike);
            }
        } else // All monitors share same condition, so only test one.
        {
            double delay = -2;
            for (Instance i : monitors) {
                if (i == null)
                    continue;
                delay = eventType.test(i, simulator);
                break;
            }
            // the trigger condition was not satisfied
            if (delay < -1)
                continue;
            if (// Each target instance may require a different delay.
            es.delayEach) {
                for (Instance i : monitors) {
                    if (i == null)
                        continue;
                    // This results in one redundant eval, of first entry in monitors. Not clear if it's worth the work to avoid this.
                    delay = eventType.delay(i, simulator);
                    EventSpikeSingle spike;
                    if (delay < 0) {
                        spike = new EventSpikeSingleLatch();
                        spike.t = simulator.currentEvent.t;
                    } else if (delay == 0) {
                        spike = new EventSpikeSingle();
                        spike.t = simulator.currentEvent.t;
                    } else {
                        double ratio = delay / event.dt;
                        int step = (int) Math.round(ratio);
                        if (Math.abs(ratio - step) < 1e-3) {
                            if (simulator.eventMode == Simulator.DURING)
                                spike = new EventSpikeSingleLatch();
                            else
                                spike = new EventSpikeSingle();
                            if (simulator.eventMode == Simulator.AFTER)
                                delay = (step + 1e-6) * event.dt;
                            else
                                delay = (step - 1e-6) * event.dt;
                        } else {
                            spike = new EventSpikeSingle();
                        }
                        spike.t = simulator.currentEvent.t + delay;
                    }
                    spike.eventType = eventType;
                    spike.target = i;
                    simulator.queueEvent.add(spike);
                }
            } else // All delays are the same.
            {
                EventSpikeMulti spike;
                if (delay < 0) {
                    spike = new EventSpikeMultiLatch();
                    spike.t = simulator.currentEvent.t;
                } else if (delay == 0) {
                    spike = new EventSpikeMulti();
                    spike.t = simulator.currentEvent.t;
                } else {
                    double ratio = delay / event.dt;
                    int step = (int) Math.round(ratio);
                    if (Math.abs(ratio - step) < 1e-3) {
                        if (simulator.eventMode == Simulator.DURING)
                            spike = new EventSpikeMultiLatch();
                        else
                            spike = new EventSpikeMulti();
                        if (simulator.eventMode == Simulator.AFTER)
                            delay = (step + 1e-6) * event.dt;
                        else
                            delay = (step - 1e-6) * event.dt;
                    } else {
                        spike = new EventSpikeMulti();
                    }
                    spike.t = simulator.currentEvent.t + delay;
                }
                spike.eventType = eventType;
                // We don't copy the array, just keep a reference to it. What could go wrong with this?
                // If a part dies and tries to remove itself from the list while it is being used to deliver spikes,
                // then we could get a null pointer exception. Solution is to synchronize access to the list.
                // If a connection is born while the spike is in flight, one could argue that it shouldn't
                // receive it, but one could also argue that it should. In nature these two things (spikes
                // and synapse creation) occur at vastly different timescales. Wouldn't a nascent synapse
                // receive spikes even as it is forming?
                spike.targets = monitors;
                simulator.queueEvent.add(spike);
            }
        }
    }
    // Other stuff
    if (bed.lastT != null)
        setFinal(bed.lastT, new Scalar(simulator.currentEvent.t));
    for (Variable v : bed.localBufferedExternal) setFinal(v, getFinal(v));
    for (Integer i : bed.eventLatches) valuesFloat[i] = 0;
    for (Variable v : bed.localBufferedExternalWrite) {
        switch(v.assignment) {
            case Variable.ADD:
                // initial value is zero-equivalent (additive identity)
                set(v, v.type);
                break;
            case Variable.MULTIPLY:
            case Variable.DIVIDE:
                // multiplicative identity
                if (v.type instanceof Matrix)
                    set(v, ((Matrix) v.type).identity());
                else
                    set(v, new Scalar(1));
                break;
            case Variable.MIN:
                if (v.type instanceof Matrix)
                    set(v, ((Matrix) v.type).clear(Double.POSITIVE_INFINITY));
                else
                    set(v, new Scalar(Double.POSITIVE_INFINITY));
                break;
            case Variable.MAX:
                if (v.type instanceof Matrix)
                    set(v, ((Matrix) v.type).clear(Double.NEGATIVE_INFINITY));
                else
                    set(v, new Scalar(Double.NEGATIVE_INFINITY));
                break;
        }
    }
    if (bed.type != null) {
        int type = (int) ((Scalar) get(bed.type)).value;
        if (type > 0) {
            ArrayList<EquationSet> split = equations.splits.get(type - 1);
            if (// Make sure $type != me. Otherwise it's a null operation
            split.size() > 1 || split.get(0) != equations) {
                // indicates that this instance is one of the resulting parts
                boolean used = false;
                int countParts = split.size();
                for (int i = 0; i < countParts; i++) {
                    EquationSet other = split.get(i);
                    Scalar splitPosition = new Scalar(i + 1);
                    if (other == equations && !used) {
                        used = true;
                        setFinal(bed.type, splitPosition);
                    } else {
                        InternalBackendData otherBed = (InternalBackendData) other.backendData;
                        Part p = new Part(other, (Part) container);
                        // If this is a connection, keep the same bindings
                        Conversion conversion = bed.conversions.get(other);
                        if (conversion.bindings != null) {
                            for (int j = 0; j < conversion.bindings.length; j++) {
                                p.valuesObject[otherBed.endpoints + conversion.bindings[j]] = valuesObject[bed.endpoints + j];
                            }
                        }
                        event.enqueue(p);
                        p.resolve();
                        // accountable connections are updated here
                        p.init(simulator);
                        // Copy over variables
                        int count = conversion.from.size();
                        for (int v = 0; v < count; v++) {
                            Variable from = conversion.from.get(v);
                            Variable to = conversion.to.get(v);
                            p.setFinal(to, get(from));
                        }
                        // Set $type to be our position in the split
                        p.setFinal(otherBed.type, splitPosition);
                    }
                }
                if (!used) {
                    die();
                    return false;
                }
            }
        }
    }
    if (equations.lethalP) {
        double p;
        if (bed.p.hasAttribute("temporary")) {
            InstanceTemporaries temp = new InstanceTemporaries(this, simulator, false);
            for (Variable v : bed.Pdependencies) {
                Type result = v.eval(temp);
                if (result != null && v.writeIndex >= 0)
                    temp.set(v, result);
            }
            Type result = bed.p.eval(temp);
            if (result == null)
                p = 1;
            else
                p = ((Scalar) result).value;
        } else {
            p = ((Scalar) get(bed.p)).value;
        }
        if (p == 0 || p < 1 && p < simulator.random.nextDouble()) {
            die();
            return false;
        }
    }
    if (equations.lethalConnection) {
        int count = equations.connectionBindings.size();
        for (int i = 0; i < count; i++) {
            if (!getPart(i).getLive()) {
                die();
                return false;
            }
        }
    }
    if (equations.lethalContainer) {
        if (!((Part) container).getLive()) {
            die();
            return false;
        }
    }
    return true;
}
Also used : EquationSet(gov.sandia.n2a.eqset.EquationSet) Variable(gov.sandia.n2a.eqset.Variable) Instance(gov.sandia.n2a.language.type.Instance) ArrayList(java.util.ArrayList) Conversion(gov.sandia.n2a.backend.internal.InternalBackendData.Conversion) Scalar(gov.sandia.n2a.language.type.Scalar) EventSource(gov.sandia.n2a.backend.internal.InternalBackendData.EventSource) Type(gov.sandia.n2a.language.Type) Matrix(gov.sandia.n2a.language.type.Matrix) EventTarget(gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)

Example 10 with Scalar

use of gov.sandia.n2a.language.type.Scalar in project n2a by frothga.

the class Part method die.

public void die() {
    // set $live to false, if it is stored in this part
    InternalBackendData bed = (InternalBackendData) equations.backendData;
    if (bed.liveStorage == InternalBackendData.LIVE_STORED) {
        set(bed.live, new Scalar(0));
    }
    // update accountable endpoints
    if (bed.count != null) {
        int length = bed.count.length;
        for (int i = 0; i < length; i++) {
            if (bed.count[i] >= 0) {
                Part p = (Part) valuesObject[bed.endpoints + i];
                p.valuesFloat[bed.count[i]]--;
            }
        }
    }
    // Release event monitors
    for (EventTarget et : bed.eventTargets) {
        for (EventSource es : et.sources) {
            // Don't bother with self-connection, since we are going away.
            if (es.reference == null)
                continue;
            Part source = (Part) valuesObject[es.reference.index];
            @SuppressWarnings("unchecked") ArrayList<Instance> monitors = (ArrayList<Instance>) source.valuesObject[es.monitorIndex];
            int index = monitors.indexOf(this);
            // Actually removing the element can cause a concurrent modification exception. Instead, the monitors array will get flushed next time an event processes it.
            monitors.set(index, null);
        }
    }
    ((Population) container.valuesObject[bed.populationIndex]).remove(this);
}
Also used : EventSource(gov.sandia.n2a.backend.internal.InternalBackendData.EventSource) Instance(gov.sandia.n2a.language.type.Instance) ArrayList(java.util.ArrayList) EventTarget(gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget) Scalar(gov.sandia.n2a.language.type.Scalar)

Aggregations

Scalar (gov.sandia.n2a.language.type.Scalar)42 Type (gov.sandia.n2a.language.Type)17 AccessVariable (gov.sandia.n2a.language.AccessVariable)14 Variable (gov.sandia.n2a.eqset.Variable)13 Matrix (gov.sandia.n2a.language.type.Matrix)11 Constant (gov.sandia.n2a.language.Constant)10 Operator (gov.sandia.n2a.language.Operator)10 Text (gov.sandia.n2a.language.type.Text)8 EquationSet (gov.sandia.n2a.eqset.EquationSet)6 ArrayList (java.util.ArrayList)6 Simulator (gov.sandia.n2a.backend.internal.Simulator)5 Instance (gov.sandia.n2a.language.type.Instance)5 MatrixDense (gov.sandia.n2a.language.type.MatrixDense)5 TreeSet (java.util.TreeSet)5 EventSource (gov.sandia.n2a.backend.internal.InternalBackendData.EventSource)4 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)4 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)3 VariableReference (gov.sandia.n2a.eqset.VariableReference)3 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)2 EvaluationException (gov.sandia.n2a.language.EvaluationException)2