Search in sources :

Example 46 with EquationSet

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

the class ExportJob method analyze.

/**
 *        Find references to $index in connection endpoints, and set up info for ConnectionContext.
 */
public void analyze(EquationSet s) {
    for (EquationSet p : s.parts) analyze(p);
    class ExportTransformer implements Transformer {

        Variable v;

        public Operator transform(Operator op) {
            if (op instanceof AccessVariable) {
                VariableReference r = ((AccessVariable) op).reference;
                // It is possible that some variables were not resolved.
                if (r == null)
                    return null;
                Variable rv = r.variable;
                if (rv.container != v.container && !r.resolution.isEmpty()) {
                    Object o = r.resolution.get(r.resolution.size() - 1);
                    if (o instanceof ConnectionBinding) {
                        // This is somewhat of a hack, but ConnectionContext assumes the mappings A->0 and B->1.
                        switch(((ConnectionBinding) o).alias) {
                            case "A":
                                r.index = 0;
                                break;
                            case "B":
                                r.index = 1;
                                break;
                        }
                    }
                }
                return null;
            }
            if (op instanceof Output) {
                return new OutputLEMS((Output) op);
            }
            return null;
        }
    }
    ;
    ExportTransformer xform = new ExportTransformer();
    for (final Variable v : s.variables) {
        xform.v = v;
        v.transform(xform);
        // does not call that function.
        if (v.hasUsers() || v.hasAttribute("externalWrite"))
            continue;
        if (v.name.startsWith("$") || v.name.contains(".$"))
            continue;
        for (EquationEntry e : v.equations) {
            if (e.expression.isOutput()) {
                v.addAttribute("dummy");
                break;
            }
        }
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) EquationSet(gov.sandia.n2a.eqset.EquationSet) Variable(gov.sandia.n2a.eqset.Variable) UnresolvedVariable(gov.sandia.n2a.eqset.EquationSet.UnresolvedVariable) AccessVariable(gov.sandia.n2a.language.AccessVariable) Transformer(gov.sandia.n2a.language.Transformer) AccessVariable(gov.sandia.n2a.language.AccessVariable) VariableReference(gov.sandia.n2a.eqset.VariableReference) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) Output(gov.sandia.n2a.language.function.Output) EquationEntry(gov.sandia.n2a.eqset.EquationEntry)

Example 47 with EquationSet

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

the class BackendDataC method setLocalNeedPath.

public void setLocalNeedPath(EquationSet s) {
    EquationSet c = s.container;
    // Don't set flag, because we know that path() will return "".
    if (c == null && s.isSingleton(false))
        return;
    needLocalPath = true;
    setParentNeedPath(s);
}
Also used : EquationSet(gov.sandia.n2a.eqset.EquationSet)

Example 48 with EquationSet

use of gov.sandia.n2a.eqset.EquationSet 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)

Example 49 with EquationSet

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

the class JobC method analyzeEvents.

public void analyzeEvents(EquationSet s) throws Backend.AbortRun {
    BackendDataC bed = (BackendDataC) s.backendData;
    bed.analyzeEvents(s);
    for (EquationSet p : s.parts) analyzeEvents(p);
}
Also used : EquationSet(gov.sandia.n2a.eqset.EquationSet)

Example 50 with EquationSet

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

the class JobC method run.

public void run() {
    localJobDir = Host.getJobDir(Host.getLocalResourceDir(), job);
    Path errPath = localJobDir.resolve("err");
    try {
        Backend.err.set(new PrintStream(new FileOutputStream(errPath.toFile(), true), false, "UTF-8"));
    } catch (Exception e) {
    }
    try {
        Files.createFile(localJobDir.resolve("started"));
        MNode model = NodeJob.getModel(job);
        T = model.getOrDefault("float", "$metadata", "backend", "c", "type");
        if (T.startsWith("int") && T.length() > 3) {
            T = "int";
            Backend.err.get().println("WARNING: Only supported integer type is 'int', which is assumed to be signed 32-bit.");
        }
        if (!T.equals("int") && !T.equals("double") && !T.equals("float")) {
            T = "float";
            Backend.err.get().println("WARNING: Unsupported numeric type. Defaulting to single-precision float.");
        }
        kokkos = model.getFlag("$metadata", "backend", "c", "kokkos");
        gprof = model.getFlag("$metadata", "backend", "c", "gprof");
        cli = model.getFlag("$metadata", "backend", "c", "cli");
        String e = model.get("$metadata", "backend", "all", "event");
        switch(e) {
            case "before":
                during = false;
                after = false;
                break;
            case "after":
                during = false;
                after = true;
            default:
                // during
                during = true;
                after = false;
        }
        env = Host.get(job);
        Path resourceDir = env.getResourceDir();
        // Unlike localJobDir (which is created by MDir), this may not exist until we explicitly create it.
        jobDir = Host.getJobDir(resourceDir, job);
        // No good way to decide absolute path for the default value. Maybe need to call "which" command for this.
        gcc = resourceDir.getFileSystem().getPath(env.config.getOrDefault("g++", "backend", "c", "cxx"));
        runtimeDir = resourceDir.resolve("backend").resolve("c");
        rebuildRuntime();
        // digestModel() might write to a remote file (params), so we need to ensure the dir exists first.
        Files.createDirectories(jobDir);
        digestedModel = new EquationSet(model);
        digestModel();
        String duration = digestedModel.metadata.get("duration");
        if (!duration.isEmpty())
            job.set(duration, "duration");
        seed = -1;
        if (// only record seed if actually used
        digestedModel.usesRandom()) {
            seed = model.getOrDefault(System.currentTimeMillis() & 0xFFFFFFFFL, "$metadata", "seed");
            job.set(seed, "seed");
        }
        System.out.println(digestedModel.dump(false));
        Path source = jobDir.resolve("model.cc");
        generateCode(source);
        String command = env.quote(build(source));
        // The C program could append to the same error file, so we need to close the file before submitting.
        PrintStream ps = Backend.err.get();
        if (ps != System.err) {
            ps.close();
            Backend.err.remove();
            job.set(Host.size(errPath), "errSize");
        }
        env.submitJob(job, false, command);
    } catch (Exception e) {
        if (!(e instanceof AbortRun))
            e.printStackTrace(Backend.err.get());
        try {
            Files.copy(new ByteArrayInputStream("failure".getBytes("UTF-8")), localJobDir.resolve("finished"));
        } catch (Exception f) {
        }
    }
    // If an exception occurred, the error file will still be open.
    PrintStream ps = Backend.err.get();
    if (ps != System.err)
        ps.close();
}
Also used : Path(java.nio.file.Path) PrintStream(java.io.PrintStream) EquationSet(gov.sandia.n2a.eqset.EquationSet) ByteArrayInputStream(java.io.ByteArrayInputStream) FileOutputStream(java.io.FileOutputStream) MNode(gov.sandia.n2a.db.MNode) IOException(java.io.IOException) AbortRun(gov.sandia.n2a.plugins.extpoints.Backend.AbortRun)

Aggregations

EquationSet (gov.sandia.n2a.eqset.EquationSet)63 Variable (gov.sandia.n2a.eqset.Variable)25 AccessVariable (gov.sandia.n2a.language.AccessVariable)24 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)16 ArrayList (java.util.ArrayList)16 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)12 Operator (gov.sandia.n2a.language.Operator)12 MNode (gov.sandia.n2a.db.MNode)11 MPart (gov.sandia.n2a.eqset.MPart)10 Constant (gov.sandia.n2a.language.Constant)10 Scalar (gov.sandia.n2a.language.type.Scalar)10 IncommensurableException (javax.measure.IncommensurableException)9 UnconvertibleException (javax.measure.UnconvertibleException)9 AbortRun (gov.sandia.n2a.plugins.extpoints.Backend.AbortRun)8 VariableReference (gov.sandia.n2a.eqset.VariableReference)7 Type (gov.sandia.n2a.language.Type)7 ExtensionPoint (gov.sandia.n2a.plugins.ExtensionPoint)7 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)6 Visitor (gov.sandia.n2a.language.Visitor)6 EventSource (gov.sandia.n2a.backend.internal.InternalBackendData.EventSource)5