Search in sources :

Example 1 with EvaluationException

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

the class InternalBackendData method analyze.

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

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

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

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

Example 2 with EvaluationException

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

the class InternalBackendData method translateResolution.

/**
 *         Convert resolution to a form that can be processed quickly at runtime.
 */
public ArrayList<Object> translateResolution(ArrayList<Object> resolution, EquationSet current) {
    ArrayList<Object> newResolution = new ArrayList<Object>();
    Iterator<Object> it = resolution.iterator();
    while (it.hasNext()) {
        Object o = it.next();
        if (// We are following the containment hierarchy.
        o instanceof EquationSet) {
            EquationSet next = (EquationSet) o;
            if (// ascend to our container
            next == current.container) {
                newResolution.add(new ResolveContainer());
            } else // descend to one of our contained populations
            {
                int i = 0;
                for (EquationSet p : current.parts) {
                    if (p == next) {
                        newResolution.add(new ResolvePart(i));
                        break;
                    }
                    i++;
                }
                if (i >= current.parts.size())
                    throw new EvaluationException("Could not find connection target.");
            }
            current = next;
        } else if (// We are following a part reference, which means "current" is a connection.
        o instanceof ConnectionBinding) {
            ConnectionBinding c = (ConnectionBinding) o;
            InternalBackendData bed = (InternalBackendData) current.backendData;
            newResolution.add(new ResolvePart(bed.endpoints + c.index));
            current = c.endpoint;
        }
    }
    return newResolution;
}
Also used : EquationSet(gov.sandia.n2a.eqset.EquationSet) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) ArrayList(java.util.ArrayList) EvaluationException(gov.sandia.n2a.language.EvaluationException)

Example 3 with EvaluationException

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

the class Matrix method NOT.

public Type NOT() throws EvaluationException {
    int w = columns();
    int h = rows();
    // should create pseudo-inverse
    if (h != w)
        throw new EvaluationException("Can't invert non-square matrix (because we don't know about pseudo-inverse).");
    if (h == 1)
        return new Scalar(1 / get(0, 0));
    if (h == 2) {
        MatrixDense result = new MatrixDense(2, 2);
        double q = determinant();
        if (q == 0)
            throw new EvaluationException("invert: Matrix is singular!");
        result.value[0][0] = get(1, 1) / q;
        result.value[0][1] = get(1, 0) / -q;
        result.value[1][0] = get(0, 1) / -q;
        result.value[1][1] = get(0, 0) / q;
        return result;
    }
    if (h == 3) {
        MatrixDense result = new MatrixDense(3, 3);
        double q = determinant();
        if (q == 0)
            throw new EvaluationException("invert: Matrix is singular!");
        result.value[0][0] = det22(1, 2, 1, 2) / q;
        result.value[0][1] = det22(1, 2, 2, 0) / q;
        result.value[0][2] = det22(1, 2, 0, 1) / q;
        result.value[1][0] = det22(0, 2, 2, 1) / q;
        result.value[1][1] = det22(0, 2, 0, 2) / q;
        result.value[1][2] = det22(0, 2, 1, 0) / q;
        result.value[2][0] = det22(0, 1, 1, 2) / q;
        result.value[2][1] = det22(0, 1, 2, 0) / q;
        result.value[2][2] = det22(0, 1, 0, 1) / q;
        return result;
    }
    throw new EvaluationException("Can't invert matrices larger then 3x3 (because we are not using a good numerical library).");
}
Also used : EvaluationException(gov.sandia.n2a.language.EvaluationException)

Example 4 with EvaluationException

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

the class MatrixDense method load.

public void load(Reader stream, boolean units) throws EvaluationException {
    try {
        ArrayList<ArrayList<Double>> temp = new ArrayList<ArrayList<Double>>();
        ArrayList<Double> row = new ArrayList<Double>();
        int columns = 0;
        boolean transpose = false;
        // Scan for opening "["
        char token;
        do {
            token = (char) stream.read();
            if (token == '~')
                transpose = true;
        } while (token != '[' && stream.ready());
        // Read rows until closing "]"
        // for one floating-point number, so far more than enough
        char[] buffer = new char[1024];
        int index = 0;
        boolean done = false;
        while (stream.ready() && !done) {
            token = (char) stream.read();
            switch(token) {
                case '\r':
                    // ignore CR characters
                    break;
                case ' ':
                case '\t':
                    // ignore leading whitespace (equivalent to trim)
                    if (index == 0)
                        break;
                case ',':
                    // Process element
                    if (index == 0) {
                        row.add(0.0);
                    } else {
                        String value = String.valueOf(buffer, 0, index);
                        index = 0;
                        if (units)
                            row.add(Scalar.convert(value));
                        else
                            row.add(Double.valueOf(value));
                    }
                    break;
                case ']':
                    done = true;
                case ';':
                case '\n':
                    // Process any final element
                    if (index > 0) {
                        String value = String.valueOf(buffer, 0, index);
                        index = 0;
                        if (units)
                            row.add(Scalar.convert(value));
                        else
                            row.add(Double.valueOf(value));
                    }
                    // Process line
                    int c = row.size();
                    if (c > 0) {
                        temp.add(row);
                        columns = Math.max(columns, c);
                        row = new ArrayList<Double>(columns);
                    }
                    break;
                default:
                    // If we overrun the buffer, we should automatically get an index out of range error.
                    buffer[index++] = token;
            }
        }
        // Assign elements to "value"
        int rows = temp.size();
        if (transpose) {
            value = new double[rows][columns];
            for (int r = 0; r < rows; r++) {
                row = temp.get(r);
                for (int c = 0; c < row.size(); c++) {
                    value[r][c] = row.get(c);
                }
            }
        } else {
            value = new double[columns][rows];
            for (int r = 0; r < rows; r++) {
                row = temp.get(r);
                for (int c = 0; c < row.size(); c++) {
                    value[c][r] = row.get(c);
                }
            }
        }
        if (value.length == 0 || value[1].length == 0)
            throw new EvaluationException("Empty matrix");
    } catch (IOException error) {
        throw new EvaluationException("Failed to convert input to matrix");
    }
}
Also used : ArrayList(java.util.ArrayList) EvaluationException(gov.sandia.n2a.language.EvaluationException) IOException(java.io.IOException)

Example 5 with EvaluationException

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

the class MatrixDense method determinant.

public double determinant() throws EvaluationException {
    int w = value.length;
    int h = value[0].length;
    if (h != w)
        throw new EvaluationException("Can't compute determinant of non-square matrix.");
    if (h == 1)
        return value[0][0];
    if (h == 2)
        return value[0][0] * value[1][1] - value[0][1] * value[1][0];
    if (h == 3) {
        return value[0][0] * value[1][1] * value[2][2] - value[0][0] * value[2][1] * value[1][2] - value[1][0] * value[0][1] * value[2][2] + value[1][0] * value[2][1] * value[0][2] + value[2][0] * value[0][1] * value[1][2] - value[2][0] * value[1][1] * value[0][2];
    }
    throw new EvaluationException("Can't compute deteminant of matrices larger then 3x3 (because we are lazy).");
}
Also used : EvaluationException(gov.sandia.n2a.language.EvaluationException)

Aggregations

EvaluationException (gov.sandia.n2a.language.EvaluationException)7 ArrayList (java.util.ArrayList)3 EquationSet (gov.sandia.n2a.eqset.EquationSet)2 ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)2 IOException (java.io.IOException)2 AccountableConnection (gov.sandia.n2a.eqset.EquationSet.AccountableConnection)1 Variable (gov.sandia.n2a.eqset.Variable)1 VariableReference (gov.sandia.n2a.eqset.VariableReference)1 AccessVariable (gov.sandia.n2a.language.AccessVariable)1 Operator (gov.sandia.n2a.language.Operator)1 Visitor (gov.sandia.n2a.language.Visitor)1 Output (gov.sandia.n2a.language.function.Output)1 Scalar (gov.sandia.n2a.language.type.Scalar)1 BufferedReader (java.io.BufferedReader)1 TreeSet (java.util.TreeSet)1