Search in sources :

Example 46 with Variable

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

the class ExportJob method fakeConnectionTarget.

/**
 *        Replace any entries of the form A=connect() with A=N2A_fakePart.
 */
public static boolean fakeConnectionTarget(EquationSet s) {
    boolean result = false;
    for (Variable v : s.variables) {
        if (// may be due to unreadable part names in connect()
        v.equations.size() == 0) {
            String value = s.source.get(v.nameString());
            if (!Operator.containsConnect(value))
                continue;
            try {
                v.add(new EquationEntry("N2A_fakePart"));
                result = true;
            } catch (Exception e) {
            }
        } else if (// could be a properly-parsed connect() line
        v.equations.size() == 1) {
            EquationEntry e = v.equations.first();
            // connect() appears like AccessElement during initial parse
            if (!(e.expression instanceof AccessElement))
                continue;
            AccessElement ae = (AccessElement) e.expression;
            AccessVariable av = (AccessVariable) ae.operands[0];
            if (!av.name.equals("connect"))
                continue;
            av.name = "N2A_fakePart";
            e.expression = av;
            result = true;
        }
    }
    for (EquationSet p : s.parts) if (fakeConnectionTarget(p))
        result = true;
    return result;
}
Also used : 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) AccessVariable(gov.sandia.n2a.language.AccessVariable) AccessElement(gov.sandia.n2a.language.AccessElement) EquationEntry(gov.sandia.n2a.eqset.EquationEntry) UnconvertibleException(javax.measure.UnconvertibleException) IncommensurableException(javax.measure.IncommensurableException)

Example 47 with Variable

use of gov.sandia.n2a.eqset.Variable 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 48 with Variable

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

the class XyceBackendData method analyze.

public void analyze(EquationSet s) {
    if (Device.isXyceDevice(s)) {
        deviceSymbol = new Device(s);
    }
    class ContainsOperator implements Visitor {

        @SuppressWarnings("rawtypes")
        public Class targetClass;

        boolean found;

        public boolean visit(Operator op) {
            if (found)
                return false;
            if (op.getClass().equals(targetClass)) {
                found = true;
                return false;
            }
            return true;
        }

        public boolean check(EquationEntry e) {
            found = false;
            e.expression.visit(this);
            return found;
        }
    }
    ContainsOperator containsPulse = new ContainsOperator();
    containsPulse.targetClass = Pulse.class;
    ContainsOperator containsSinewave = new ContainsOperator();
    containsSinewave.targetClass = Sinewave.class;
    ContainsVariable containsT = new ContainsVariable(new Variable("$t"));
    for (Variable v : s.variables) {
        // in a static (no structural dynamics) simulation, no $variable needs to be computed at runtime
        if (v.name.startsWith("$"))
            continue;
        // Constants are already subbed in. "initOnly" values are defined during init cycle, and can now be subbed during code generation.
        if (v.hasAttribute("constant") || v.hasAttribute("initOnly"))
            continue;
        for (EquationEntry eq : v.equations) {
            // don't need to write out equations defining dynamics already defined by a device
            if (Device.isXyceDevice(s) && Device.ignoreEquation(eq))
                continue;
            Symbol handler = null;
            if (eq.variable.order > 1) {
                Backend.err.get().println("Support for higher order differential equations not implemented yet (" + eq + ")");
                throw new Backend.AbortRun();
            } else if (eq.variable.order == 1) {
                handler = new SymbolStateVar1(eq);
            } else // The following are all order 0
            if (containsPulse.check(eq)) {
                handler = new SymbolPulse(eq);
            } else if (containsSinewave.check(eq)) {
                handler = new SymbolSinewave(eq);
            } else // TODO: this doesn't seem like an adequate test. Why would having a $t be the only reason to generate a zero-order symbol?
            if (containsT.check(eq.expression)) {
                handler = new SymbolStateVar0(eq);
            } else if (isExplicitInit(eq)) {
                handler = new SymbolConstantIC(eq);
            } else {
                // The RHS expression depends on state variables, so we create a netlist .func for it.
                handler = new SymbolFunc(eq);
            }
            equationSymbols.put(eq, handler);
            // May set the handler for v several times, but only the last one is kept. Multiple handlers should agree on symbol for reference. Better yet is to handle multiple equations together.
            variableSymbols.put(v.name, handler);
        }
    }
}
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) SymbolStateVar0(gov.sandia.n2a.backend.xyce.netlist.SymbolStateVar0) SymbolStateVar1(gov.sandia.n2a.backend.xyce.netlist.SymbolStateVar1) Device(gov.sandia.n2a.backend.xyce.netlist.Device) Symbol(gov.sandia.n2a.backend.xyce.netlist.Symbol) SymbolPulse(gov.sandia.n2a.backend.xyce.netlist.SymbolPulse) SymbolFunc(gov.sandia.n2a.backend.xyce.netlist.SymbolFunc) SymbolSinewave(gov.sandia.n2a.backend.xyce.netlist.SymbolSinewave) EquationEntry(gov.sandia.n2a.eqset.EquationEntry) SymbolConstantIC(gov.sandia.n2a.backend.xyce.netlist.SymbolConstantIC)

Example 49 with Variable

use of gov.sandia.n2a.eqset.Variable 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 50 with Variable

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

Variable (gov.sandia.n2a.eqset.Variable)63 AccessVariable (gov.sandia.n2a.language.AccessVariable)38 EquationSet (gov.sandia.n2a.eqset.EquationSet)25 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)20 Scalar (gov.sandia.n2a.language.type.Scalar)18 Operator (gov.sandia.n2a.language.Operator)17 ArrayList (java.util.ArrayList)17 Type (gov.sandia.n2a.language.Type)12 Visitor (gov.sandia.n2a.language.Visitor)12 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)11 MNode (gov.sandia.n2a.db.MNode)9 VariableReference (gov.sandia.n2a.eqset.VariableReference)9 Constant (gov.sandia.n2a.language.Constant)9 MPart (gov.sandia.n2a.eqset.MPart)7 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)6 Output (gov.sandia.n2a.language.function.Output)6 FilteredTreeModel (gov.sandia.n2a.ui.eq.FilteredTreeModel)6 List (java.util.List)6 IncommensurableException (javax.measure.IncommensurableException)6 UnconvertibleException (javax.measure.UnconvertibleException)6