Search in sources :

Example 1 with Divide

use of gov.sandia.n2a.language.operator.Divide in project n2a by frothga.

the class Device method getDefinition.

// / Writes an instance-specific use of an internal device.
public String getDefinition(XyceRenderer renderer) {
    StringBuilder result = new StringBuilder();
    // Nodes that this device connects to
    List<String> nodeNames = new ArrayList<String>();
    for (int i = 0; i < varnames.size(); i++) {
        Variable v = varnames.get(i);
        if (v == ground) {
            nodeNames.add("0");
        } else if (v != empty) {
            nodeNames.add(getInstanceVarname(v.reference, renderer.pi));
        }
    }
    // Its specific parameter values will be based on first written part.
    if (model == null) {
        model = new HashMap<String, String>();
        for (Entry<String, Variable> p : paramList.entrySet()) {
            // TODO: select() can return null. Should we guard against it?
            model.put(p.getKey(), renderer.change(p.getValue().select(renderer.pi).expression));
        }
        result.append(Xyceisms.defineModel(device.getDeviceTypeName(), device.getDeviceLevel(), modelName, model));
    }
    // Instance-specific parameters that override model
    Map<String, String> instanceParams = new HashMap<String, String>();
    for (Entry<String, Variable> p : paramList.entrySet()) {
        Variable v = p.getValue();
        if (v.global)
            continue;
        String name = p.getKey();
        // TODO: select() can return null. Should we guard against it?
        String value = renderer.change(v.select(renderer.pi).expression);
        // no need to override model parameter if value is exactly the same
        if (model.get(name).equals(value))
            continue;
        instanceParams.put(name, value);
    }
    result.append(Xyceisms.defineYDeviceWithModel(device.getDeviceTypeName(), eqSet.name, nodeNames, renderer.pi.hashCode(), modelName, instanceParams));
    // Define inputs
    for (Integer inputNode : inputs.keySet()) {
        // Write a B device definition to update the node associated with the input
        // For neurons, this assumes we want to add a current of the form I/C_m
        // where the user specifies I and C_m is known.
        // Not at all clear what it means to add current to synapse, which doesn't
        // have a capacitance of its own, but this will allow adding a user-defined
        // current I to a synapse node.
        Variable v = inputs.get(inputNode);
        AccessVariable av = new AccessVariable(v.reference);
        Operator inputEq;
        if (device.getDeviceTypeName().equals("neuron")) {
            Divide d = new Divide();
            d.operand0 = av;
            av = new AccessVariable(paramList.get(device.getCapacitanceVar()).reference);
            d.operand1 = av;
            inputEq = d;
        } else {
            inputEq = av;
        }
        String eqName = Xyceisms.referenceVariable(v.name, renderer.pi.hashCode());
        String instanceVarName = getInstanceVarname(v.reference, renderer.pi);
        result.append(Xyceisms.updateDiffEq(eqName, instanceVarName, renderer.change(inputEq)));
    }
    return result.toString();
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) Variable(gov.sandia.n2a.eqset.Variable) AccessVariable(gov.sandia.n2a.language.AccessVariable) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Divide(gov.sandia.n2a.language.operator.Divide)

Example 2 with Divide

use of gov.sandia.n2a.language.operator.Divide in project n2a by frothga.

the class Variable method flattenExpressions.

public void flattenExpressions(Variable v) {
    if (assignment != v.assignment && !(// This line and the next say that * and / are compatible with each other, so ignore that case.
    (assignment == MULTIPLY && v.assignment == DIVIDE) || (assignment == DIVIDE && v.assignment == MULTIPLY))) {
        Backend.err.get().println("WARNING: Flattened variable " + v.container.prefix() + "." + v.nameString() + " has different combining operator than target (" + container.prefix() + "." + nameString() + "). Resolving in favor of higher-precedence operator.");
        v.assignment = assignment = Math.max(v.assignment, assignment);
    }
    if (v.assignment == REPLACE) {
        // We want equations from the lower level to override any pre-existing equations in the upper level.
        // Why? Because the lower-level equations represent an elaboration of the model, and are thus more specific.
        // Note that Internal executes contained populations after the upper-level equations, so the contained
        // populations take precedence even without flattening.
        NavigableSet<EquationEntry> equations0 = equations;
        equations = new TreeSet<EquationEntry>();
        // First add the lower-level equations, so they take precedence.
        for (EquationEntry e2 : v.equations) add(e2);
        for (EquationEntry e0 : equations0) add(e0);
    } else {
        // For combiners, it is necessary to create new equations for every combination of conditions.
        // Of course, unconditional equations and equations with matching conditions can be combined more directly.
        // First step is to augment both equation sets with an unconditional form, if they lack it.
        EquationEntry query = new EquationEntry(this, "");
        EquationEntry e = find(query);
        // expression and condition are null; we deal with this below
        if (e == null)
            add(query);
        query = new EquationEntry(v, "");
        e = v.find(query);
        if (e == null)
            v.add(query);
        NavigableSet<EquationEntry> equations0 = equations;
        equations = new TreeSet<EquationEntry>();
        for (EquationEntry e0 : equations0) {
            for (EquationEntry e1 : v.equations) {
                if (// Condition strings are exactly the same. TODO: compare ASTs for actual logic equivalence.
                e0.compareTo(e1) == 0) {
                    e = new EquationEntry(this, "");
                    e.condition = e0.condition;
                } else if (e0.condition == null) {
                    // If so, then only those equations should be merged, so skip this one.
                    if (find(e1) != null)
                        continue;
                    e = new EquationEntry(this, "");
                    e.condition = e1.condition;
                } else if (e1.condition == null) {
                    // Check if e0.condition exists in v.equations
                    if (v.find(e0) != null)
                        continue;
                    e = new EquationEntry(this, "");
                    e.condition = e0.condition;
                } else {
                    e = new EquationEntry(this, "");
                    AND and = new AND();
                    e.condition = and;
                    and.operand0 = e0.condition;
                    and.operand1 = e1.condition;
                }
                if (e.condition != null)
                    e.ifString = e.condition.render();
                // merge expressions
                if (e0.expression == null) {
                    // which could also be null
                    e.expression = e1.expression;
                } else if (e1.expression == null) {
                    e.expression = e0.expression;
                } else // Both expressions exist
                {
                    OperatorBinary op = null;
                    Function f = null;
                    switch(v.assignment) {
                        case ADD:
                            op = new Add();
                            break;
                        case MULTIPLY:
                            op = new Multiply();
                            break;
                        case DIVIDE:
                            op = new Divide();
                            break;
                        case MIN:
                            f = new Min();
                            break;
                        case MAX:
                            f = new Max();
                            break;
                    }
                    if (op != null) {
                        op.operand0 = e0.expression;
                        op.operand1 = e1.expression;
                        e.expression = op;
                    } else if (f != null) {
                        f.operands[0] = e0.expression;
                        f.operands[1] = e1.expression;
                        e.expression = f;
                    }
                }
                if (e.expression != null)
                    equations.add(e);
            }
        }
    }
    v.equations.clear();
}
Also used : Add(gov.sandia.n2a.language.operator.Add) Function(gov.sandia.n2a.language.Function) Divide(gov.sandia.n2a.language.operator.Divide) Min(gov.sandia.n2a.language.function.Min) Max(gov.sandia.n2a.language.function.Max) AND(gov.sandia.n2a.language.operator.AND) Multiply(gov.sandia.n2a.language.operator.Multiply) OperatorBinary(gov.sandia.n2a.language.OperatorBinary)

Aggregations

Divide (gov.sandia.n2a.language.operator.Divide)2 Variable (gov.sandia.n2a.eqset.Variable)1 AccessVariable (gov.sandia.n2a.language.AccessVariable)1 Function (gov.sandia.n2a.language.Function)1 Operator (gov.sandia.n2a.language.Operator)1 OperatorBinary (gov.sandia.n2a.language.OperatorBinary)1 Max (gov.sandia.n2a.language.function.Max)1 Min (gov.sandia.n2a.language.function.Min)1 AND (gov.sandia.n2a.language.operator.AND)1 Add (gov.sandia.n2a.language.operator.Add)1 Multiply (gov.sandia.n2a.language.operator.Multiply)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1