Search in sources :

Example 6 with Backend

use of gov.sandia.n2a.plugins.extpoints.Backend in project n2a by frothga.

the class BackendDataC method analyze.

public void analyze(final EquationSet s) {
    boolean headless = AppData.properties.getBoolean("headless");
    if (!headless)
        System.out.println(s.name);
    for (// we want the sub-lists to be ordered correctly
    Variable v : // we want the sub-lists to be ordered correctly
    s.ordered) {
        if (!headless) {
            String className = "null";
            if (v.type != null)
                className = v.type.getClass().getSimpleName();
            System.out.println("  " + v.nameString() + " " + v.attributeString() + " " + className);
        }
        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("$n") && v.order == 0) {
            if (s.connectionBindings != null) {
                // It is an error to explicitly define $n on a connection,
                // which is the only way we can get to this point.
                Backend.err.get().println("$n is not applicable to connections");
                throw new Backend.AbortRun();
            }
            n = v;
            nInitOnly = n.hasAttribute("initOnly");
            // In this special case we will directly use the current population count.
            if (nInitOnly)
                n.addAttribute("preexistent");
        } else if (v.name.equals("$index")) {
            index = v;
            // Don't let $index enter into any variable lists. Instead, always give it special treatment. In effect, it is a list of one.
            continue;
        } else if (v.name.equals("$live")) {
            live = v;
            // $live can never function as a regular variable because it is stored as a bit flag
            continue;
        } else if (v.name.equals("$t")) {
            if (v.order == 0)
                t = v;
            else if (v.order == 1)
                dt = v;
        }
        if (v.hasAny(new String[] { "constant", "accessor" }) && !v.hasAll(new String[] { "constant", "reference" }))
            continue;
        boolean initOnly = v.hasAttribute("initOnly");
        boolean emptyCombiner = v.isEmptyCombiner();
        boolean updates = !initOnly && v.equations.size() > 0 && !emptyCombiner && (v.derivative == null || v.hasAttribute("updates"));
        boolean temporary = v.hasAttribute("temporary");
        boolean unusedTemporary = temporary && !v.hasUsers();
        boolean derivativeOrDependency = v.hasAttribute("derivativeOrDependency");
        if (v.hasAttribute("global")) {
            if (updates && !unusedTemporary)
                globalUpdate.add(v);
            if (derivativeOrDependency)
                globalDerivativeUpdate.add(v);
            if (!unusedTemporary && !emptyCombiner)
                globalInit.add(v);
            if (!v.hasAttribute("reference")) {
                if (!temporary && !v.hasAttribute("dummy")) {
                    if (!v.hasAttribute("preexistent")) {
                        globalMembers.add(v);
                        // check if v.usedBy contains any variable that is not v's integral
                        if (derivativeOrDependency && v.derivative == null && v.usedBy != null) {
                            for (Object o : v.usedBy) {
                                if (o instanceof Variable && ((Variable) o).derivative != v) {
                                    globalDerivativePreserve.add(v);
                                    break;
                                }
                            }
                        }
                    }
                    boolean external = false;
                    if (!initOnly) {
                        if (v.name.equals("$t")) {
                            if (v.order > 1)
                                globalDerivative.add(v);
                        } else // any other variable
                        {
                            if (v.order > 0)
                                globalDerivative.add(v);
                        }
                        // The integration step has roughly the same effect as an external write.
                        if (v.hasAttribute("externalWrite") || v.assignment != Variable.REPLACE) {
                            external = true;
                            globalBufferedExternalWrite.add(v);
                            if (derivativeOrDependency)
                                globalBufferedExternalWriteDerivative.add(v);
                        }
                        if (external || (v.hasAttribute("externalRead") && updates)) {
                            external = true;
                            globalBufferedExternal.add(v);
                            if (derivativeOrDependency)
                                globalBufferedExternalDerivative.add(v);
                        }
                    }
                    if (external || v.hasAttribute("cycle")) {
                        globalBuffered.add(v);
                        if (!external && !initOnly) {
                            globalBufferedInternalUpdate.add(v);
                            if (derivativeOrDependency)
                                globalBufferedInternalDerivative.add(v);
                        }
                    }
                }
            }
        } else // local
        {
            if (updates && !unusedTemporary)
                localUpdate.add(v);
            if (derivativeOrDependency)
                localDerivativeUpdate.add(v);
            if (!unusedTemporary && !emptyCombiner && v != type)
                localInit.add(v);
            if (v.hasAttribute("reference")) {
                if (v.reference.variable.container.canDie())
                    localReference.add(v.reference);
            } else {
                if (!temporary && !v.hasAttribute("dummy")) {
                    if (!v.hasAttribute("preexistent")) {
                        localMembers.add(v);
                        if (derivativeOrDependency && v.derivative == null && v.usedBy != null) {
                            for (Object o : v.usedBy) {
                                if (o instanceof Variable && ((Variable) o).derivative != v) {
                                    localDerivativePreserve.add(v);
                                    break;
                                }
                            }
                        }
                    }
                    boolean external = false;
                    if (!initOnly) {
                        if (v.name.equals("$t")) {
                            if (v.order > 1)
                                localDerivative.add(v);
                        } else {
                            if (v.order > 0)
                                localDerivative.add(v);
                        }
                        if (v.hasAttribute("externalWrite") || v.assignment != Variable.REPLACE) {
                            external = true;
                            localBufferedExternalWrite.add(v);
                            if (derivativeOrDependency)
                                localBufferedExternalWriteDerivative.add(v);
                        }
                        if (external || (v.hasAttribute("externalRead") && updates)) {
                            external = true;
                            localBufferedExternal.add(v);
                            if (derivativeOrDependency)
                                localBufferedExternalDerivative.add(v);
                        }
                    }
                    if (external || v.hasAttribute("cycle")) {
                        localBuffered.add(v);
                        if (!external && !initOnly) {
                            localBufferedInternalUpdate.add(v);
                            if (derivativeOrDependency)
                                localBufferedInternalDerivative.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("constant", "initOnly")) {
            if (v.hasAttribute("global"))
                globalIntegrated.add(v);
            else
                localIntegrated.add(v);
        }
    }
    // Purge any lists that consist solely of temporaries, as they accomplish nothing.
    for (List<Variable> list : Arrays.asList(globalUpdate, globalDerivativeUpdate, globalInit, globalIntegrated, localUpdate, localDerivativeUpdate, localInit, localIntegrated)) {
        boolean allTemporary = true;
        for (Variable v : list) if (!v.hasAttribute("temporary"))
            allTemporary = false;
        if (allTemporary)
            list.clear();
    }
    if (dt != null && dt.hasAttribute("constant")) {
        setDt = true;
        // However, if the nearest container that defines $t' matches our value, then don't set $t'.
        if (s.container != null) {
            Variable pdt = s.container.findDt();
            if (pdt != null && pdt.hasAttribute("constant")) {
                double value = dt.equations.first().expression.getDouble();
                double pvalue = pdt.equations.first().expression.getDouble();
                setDt = value != pvalue;
            }
        }
    }
    if (s.connectionBindings != null) {
        for (ConnectionBinding c : s.connectionBindings) {
            Variable v = s.find(new Variable(c.alias + ".$max", -1));
            if (v == null)
                v = s.find(new Variable(c.alias + ".$min", -1));
            if (v != null)
                accountableEndpoints.add(c.alias);
            if (s.find(new Variable(c.alias + ".$project")) != null)
                hasProject = true;
        }
    }
    if (eventTargets.size() > 0) {
        for (EventTarget et : eventTargets) {
            if (et.delay < -1) {
                needLocalEventDelay = true;
                break;
            }
        }
    }
    boolean canDie = s.canDie();
    refcount = s.referenced && canDie;
    singleton = s.isSingleton(true);
    // Works correctly even if n is null.
    canResize = globalMembers.contains(n);
    trackInstances = s.connected || s.needInstanceTracking || canResize;
    canGrowOrDie = s.lethalP || s.lethalType || s.canGrow();
    trackN = n != null && !singleton;
    boolean Euler = s.getRoot().metadata.getOrDefault("Euler", "backend", "all", "integrator").equals("Euler");
    if (!canResize && canGrowOrDie && n != null && n.hasUsers()) {
        // This is a flaw in the analysis process that needs to be fixed.
        // See note in InternalBackendData for details.
        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.");
    }
    int flagCount = eventTargets.size();
    if (live != null && !live.hasAny(new String[] { "constant", "accessor" }))
        liveFlag = flagCount++;
    if (trackInstances && s.connected)
        newborn = flagCount++;
    if (flagCount == 0)
        localFlagType = "";
    else if (flagCount <= 8)
        localFlagType = "uint8_t";
    else if (flagCount <= 16)
        localFlagType = "uint16_t";
    else if (flagCount <= 32)
        localFlagType = "uint32_t";
    else if (flagCount <= 64)
        localFlagType = "uint64_t";
    else {
        Backend.err.get().println("ERROR: Too many local flags to fit in basic integer type");
        throw new Backend.AbortRun();
    }
    flagCount = 0;
    if (trackInstances && s.connected)
        clearNew = flagCount++;
    if (flagCount == 0)
        globalFlagType = "";
    else if (flagCount <= 8)
        globalFlagType = "uint8_t";
    else if (flagCount <= 16)
        globalFlagType = "uint16_t";
    else if (flagCount <= 32)
        globalFlagType = "uint32_t";
    else if (flagCount <= 64)
        globalFlagType = "uint64_t";
    else {
        Backend.err.get().println("ERROR: Too many global flags to fit in basic integer type");
        throw new Backend.AbortRun();
    }
    needGlobalDerivative = !Euler && globalDerivative.size() > 0;
    needGlobalIntegrate = globalIntegrated.size() > 0;
    needGlobalPreserve = !Euler && (needGlobalIntegrate || globalDerivativePreserve.size() > 0 || globalBufferedExternalWriteDerivative.size() > 0);
    needGlobalDtor = needGlobalPreserve || needGlobalDerivative;
    needGlobalCtor = needGlobalDtor || (index != null || n != null) && !singleton;
    needGlobalInit = globalMembers.size() > 0 || !globalFlagType.isEmpty() || globalInit.size() > 0 || singleton || n != null || s.connectionBindings != null;
    needGlobalUpdate = globalUpdate.size() > 0;
    needGlobalFinalizeN = s.container == null && (canResize || canGrowOrDie);
    needGlobalFinalize = globalBufferedExternal.size() > 0 || needGlobalFinalizeN || (canResize && (canGrowOrDie || !n.hasAttribute("initOnly")));
    needGlobalUpdateDerivative = !Euler && globalDerivativeUpdate.size() > 0;
    needGlobalFinalizeDerivative = !Euler && globalBufferedExternalDerivative.size() > 0;
    // Created simplified localInit to check if init is needed.
    // This is only temporary, because the proper simplification should only be done after I/O operators have names generated.
    List<Variable> simplifiedLocalInit = new ArrayList<Variable>(localInit);
    s.simplify("$init", simplifiedLocalInit);
    needLocalDerivative = !Euler && localDerivative.size() > 0;
    needLocalIntegrate = localIntegrated.size() > 0;
    needLocalPreserve = !Euler && (needLocalIntegrate || localDerivativePreserve.size() > 0 || localBufferedExternalWriteDerivative.size() > 0);
    needLocalDtor = needLocalPreserve || needLocalDerivative;
    needLocalCtor = needLocalDtor || s.accountableConnections != null || refcount || index != null || localMembers.size() > 0 || s.parts.size() > 0;
    needLocalDie = canDie && (liveFlag >= 0 || trackN || accountableEndpoints.size() > 0 || eventTargets.size() > 0);
    needLocalInit = localBufferedExternal.size() > 0 || eventTargets.size() > 0 || !localFlagType.isEmpty() || lastT || simplifiedLocalInit.size() > 0 || trackN || accountableEndpoints.size() > 0 || eventTargets.size() > 0 || s.parts.size() > 0;
    needLocalUpdate = localUpdate.size() > 0;
    needLocalFinalize = localBufferedExternal.size() > 0 || type != null || canDie;
    needLocalUpdateDerivative = !Euler && localDerivativeUpdate.size() > 0;
    needLocalFinalizeDerivative = !Euler && localBufferedExternalDerivative.size() > 0;
    // Ensure that functions are emitted to update child populations.
    for (EquationSet p : s.parts) {
        BackendDataC pbed = (BackendDataC) p.backendData;
        if (pbed.needGlobalInit)
            needLocalInit = true;
        if (pbed.needGlobalIntegrate)
            needLocalIntegrate = true;
        if (pbed.needGlobalUpdate)
            needLocalUpdate = true;
        if (pbed.needGlobalFinalize)
            needLocalFinalize = true;
        if (pbed.needGlobalUpdateDerivative)
            needLocalUpdateDerivative = true;
        if (pbed.needGlobalFinalizeDerivative)
            needLocalFinalizeDerivative = true;
        if (pbed.needGlobalPreserve)
            needLocalPreserve = true;
        if (pbed.needGlobalDerivative)
            needLocalDerivative = true;
    }
}
Also used : EquationSet(gov.sandia.n2a.eqset.EquationSet) Variable(gov.sandia.n2a.eqset.Variable) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) ArrayList(java.util.ArrayList) Backend(gov.sandia.n2a.plugins.extpoints.Backend) EventTarget(gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)

Aggregations

Backend (gov.sandia.n2a.plugins.extpoints.Backend)6 Date (java.util.Date)4 Host (gov.sandia.n2a.host.Host)3 Remote (gov.sandia.n2a.host.Remote)3 IOException (java.io.IOException)3 MDoc (gov.sandia.n2a.db.MDoc)2 MNode (gov.sandia.n2a.db.MNode)2 NodeJob (gov.sandia.n2a.ui.jobs.NodeJob)2 Path (java.nio.file.Path)2 SimpleDateFormat (java.text.SimpleDateFormat)2 TreePath (javax.swing.tree.TreePath)2 InternalBackend (gov.sandia.n2a.backend.internal.InternalBackend)1 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)1 EquationSet (gov.sandia.n2a.eqset.EquationSet)1 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)1 MPart (gov.sandia.n2a.eqset.MPart)1 Variable (gov.sandia.n2a.eqset.Variable)1 HostSystem (gov.sandia.n2a.execenvs.HostSystem)1 UnitValue (gov.sandia.n2a.language.UnitValue)1 ExtensionPoint (gov.sandia.n2a.plugins.ExtensionPoint)1