Search in sources :

Example 1 with Operator

use of gov.sandia.n2a.language.Operator 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 Operator

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

the class JobC method generateStatic.

public void generateStatic(final EquationSet s, final StringBuilder result) {
    for (EquationSet p : s.parts) generateStatic(p, result);
    // Generate static definitions
    final BackendDataC bed = (BackendDataC) s.backendData;
    class CheckStatic extends Visitor {

        public boolean global;

        public boolean visit(Operator op) {
            if (op instanceof Constant) {
                Type m = ((Constant) op).value;
                if (m instanceof Matrix) {
                    Matrix A = (Matrix) m;
                    int rows = A.rows();
                    int cols = A.columns();
                    String matrixName = "Matrix" + matrixNames.size();
                    matrixNames.put(op, matrixName);
                    if (rows == 3 && cols == 1)
                        result.append("Vector3 " + matrixName + " = Matrix<float>");
                    else
                        result.append("Matrix<float> " + matrixName);
                    result.append(" (\"" + A + "\");\n");
                }
                // Don't try to descend tree from here
                return false;
            }
            if (op instanceof Function) {
                Function f = (Function) op;
                if (// We need to auto-generate the column name.
                f instanceof Output && f.operands.length < 3) {
                    String stringName = "columnName" + stringNames.size();
                    stringNames.put(op, stringName);
                    if (global) {
                        bed.setGlobalNeedPath(s);
                        bed.globalColumns.add(stringName);
                    } else {
                        bed.setLocalNeedPath(s);
                        bed.localColumns.add(stringName);
                    }
                }
                // Detect functions that need static handles
                if (f.operands.length > 0) {
                    Operator operand0 = f.operands[0];
                    if (operand0 instanceof Constant) {
                        Constant c = (Constant) operand0;
                        Type o = c.value;
                        if (o instanceof Text) {
                            String fileName = ((Text) o).value;
                            if (op instanceof ReadMatrix) {
                                if (!matrixNames.containsKey(fileName)) {
                                    String matrixName = "Matrix" + matrixNames.size();
                                    matrixNames.put(fileName, matrixName);
                                    result.append("MatrixInput * " + matrixName + " = matrixHelper (\"" + fileName + "\");\n");
                                }
                            } else if (f instanceof Input) {
                                if (!inputNames.containsKey(fileName)) {
                                    String inputName = "Input" + inputNames.size();
                                    inputNames.put(fileName, inputName);
                                    result.append("InputHolder * " + inputName + " = inputHelper (\"" + fileName + "\");\n");
                                }
                            } else if (f instanceof Output) {
                                if (!outputNames.containsKey(fileName)) {
                                    String outputName = "Output" + outputNames.size();
                                    outputNames.put(fileName, outputName);
                                    result.append("OutputHolder * " + outputName + " = outputHelper (\"" + fileName + "\");\n");
                                }
                            }
                        }
                    } else // Dynamic file name (no static handle)
                    {
                        if (f instanceof ReadMatrix) {
                            matrixNames.put(op, "Matrix" + matrixNames.size());
                            stringNames.put(operand0, "fileName" + stringNames.size());
                        } else if (f instanceof Input) {
                            inputNames.put(op, "Input" + inputNames.size());
                            stringNames.put(operand0, "fileName" + stringNames.size());
                        } else if (f instanceof Output) {
                            outputNames.put(op, "Output" + outputNames.size());
                            stringNames.put(operand0, "fileName" + stringNames.size());
                        }
                    }
                }
                // Functions could be nested, so continue descent.
                return true;
            }
            return true;
        }
    }
    CheckStatic checkStatic = new CheckStatic();
    for (Variable v : s.ordered) {
        checkStatic.global = v.hasAttribute("global");
        v.visit(checkStatic);
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) EquationSet(gov.sandia.n2a.eqset.EquationSet) Variable(gov.sandia.n2a.eqset.Variable) AccessVariable(gov.sandia.n2a.language.AccessVariable) Visitor(gov.sandia.n2a.language.Visitor) Constant(gov.sandia.n2a.language.Constant) Text(gov.sandia.n2a.language.type.Text) ReadMatrix(gov.sandia.n2a.language.function.ReadMatrix) Function(gov.sandia.n2a.language.Function) Type(gov.sandia.n2a.language.Type) Input(gov.sandia.n2a.language.function.Input) ReadMatrix(gov.sandia.n2a.language.function.ReadMatrix) BuildMatrix(gov.sandia.n2a.language.BuildMatrix) Matrix(gov.sandia.n2a.language.type.Matrix) Output(gov.sandia.n2a.language.function.Output)

Example 3 with Operator

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

the class InternalBackendData method analyzeEvents.

public static void analyzeEvents(final EquationSet s, final List<EventTarget> eventTargets, final List<Variable> eventReferences) {
    class EventVisitor extends Visitor {

        public boolean found;

        public boolean visit(Operator op) {
            if (op instanceof Event) {
                found = true;
                Event de = (Event) op;
                if (// this event has not yet been analyzed
                de.eventType == null) {
                    final EventTarget et = new EventTarget(de);
                    int targetIndex = eventTargets.indexOf(et);
                    if (// event target already exists
                    targetIndex >= 0) {
                        de.eventType = eventTargets.get(targetIndex);
                    } else // we must create a new event target, or more properly, fill in the event target we just used as a query object
                    {
                        // Create an entry and save the index
                        targetIndex = eventTargets.size();
                        eventTargets.add(et);
                        de.eventType = et;
                        et.container = s;
                        // Determine edge type
                        if (de.operands.length < 3) {
                            et.edge = EventTarget.RISE;
                        } else if (de.operands[2] instanceof Constant) {
                            Constant c = (Constant) de.operands[2];
                            if (c.value instanceof Text) {
                                Text t = (Text) c.value;
                                if (t.value.equalsIgnoreCase("nonzero"))
                                    et.edge = EventTarget.NONZERO;
                                else if (t.value.equalsIgnoreCase("change"))
                                    et.edge = EventTarget.CHANGE;
                                else if (t.value.equalsIgnoreCase("fall"))
                                    et.edge = EventTarget.FALL;
                                else
                                    et.edge = EventTarget.RISE;
                            } else {
                                Backend.err.get().println("ERROR: event() edge type must be a string.");
                                throw new Backend.AbortRun();
                            }
                        } else {
                            Backend.err.get().println("ERROR: event() edge type must be constant.");
                            throw new Backend.AbortRun();
                        }
                        // Allocate auxiliary variable
                        if (de.operands[0] instanceof AccessVariable) {
                            AccessVariable av = (AccessVariable) de.operands[0];
                            VariableReference reference = av.reference;
                            Variable v = reference.variable;
                            // then the user has broken the rule that we can't see temporaries in other parts.
                            if (v.hasAttribute("temporary") && v.container != s) {
                                Backend.err.get().println("WARNING: Cannot be temporary due to event monitor: " + v.container.name + "." + v.nameString() + " from " + s.name);
                                v.removeAttribute("temporary");
                            }
                            // so fall through to the !trackOne case below.
                            if (!v.hasAttribute("temporary")) {
                                // ensure it's buffered, so we can detect change
                                v.addAttribute("externalRead");
                                et.trackOne = true;
                                // just a holder for the reference
                                et.track = new Variable();
                                et.track.reference = reference;
                            }
                        }
                        if (// Expression, so create auxiliary variable. Aux not needed for NONZERO, because no change detection.
                        !et.trackOne && et.edge != EventTarget.NONZERO) {
                            et.track = new Variable("eventAux" + targetIndex, 0);
                            et.track.type = new Scalar(0);
                            et.track.reference = new VariableReference();
                            et.track.reference.variable = et.track;
                        }
                        // Locate any temporaries for evaluation. TODO: for more efficiency, we could have separate lists of temporaries for the condition and delay operands
                        // Tie into the dependency graph using a phantom variable (which can go away afterward without damaging the graph).
                        final Variable phantom = new Variable("event");
                        phantom.uses = new IdentityHashMap<Variable, Integer>();
                        for (int i = 0; i < et.event.operands.length; i++) et.event.operands[i].visit(new Visitor() {

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    Variable v = av.reference.variable;
                                    if (!phantom.uses.containsKey(v))
                                        phantom.uses.put(v, 1);
                                    return false;
                                }
                                return true;
                            }
                        });
                        // Scan all variables in equation set to see if we need them
                        for (Variable t : s.variables) {
                            if (t.hasAttribute("temporary") && phantom.dependsOn(t) != null)
                                et.dependencies.add(t);
                        }
                        // Note the default is already set to -1 (no care)
                        class DelayVisitor extends Visitor {

                            TreeSet<EquationSet> containers = new TreeSet<EquationSet>();

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    // could include the target part itself, if in fact we use local variables
                                    containers.add(av.reference.variable.container);
                                    return false;
                                }
                                return true;
                            }
                        }
                        DelayVisitor dv = new DelayVisitor();
                        if (de.operands.length >= 2) {
                            if (de.operands[1] instanceof Constant) {
                                Constant c = (Constant) de.operands[1];
                                et.delay = (float) ((Scalar) c.value).value;
                                if (et.delay < 0)
                                    et.delay = -1;
                            } else {
                                // indicates that we need to evaluate delay at run time
                                et.delay = -2;
                                de.operands[1].visit(dv);
                            }
                        }
                        // Set up monitors in source parts
                        class ConditionVisitor extends Visitor {

                            TreeSet<EquationSet> containers = new TreeSet<EquationSet>();

                            public boolean visit(Operator op) {
                                if (op instanceof AccessVariable) {
                                    AccessVariable av = (AccessVariable) op;
                                    Variable v = av.reference.variable;
                                    EquationSet sourceContainer = v.container;
                                    containers.add(sourceContainer);
                                    // Set up monitors for values that can vary during update.
                                    if (!v.hasAttribute("constant") && !v.hasAttribute("initOnly") && !et.monitors(sourceContainer)) {
                                        EventSource es = new EventSource(sourceContainer, et);
                                        // null means self-reference, a special case handled in Part
                                        if (sourceContainer != s)
                                            es.reference = av.reference;
                                        et.sources.add(es);
                                    }
                                    return false;
                                }
                                return true;
                            }
                        }
                        ConditionVisitor cv = new ConditionVisitor();
                        de.operands[0].visit(cv);
                        // Special case for event with no references that vary
                        if (et.sources.isEmpty()) {
                            // We can avoid creating a self monitor if we know for certain that the event will never fire
                            boolean neverFires = false;
                            if (de.operands[0] instanceof Constant) {
                                if (et.edge == EventTarget.NONZERO) {
                                    Type op0 = ((Constant) de.operands[0]).value;
                                    if (op0 instanceof Scalar) {
                                        neverFires = ((Scalar) op0).value == 0;
                                    } else {
                                        Backend.err.get().println("ERROR: Condition for event() must resolve to a number.");
                                        throw new Backend.AbortRun();
                                    }
                                } else {
                                    neverFires = true;
                                }
                            }
                            if (!neverFires) {
                                EventSource es = new EventSource(s, et);
                                // This is a self-reference, so es.reference should be null.
                                et.sources.add(es);
                            }
                        }
                        // Determine if monitor needs to test every target, or if one representative target is sufficient
                        for (EventSource source : et.sources) {
                            // associated with any given source instance, so every target must be evaluated separately.
                            if (cv.containers.size() > 1)
                                source.testEach = true;
                            if (dv.containers.size() > 1 || (dv.containers.size() == 1 && dv.containers.first() != source.container))
                                source.delayEach = true;
                        }
                    }
                }
            }
            return true;
        }
    }
    EventVisitor eventVisitor = new EventVisitor();
    for (Variable v : s.variables) {
        eventVisitor.found = false;
        v.visit(eventVisitor);
        if ((eventVisitor.found || v.dependsOnEvent()) && v.reference.variable != v)
            eventReferences.add(v);
    }
}
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) Constant(gov.sandia.n2a.language.Constant) Scalar(gov.sandia.n2a.language.type.Scalar) TreeSet(java.util.TreeSet) EquationSet(gov.sandia.n2a.eqset.EquationSet) AccessVariable(gov.sandia.n2a.language.AccessVariable) VariableReference(gov.sandia.n2a.eqset.VariableReference) Text(gov.sandia.n2a.language.type.Text) Backend(gov.sandia.n2a.plugins.extpoints.Backend) Type(gov.sandia.n2a.language.Type) Event(gov.sandia.n2a.language.function.Event)

Example 4 with Operator

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

the class Max method simplify.

public Operator simplify(Variable from) {
    Operator result = super.simplify(from);
    if (result != this)
        return result;
    // Check if Max appears as an operand. If so, merge its operands into ours
    ArrayList<Operator> newOperands = new ArrayList<Operator>(operands.length);
    boolean changed = false;
    for (int i = 0; i < operands.length; i++) {
        Operator o = operands[i];
        if (o instanceof Max) {
            Max m = (Max) o;
            newOperands.addAll(Arrays.asList(m.operands));
            changed = true;
        } else {
            newOperands.add(o);
        }
    }
    if (changed) {
        from.changed = true;
        Max newMax = new Max();
        newMax.operands = newOperands.toArray(new Operator[0]);
        return result;
    }
    return this;
}
Also used : Operator(gov.sandia.n2a.language.Operator) ArrayList(java.util.ArrayList)

Example 5 with Operator

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

the class AND method simplify.

public Operator simplify(Variable from) {
    Operator result = super.simplify(from);
    if (result != this)
        return result;
    if (operand0 instanceof Constant) {
        Type c0 = ((Constant) operand0).value;
        if (c0 instanceof Scalar) {
            from.changed = true;
            double value = ((Scalar) c0).value;
            if (value == 0) {
                operand1.releaseDependencies(from);
                return new Constant(new Scalar(0));
            }
            return operand1;
        }
    } else if (operand1 instanceof Constant) {
        Type c1 = ((Constant) operand1).value;
        if (c1 instanceof Scalar) {
            from.changed = true;
            double value = ((Scalar) c1).value;
            if (value == 0) {
                operand0.releaseDependencies(from);
                return new Constant(new Scalar(0));
            }
            return operand0;
        }
    }
    return this;
}
Also used : Operator(gov.sandia.n2a.language.Operator) Type(gov.sandia.n2a.language.Type) Constant(gov.sandia.n2a.language.Constant) Scalar(gov.sandia.n2a.language.type.Scalar)

Aggregations

Operator (gov.sandia.n2a.language.Operator)104 AccessVariable (gov.sandia.n2a.language.AccessVariable)41 Constant (gov.sandia.n2a.language.Constant)37 Visitor (gov.sandia.n2a.language.Visitor)26 Variable (gov.sandia.n2a.eqset.Variable)17 ArrayList (java.util.ArrayList)16 Type (gov.sandia.n2a.language.Type)14 Scalar (gov.sandia.n2a.language.type.Scalar)14 Output (gov.sandia.n2a.language.function.Output)13 EquationSet (gov.sandia.n2a.eqset.EquationSet)12 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)10 Input (gov.sandia.n2a.language.function.Input)10 Text (gov.sandia.n2a.language.type.Text)10 Matrix (gov.sandia.n2a.language.type.Matrix)9 TreeSet (java.util.TreeSet)9 ReadMatrix (gov.sandia.n2a.language.function.ReadMatrix)8 Add (gov.sandia.n2a.language.operator.Add)8 BuildMatrix (gov.sandia.n2a.language.BuildMatrix)7 Event (gov.sandia.n2a.language.function.Event)7 Instance (gov.sandia.n2a.language.type.Instance)7