Search in sources :

Example 1 with Split

use of gov.sandia.n2a.language.Split in project n2a by frothga.

the class EquationSet method resolveRHS.

public void resolveRHS(LinkedList<String> unresolved) {
    for (EquationSet s : parts) {
        s.resolveRHS(unresolved);
    }
    class Resolver extends Transformer {

        public Variable from;

        public LinkedList<String> unresolved;

        public String fromName() {
            String result = from.container.prefix();
            if (!result.isEmpty())
                result += ".";
            return result + from.nameString();
        }

        public Operator transform(Operator op) {
            if (op instanceof AccessVariable) {
                AccessVariable av = (AccessVariable) op;
                Variable query = new Variable(av.getName(), av.getOrder());
                query.reference = new VariableReference();
                EquationSet dest = resolveEquationSet(query, false);
                if (dest == null) {
                    unresolved.add(av.name + "\t" + fromName());
                } else {
                    query.reference.variable = dest.find(query);
                    if (query.reference.variable == null) {
                        if (query.name.equals("(connection)")) {
                            // create a phantom variable.  TODO: should this be an attribute instead?
                            query.reference.variable = new Variable("(connection)");
                            // the container itself is really the target
                            query.reference.variable.container = dest;
                            // because instance variables are bound before the part is put into service, and remain constant for its entire life
                            query.reference.variable.addAttribute("initOnly");
                            // TODO: when $connect() is implemented, instances should become first class variables in the equation set, and this circular reference will be created by resolveLHS()
                            query.reference.variable.reference = query.reference;
                        } else if (// accountable endpoint
                        query.name.equals("$count")) {
                            if (dest.accountableConnections == null)
                                dest.accountableConnections = new TreeSet<AccountableConnection>();
                            String alias = av.name.split("\\.", 2)[0];
                            AccountableConnection ac = new AccountableConnection(EquationSet.this, alias);
                            if (!dest.accountableConnections.add(ac))
                                ac = dest.accountableConnections.floor(ac);
                            if (ac.count == null) {
                                // Create a fully-functional variable.
                                // However, it never gets formally added to dest, because dest should never evaluate it.
                                // Rather, it is maintained by the backend's connection system.
                                ac.count = new Variable(prefix() + ".$count");
                                ac.count.type = new Scalar(0);
                                ac.count.container = dest;
                                ac.count.equations = new TreeSet<EquationEntry>();
                                query.reference.variable = ac.count;
                                query.reference.variable.reference = query.reference;
                            } else {
                                query.reference.variable = ac.count;
                            }
                        } else {
                            unresolved.add(av.name + "\t" + fromName());
                        }
                    } else {
                        Variable target = query.reference.variable;
                        from.addDependencyOn(target);
                        if (from.container != target.container) {
                            target.addAttribute("externalRead");
                            if (target.hasAttribute("temporary")) {
                                Backend.err.get().println("WARNING: Variable " + target.container.prefix() + "." + target.nameString() + " has an external read, so cannot be temporary.");
                                target.removeAttribute("temporary");
                            }
                        }
                    }
                }
                av.reference = query.reference;
                return av;
            }
            if (op instanceof Split) {
                Split split = (Split) op;
                int count = split.names.length;
                split.parts = new ArrayList<EquationSet>(count);
                for (int i = 0; i < count; i++) {
                    String temp = split.names[i];
                    EquationSet part = container.parts.floor(new EquationSet(temp));
                    if (part.name.equals(temp))
                        split.parts.add(part);
                    else
                        unresolved.add(temp + "\t" + fromName());
                }
            }
            return null;
        }
    }
    Resolver resolver = new Resolver();
    for (Variable v : variables) {
        resolver.from = v;
        resolver.unresolved = unresolved;
        v.transform(resolver);
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) Transformer(gov.sandia.n2a.language.Transformer) AccessVariable(gov.sandia.n2a.language.AccessVariable) LinkedList(java.util.LinkedList) Scalar(gov.sandia.n2a.language.type.Scalar) TreeSet(java.util.TreeSet) Split(gov.sandia.n2a.language.Split)

Example 2 with Split

use of gov.sandia.n2a.language.Split in project n2a by frothga.

the class InternalBackendData method analyze.

public void analyze(final EquationSet s) {
    boolean headless = AppData.properties.getBoolean("headless");
    if (!headless)
        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();
    }
    fastExit = s.metadata.getFlag("backend", "all", "fastExit");
    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();
            String dimensionName = "";
            if (v.unit != null)
                dimensionName = v.unit.toString();
            System.out.println("  " + v.nameString() + " " + v.attributeString() + " " + className + " " + dimensionName);
        }
        if (v.name.equals("$connect"))
            connect = v;
        else 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;
        }
        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();
        if (v.hasAttribute("externalWrite"))
            v.externalWrite = true;
        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.hasColumnName) {
                            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" })) {
                if (updates)
                    globalUpdate.add(v);
                if (!unusedTemporary && !emptyCombiner)
                    globalInit.add(v);
                if (v.hasAttribute("reference")) {
                    addReferenceGlobal(v.reference, s);
                } else if (!temporary && !v.hasAttribute("dummy")) {
                    if (!v.hasAttribute("preexistent"))
                        globalMembers.add(v);
                    boolean external = false;
                    if (v.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")) {
                        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.hasColumnName) {
                            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" })) {
                if (updates)
                    localUpdate.add(v);
                if (!unusedTemporary && !emptyCombiner && !forbiddenLocalInit.contains(v.name))
                    localInit.add(v);
                if (v.hasAttribute("reference")) {
                    addReferenceLocal(v.reference, s);
                } else if (!temporary && !v.hasAttribute("dummy")) {
                    if (!v.hasAttribute("preexistent"))
                        localMembers.add(v);
                    boolean external = false;
                    if (v.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")) {
                        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);
        }
    }
    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;
            }
        }
    }
    determineOrderInit("$init", s, localInit);
    determineOrderInit("$init", s, globalInit);
    singleton = s.isSingleton(true);
    populationCanGrowOrDie = s.lethalP || s.lethalType || s.canGrow();
    if (n != null && !singleton) {
        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 && !singleton) {
        indexNext = allocateGlobalFloat("indexNext");
        indexAvailable = allocateGlobalObject("indexAvailable");
    }
    if (// track instances
    singleton || s.connected || s.needInstanceTracking || populationCanResize) {
        // The reason populationCanResize forces use of the instances array is to enable pruning of parts when $n decreases.
        // The reason to "track instances" for a singleton is to allocate a slot for direct storage of the single instance in valuesObject.
        instances = allocateGlobalObject("instances");
        if (// in addition, track newly created instances
        s.connected) {
            if (!singleton)
                firstborn = allocateGlobalFloat("firstborn");
            newborn = allocateLocalFloat("newborn");
        }
    }
    // Just give name of connection part itself.
    if (s.connectionBindings != null) {
        singleConnection = true;
        for (ConnectionBinding cb : s.connectionBindings) {
            if (cb.endpoint.container != s.container || !cb.endpoint.isSingleton(true)) {
                singleConnection = false;
                break;
            }
        }
    }
    if (p != null) {
        Pdependencies = new ArrayList<Variable>();
        PdependenciesTemp = new ArrayList<Variable>();
        for (Variable t : s.ordered) {
            boolean temporary = t.hasAttribute("temporary");
            if ((temporary || localMembers.contains(t)) && p.dependsOn(t) != null) {
                Pdependencies.add(t);
                if (temporary)
                    PdependenciesTemp.add(t);
            }
        }
        determineOrderInit("$connect", s, Pdependencies);
        // determineOrderInit() is not needed for PdepenciesTemp, because temps are already in the correct order.
        // Default is no polling
        String pollString = "-1";
        if (p.metadata != null)
            pollString = p.metadata.getOrDefault(pollString, "poll");
        poll = new UnitValue(pollString).get();
        if (poll >= 0) {
            pollDeadline = allocateGlobalFloat("pollDeadline");
            pollSorted = allocateGlobalObject("pollSorted");
        }
    }
    if (type != null) {
        for (EquationEntry e : type.equations) {
            Split split = (Split) e.expression;
            split.index = type.reference.variable.container.splits.indexOf(split.parts);
        }
    }
    if (xyz != null) {
        XYZdependencies = new ArrayList<Variable>();
        XYZdependenciesTemp = new ArrayList<Variable>();
        for (Variable t : s.ordered) {
            boolean temporary = t.hasAttribute("temporary");
            if ((temporary || localMembers.contains(t)) && xyz.dependsOn(t) != null) {
                XYZdependencies.add(t);
                if (temporary)
                    XYZdependenciesTemp.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) {
        populationIndex = s.container.parts.indexOf(s);
    }
    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.allocateLocalFloat(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 (project[i].dependsOn(t) != null) {
                        dependencies.add(t);
                    }
                }
                final TreeSet<VariableReference> references = new TreeSet<VariableReference>();
                class ProjectVisitor implements 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 object array rather than the float array.
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.readIndex = v.writeIndex = allocateLocalFloat(v.nameString());
        } else {
            v.readIndex = v.writeIndex = allocateLocalObject(v.nameString());
        }
    }
    for (Variable v : localBufferedExternal) {
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = allocateLocalFloat("next_" + v.nameString());
        } else {
            v.writeIndex = allocateLocalObject("next_" + v.nameString());
        }
    }
    for (Variable v : localBufferedInternal) {
        v.writeTemp = true;
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = allocateLocalTempFloat("next_" + v.nameString());
        } else {
            v.writeIndex = allocateLocalTempObject("next_" + v.nameString());
        }
    }
    // Globals
    for (Variable v : globalMembers) {
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.readIndex = v.writeIndex = allocateGlobalFloat(v.nameString());
        } else {
            v.readIndex = v.writeIndex = allocateGlobalObject(v.nameString());
        }
    }
    for (Variable v : globalBufferedExternal) {
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = allocateGlobalFloat("next_" + v.nameString());
        } else {
            v.writeIndex = allocateGlobalObject("next_" + v.nameString());
        }
    }
    for (Variable v : globalBufferedInternal) {
        v.writeTemp = true;
        if (v.type instanceof Scalar && v.reference.variable == v) {
            v.writeIndex = allocateGlobalTempFloat("next_" + v.nameString());
        } else {
            v.writeIndex = allocateGlobalTempObject("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 = allocateGlobalTempFloat(v.nameString());
            } else {
                v.readIndex = v.writeIndex = allocateGlobalTempObject(v.nameString());
            }
        } else {
            if (v.type instanceof Scalar && v.reference.variable == v) {
                v.readIndex = v.writeIndex = allocateLocalTempFloat(v.nameString());
            } else {
                v.readIndex = v.writeIndex = allocateLocalTempObject(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);
}
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) 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) UnitValue(gov.sandia.n2a.language.UnitValue) Scalar(gov.sandia.n2a.language.type.Scalar) TreeSet(java.util.TreeSet) Output(gov.sandia.n2a.language.function.Output) EquationEntry(gov.sandia.n2a.eqset.EquationEntry) Split(gov.sandia.n2a.language.Split)

Example 3 with Split

use of gov.sandia.n2a.language.Split in project n2a by frothga.

the class EquationSet method resolveRHS.

public void resolveRHS(LinkedList<UnresolvedVariable> unresolved) {
    for (EquationSet s : parts) {
        s.resolveRHS(unresolved);
    }
    class Resolver implements Visitor {

        public Variable from;

        public LinkedList<UnresolvedVariable> unresolved;

        public String fromName() {
            String result = from.container.prefix();
            if (!result.isEmpty())
                result += ".";
            return result + from.nameString();
        }

        public boolean visit(Operator op) {
            if (op instanceof AccessVariable) {
                AccessVariable av = (AccessVariable) op;
                Variable query = new Variable(av.getName(), av.getOrder());
                VariableReference r = new VariableReference();
                query.reference = r;
                av.reference = r;
                // modifies "r" with actual resolution path
                EquationSet dest = resolveEquationSet(query, false);
                r.removeLoops();
                // dependencies from "from" to each part in the resolution path
                r.addDependencies(from);
                if (dest == null) {
                    unresolved.add(new UnresolvedVariable(av.name, fromName()));
                } else {
                    // "query" contains the modified variable name, needed for lookup within "dest"
                    r.variable = dest.find(query);
                    if (r.variable == null) {
                        if (query.hasAttribute("instance")) {
                            // Configure reference to destination container itself.
                            // Recycle the query variable as a pseudo target (one that doesn't actually exist in the container).
                            r.variable = query;
                            query.container = dest;
                            query.equations = new TreeSet<EquationEntry>();
                            query.type = new Instance();
                            // Only for use by Internal backend. It's easier to set this here than to scan for "instance" variables in InternalBackendData.analyze().
                            query.readIndex = -2;
                        } else if (// accountable endpoint
                        query.name.equals("$count")) {
                            int last = r.resolution.size() - 1;
                            Object o = null;
                            if (last >= 0)
                                o = r.resolution.get(last);
                            if (!(o instanceof ConnectionBinding)) {
                                unresolved.add(new UnresolvedVariable(av.name, fromName()));
                            } else {
                                ConnectionBinding cb = (ConnectionBinding) o;
                                if (dest.accountableConnections == null)
                                    dest.accountableConnections = new TreeSet<AccountableConnection>();
                                AccountableConnection ac = new AccountableConnection(r.penultimateContainer(EquationSet.this), cb.alias);
                                if (!dest.accountableConnections.add(ac))
                                    ac = dest.accountableConnections.floor(ac);
                                if (ac.count == null) {
                                    // Create a fully-functional variable.
                                    // However, it never gets formally added to dest, because dest should never evaluate it.
                                    // Rather, it is maintained by the backend's connection system.
                                    ac.count = new Variable(prefix() + ".$count");
                                    ac.count.type = new Scalar(0);
                                    ac.count.container = dest;
                                    ac.count.equations = new TreeSet<EquationEntry>();
                                    ac.count.reference = new VariableReference();
                                    ac.count.reference.variable = ac.count;
                                }
                                r.variable = ac.count;
                            }
                        } else {
                            unresolved.add(new UnresolvedVariable(av.name, fromName()));
                        }
                    } else {
                        from.addDependencyOn(r.variable);
                    }
                }
                return false;
            }
            if (op instanceof Split) {
                Split split = (Split) op;
                split.parts = new ArrayList<EquationSet>(split.names.length);
                EquationSet self = from.reference.variable.container;
                // Could be null, if self is top-level model.
                EquationSet family = self.container;
                for (String partName : split.names) {
                    EquationSet part;
                    if (// This allows for $type in top-level model, where no higher container is available to search in.
                    partName.equals(self.name))
                        // This allows for $type in top-level model, where no higher container is available to search in.
                        part = self;
                    else
                        part = family.findPart(partName);
                    if (part != null) {
                        split.parts.add(part);
                        Variable query = new Variable("$type");
                        Variable type = part.find(query);
                        if (type == null) {
                            type = query;
                            part.add(type);
                            // double-buffer it
                            type.addAttribute("externalWrite");
                            type.unit = AbstractUnit.ONE;
                            type.equations = new TreeSet<EquationEntry>();
                            type.reference = new VariableReference();
                            type.reference.variable = type;
                        }
                        if (type != from)
                            type.addDependencyOn(from);
                    } else {
                        unresolved.add(new UnresolvedVariable(partName, fromName()));
                    }
                }
                return false;
            }
            return true;
        }
    }
    Resolver resolver = new Resolver();
    resolver.unresolved = unresolved;
    for (Variable v : variables) {
        resolver.from = v;
        v.visit(resolver);
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) AccessVariable(gov.sandia.n2a.language.AccessVariable) Visitor(gov.sandia.n2a.language.Visitor) Instance(gov.sandia.n2a.language.type.Instance) LinkedList(java.util.LinkedList) Scalar(gov.sandia.n2a.language.type.Scalar) TreeSet(java.util.TreeSet) Split(gov.sandia.n2a.language.Split)

Example 4 with Split

use of gov.sandia.n2a.language.Split in project n2a by frothga.

the class JobC method multiconditional.

public void multiconditional(Variable v, CRenderer context, String pad) throws Exception {
    boolean init = context.part.getInit();
    boolean isType = v.name.equals("$type");
    if (v.hasAttribute("temporary"))
        context.result.append(pad + type(v) + " " + mangle(v) + ";\n");
    // Select the default equation
    EquationEntry defaultEquation = null;
    for (EquationEntry e : v.equations) {
        if (// TODO: also handle $init==1, or any other equivalent expression
        init && e.ifString.equals("$init")) {
            defaultEquation = e;
            break;
        }
        if (e.ifString.length() == 0)
            defaultEquation = e;
    }
    // Initialize static objects, and dump dynamic objects needed by conditions
    for (EquationEntry e : v.equations) {
        if (init) {
            prepareStaticObjects(e.expression, context, pad);
            if (e.condition != null)
                prepareStaticObjects(e.condition, context, pad);
        }
        if (e.condition != null)
            prepareDynamicObjects(e.condition, context, init, pad);
    }
    // Write the conditional equations
    boolean haveIf = false;
    String padIf = pad;
    for (EquationEntry e : v.equations) {
        if (e == defaultEquation)
            continue;
        if (init) {
            if (e.ifString.length() == 0)
                continue;
        } else // not init
        {
            if (e.ifString.equals("$init"))
                continue;
        }
        if (e.condition != null) {
            String ifString;
            if (haveIf) {
                ifString = "elseif (";
            } else {
                ifString = "if (";
                haveIf = true;
                padIf = pad + "  ";
            }
            context.result.append(pad + ifString);
            e.condition.render(context);
            context.result.append(")\n");
            context.result.append(pad + "{\n");
        }
        if (isType) {
            // per the N2A language document.
            if (!(e.expression instanceof Split)) {
                Backend.err.get().println("Unexpected expression for $type");
                throw new Backend.AbortRun();
            }
            int index = context.part.splits.indexOf(((Split) e.expression).parts);
            context.result.append(padIf + resolve(v.reference, context, true) + " = " + (index + 1) + ";\n");
        } else {
            prepareDynamicObjects(e.expression, context, init, pad);
            context.result.append(padIf);
            renderEquation(context, e);
        }
        if (haveIf)
            context.result.append(pad + "}\n");
    }
    // Write the default equation
    if (defaultEquation == null) {
        if (isType) {
            if (haveIf) {
                context.result.append(pad + "else\n");
                context.result.append(pad + "{\n");
            }
            // always reset $type to 0
            context.result.append(padIf + resolve(v.reference, context, true) + " = 0;\n");
            if (haveIf)
                context.result.append(pad + "}\n");
        } else {
            // to copy forward the current buffered value.
            if (v.assignment == Variable.REPLACE && v.reference.variable == v && v.equations.size() > 0 && v.hasAny("cycle", "externalRead") && !v.hasAttribute("initOnly")) {
                if (haveIf) {
                    context.result.append(pad + "else\n");
                    context.result.append(pad + "{\n");
                }
                // copy previous value
                context.result.append(padIf + resolve(v.reference, context, true) + " = " + resolve(v.reference, context, false) + ";\n");
                if (haveIf)
                    context.result.append(pad + "}\n");
            }
        }
    } else {
        if (haveIf) {
            context.result.append(pad + "else\n");
            context.result.append(pad + "{\n");
        }
        if (isType) {
            ArrayList<EquationSet> split = ((Split) defaultEquation.expression).parts;
            int index = context.part.splits.indexOf(split);
            context.result.append(padIf + resolve(v.reference, context, true) + " = " + (index + 1) + ";\n");
        } else {
            prepareDynamicObjects(defaultEquation.expression, context, init, pad);
            context.result.append(padIf);
            renderEquation(context, defaultEquation);
        }
        if (haveIf)
            context.result.append(pad + "}\n");
    }
}
Also used : EquationSet(gov.sandia.n2a.eqset.EquationSet) EquationEntry(gov.sandia.n2a.eqset.EquationEntry) Split(gov.sandia.n2a.language.Split) AbortRun(gov.sandia.n2a.plugins.extpoints.Backend.AbortRun)

Example 5 with Split

use of gov.sandia.n2a.language.Split in project n2a by frothga.

the class EquationSet method collectSplits.

/**
 *        Scans all conditional forms of $type, and stores the patterns in the splits field.
 *        Depends on results of: resolveLHS(), resolveRHS()
 */
public void collectSplits() {
    for (EquationSet s : parts) {
        s.collectSplits();
    }
    if (splits == null)
        splits = new ArrayList<ArrayList<EquationSet>>();
    if (splitSources == null)
        splitSources = new HashSet<EquationSet>();
    for (Variable v : variables) {
        // The actual variable. It is possible for an equation in one part to indicate a type split in another part.
        Variable type = v.reference.variable;
        if (!type.name.equals("$type"))
            continue;
        EquationSet container = type.container;
        if (// in case we are referencing $type in another equation set that has not yet been processed
        container.splits == null) {
            container.splits = new ArrayList<ArrayList<EquationSet>>();
        }
        for (EquationEntry e : v.equations) {
            if (!(e.expression instanceof Split)) {
                Backend.err.get().println("Unexpected expression for $type");
                throw new Backend.AbortRun();
            }
            ArrayList<EquationSet> split = ((Split) e.expression).parts;
            if (!container.splits.contains(split)) {
                container.splits.add(split);
                for (EquationSet t : split) {
                    if (t.splitSources == null)
                        t.splitSources = new HashSet<EquationSet>();
                    t.splitSources.add(container);
                }
            }
        }
    }
}
Also used : AccessVariable(gov.sandia.n2a.language.AccessVariable) ArrayList(java.util.ArrayList) Split(gov.sandia.n2a.language.Split) AbortRun(gov.sandia.n2a.plugins.extpoints.Backend.AbortRun) HashSet(java.util.HashSet)

Aggregations

Split (gov.sandia.n2a.language.Split)6 AccessVariable (gov.sandia.n2a.language.AccessVariable)4 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)3 Operator (gov.sandia.n2a.language.Operator)3 Scalar (gov.sandia.n2a.language.type.Scalar)3 AbortRun (gov.sandia.n2a.plugins.extpoints.Backend.AbortRun)3 TreeSet (java.util.TreeSet)3 EquationSet (gov.sandia.n2a.eqset.EquationSet)2 Visitor (gov.sandia.n2a.language.Visitor)2 ArrayList (java.util.ArrayList)2 LinkedList (java.util.LinkedList)2 AccountableConnection (gov.sandia.n2a.eqset.EquationSet.AccountableConnection)1 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)1 Variable (gov.sandia.n2a.eqset.Variable)1 VariableReference (gov.sandia.n2a.eqset.VariableReference)1 Transformer (gov.sandia.n2a.language.Transformer)1 UnitValue (gov.sandia.n2a.language.UnitValue)1 Output (gov.sandia.n2a.language.function.Output)1 Instance (gov.sandia.n2a.language.type.Instance)1 ExtensionPoint (gov.sandia.n2a.plugins.ExtensionPoint)1