Search in sources :

Example 1 with ConnectionMatrix

use of gov.sandia.n2a.eqset.EquationSet.ConnectionMatrix in project n2a by frothga.

the class JobC method generateDefinitionsLocal.

public void generateDefinitionsLocal(RendererC context) throws Exception {
    EquationSet s = context.part;
    BackendDataC bed = context.bed;
    StringBuilder result = context.result;
    context.global = false;
    String ns = prefix(s) + "::";
    // Unit ctor
    if (bed.needLocalCtor) {
        result.append(ns + prefix(s) + " ()\n");
        result.append("{\n");
        if (bed.needLocalDerivative) {
            result.append("  stackDerivative = 0;\n");
        }
        if (bed.needLocalPreserve) {
            result.append("  preserve = 0;\n");
        }
        for (EquationSet p : s.parts) {
            result.append("  " + mangle(p.name) + ".container = this;\n");
            BackendDataC pbed = (BackendDataC) p.backendData;
            if (pbed.singleton) {
                result.append("  " + mangle(p.name) + ".instance.container = this;\n");
            }
        }
        if (s.accountableConnections != null) {
            for (EquationSet.AccountableConnection ac : s.accountableConnections) {
                result.append("  int " + prefix(ac.connection) + "_" + mangle(ac.alias) + "_count = 0;\n");
            }
        }
        if (bed.refcount) {
            result.append("  refcount = 0;\n");
        }
        if (bed.index != null) {
            // -1 indicates that an index needs to be assigned. This should only be done once.
            result.append("  __24index = -1;\n");
        }
        if (bed.localMembers.size() > 0) {
            result.append("  clear ();\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit dtor
    if (bed.needLocalDtor) {
        result.append(ns + "~" + prefix(s) + " ()\n");
        result.append("{\n");
        if (bed.needLocalDerivative) {
            result.append("  while (stackDerivative)\n");
            result.append("  {\n");
            result.append("    Derivative * temp = stackDerivative;\n");
            result.append("    stackDerivative = stackDerivative->next;\n");
            result.append("    delete temp;\n");
            result.append("  }\n");
        }
        if (bed.needLocalPreserve) {
            result.append("  if (preserve) delete preserve;\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit clear
    if (bed.localMembers.size() > 0) {
        result.append("void " + ns + "clear ()\n");
        result.append("{\n");
        for (Variable v : bed.localMembers) {
            result.append("  " + zero(mangle(v), v) + ";\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit setPeriod
    if (// instance of top-level population, so set period on wrapper whenever our period changes
    s.container == null) {
        result.append("void " + ns + "setPeriod (" + T + " dt)\n");
        result.append("{\n");
        result.append("  PartTime<" + T + ">::setPeriod (dt);\n");
        result.append("  if (container->visitor->event != visitor->event) container->setPeriod (dt);\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit die
    if (bed.needLocalDie) {
        result.append("void " + ns + "die ()\n");
        result.append("{\n");
        if (s.metadata.getFlag("backend", "all", "fastExit")) {
            result.append("  Simulator<" + T + ">::instance.stop = true;\n");
        } else {
            // tag part as dead
            if (// $live is stored in this part
            bed.liveFlag >= 0) {
                result.append("  flags &= ~((" + bed.localFlagType + ") 0x1 << " + bed.liveFlag + ");\n");
            }
            // instance counting
            if (bed.n != null && !bed.singleton)
                result.append("  container->" + mangle(s.name) + ".n--;\n");
            for (String alias : bed.accountableEndpoints) {
                result.append("  " + mangle(alias) + "->" + prefix(s) + "_" + mangle(alias) + "_count--;\n");
            }
            // release event monitors
            for (EventTarget et : bed.eventTargets) {
                for (EventSource es : et.sources) {
                    String part = "";
                    if (es.reference != null)
                        part = resolveContainer(es.reference, context, "");
                    String eventMonitor = "eventMonitor_" + prefix(s);
                    if (es.monitorIndex > 0)
                        eventMonitor += "_" + es.monitorIndex;
                    result.append("  removeMonitor (" + part + eventMonitor + ", this);\n");
                }
            }
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit enterSimulation
    if (bed.localReference.size() > 0) {
        result.append("void " + ns + "enterSimulation ()\n");
        result.append("{\n");
        // String rather than EquationSet, because we may have references to several different instances of the same EquationSet, and all must be accounted
        TreeSet<String> touched = new TreeSet<String>();
        for (VariableReference r : bed.localReference) {
            String container = resolveContainer(r, context, "");
            if (touched.add(container))
                result.append("  " + container + "refcount++;\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit leaveSimulation
    {
        result.append("void " + ns + "leaveSimulation ()\n");
        result.append("{\n");
        if (!bed.singleton) {
            result.append("  " + containerOf(s, false, "") + mangle(s.name) + ".remove (this);\n");
        }
        TreeSet<String> touched = new TreeSet<String>();
        for (VariableReference r : bed.localReference) {
            String container = resolveContainer(r, context, "");
            if (touched.add(container))
                result.append("  " + container + "refcount--;\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit isFree
    if (bed.refcount) {
        result.append("bool " + ns + "isFree ()\n");
        result.append("{\n");
        result.append("  return refcount == 0;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit init
    if (bed.needLocalInit) {
        result.append("void " + ns + "init ()\n");
        result.append("{\n");
        s.setInit(1);
        for (Variable v : bed.localBufferedExternal) {
            // Clear both buffered and regular values, so we can use a proper combiner during init.
            result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
            result.append("  " + clearAccumulator(mangle(v), v, context) + ";\n");
        }
        for (EventTarget et : bed.eventTargets) {
            if (et.timeIndex >= 0) {
                // Normal values are modulo 1 second. This initial value guarantees no match.
                result.append("  eventTime" + et.timeIndex + " = 10;\n");
            }
        // Auxiliary variables get initialized as part of the regular list below.
        }
        if (!bed.localFlagType.isEmpty()) {
            if (bed.liveFlag >= 0) {
                if (bed.newborn >= 0) {
                    result.append("  flags |= (" + bed.localFlagType + ") 0x1 << " + bed.liveFlag + ";\n");
                } else {
                    result.append("  flags = (" + bed.localFlagType + ") 0x1 << " + bed.liveFlag + ";\n");
                }
            } else {
                if (bed.newborn < 0) {
                    result.append("  flags = 0;\n");
                }
            // else flags has already been initialized by Population::add()
            }
        }
        // Initialize static objects
        for (// non-optimized list, so hopefully all variables are covered
        Variable v : // non-optimized list, so hopefully all variables are covered
        bed.localInit) {
            for (EquationEntry e : v.equations) {
                prepareStaticObjects(e.expression, context, "  ");
                if (e.condition != null)
                    prepareStaticObjects(e.condition, context, "  ");
            }
        }
        // Compute variables
        if (bed.lastT) {
            result.append("  lastT = Simulator<" + T + ">::instance.currentEvent->t;\n");
        }
        s.simplify("$init", bed.localInit);
        if (T.equals("int"))
            EquationSet.determineExponentsSimplified(bed.localInit);
        EquationSet.determineOrderInit(bed.localInit);
        if (bed.localInit.contains(bed.dt)) {
            result.append("  EventStep<" + T + "> * event = getEvent ();\n");
            context.hasEvent = true;
            result.append("  " + type(bed.dt) + " " + mangle(bed.dt) + ";\n");
        }
        for (// optimized list: only variables with equations that actually fire during init
        Variable v : // optimized list: only variables with equations that actually fire during init
        bed.localInit) {
            multiconditional(v, context, "  ");
        }
        // TODO: may need to deal with REPLACE for buffered variables. See internal.Part
        if (bed.localInit.contains(bed.dt)) {
            result.append("  if (" + mangle(bed.dt) + " != event->dt) setPeriod (" + mangle(bed.dt) + ");\n");
        } else if (// implies that bed.dt exists and is constant
        bed.setDt) {
            result.append("  setPeriod (" + resolve(bed.dt.reference, context, false) + ");\n");
        }
        // instance counting
        if (bed.trackN)
            result.append("  " + containerOf(s, false, "") + mangle(s.name) + ".n++;\n");
        for (String alias : bed.accountableEndpoints) {
            result.append("  " + mangle(alias) + "->" + prefix(s) + "_" + mangle(alias) + "_count++;\n");
        }
        // Request event monitors
        for (EventTarget et : bed.eventTargets) {
            for (EventSource es : et.sources) {
                String part = "";
                if (es.reference != null)
                    part = resolveContainer(es.reference, context, "");
                String eventMonitor = "eventMonitor_" + prefix(s);
                if (es.monitorIndex > 0)
                    eventMonitor += "_" + es.monitorIndex;
                result.append("  " + part + eventMonitor + ".push_back (this);\n");
            }
        }
        // contained populations
        if (s.parts.size() > 0) {
            // If there are parts at all, then orderedParts must be filled in correctly. Otherwise it may be null.
            for (EquationSet e : s.orderedParts) {
                if (((BackendDataC) e.backendData).needGlobalInit) {
                    result.append("  " + mangle(e.name) + ".init ();\n");
                }
            }
        }
        s.setInit(0);
        context.hasEvent = false;
        result.append("}\n");
        result.append("\n");
    }
    // Unit integrate
    if (bed.needLocalIntegrate) {
        result.append("void " + ns + "integrate ()\n");
        result.append("{\n");
        push_region(result, ns + "integrate()");
        if (bed.localIntegrated.size() > 0) {
            if (bed.lastT) {
                result.append("  " + T + " dt = Simulator<" + T + ">::instance.currentEvent->t - lastT;\n");
            } else {
                result.append("  EventStep<" + T + "> * event = getEvent ();\n");
                context.hasEvent = true;
                result.append("  " + T + " dt = event->dt;\n");
            }
            // Note the resolve() call on the left-hand-side below has lvalue==false.
            // Integration always takes place in the primary storage of a variable.
            String pad = "";
            if (bed.needLocalPreserve) {
                pad = "  ";
                result.append("  if (preserve)\n");
                result.append("  {\n");
                for (Variable v : bed.localIntegrated) {
                    result.append("    " + resolve(v.reference, context, false) + " = preserve->" + mangle(v) + " + ");
                    int shift = v.derivative.exponent + bed.dt.exponent - Operator.MSB - v.exponent;
                    if (shift != 0 && T.equals("int")) {
                        result.append("(int) ((int64_t) " + resolve(v.derivative.reference, context, false) + " * dt" + context.printShift(shift) + ");\n");
                    } else {
                        result.append(resolve(v.derivative.reference, context, false) + " * dt;\n");
                    }
                }
                result.append("  }\n");
                result.append("  else\n");
                result.append("  {\n");
            }
            for (Variable v : bed.localIntegrated) {
                result.append(pad + "  " + resolve(v.reference, context, false) + " += ");
                int shift = v.derivative.exponent + bed.dt.exponent - Operator.MSB - v.exponent;
                if (shift != 0 && T.equals("int")) {
                    result.append("(int) ((int64_t) " + resolve(v.derivative.reference, context, false) + " * dt" + context.printShift(shift) + ");\n");
                } else {
                    result.append(resolve(v.derivative.reference, context, false) + " * dt;\n");
                }
            }
            if (bed.needLocalPreserve)
                result.append("  }\n");
        }
        // contained populations
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalIntegrate) {
                result.append("  " + mangle(e.name) + ".integrate ();\n");
            }
        }
        context.hasEvent = false;
        pop_region(result);
        result.append("}\n");
        result.append("\n");
    }
    // Unit update
    if (bed.needLocalUpdate) {
        result.append("void " + ns + "update ()\n");
        result.append("{\n");
        push_region(result, ns + "update()");
        for (Variable v : bed.localBufferedInternalUpdate) {
            result.append("  " + type(v) + " " + mangle("next_", v) + ";\n");
        }
        s.simplify("$live", bed.localUpdate);
        if (T.equals("int"))
            EquationSet.determineExponentsSimplified(bed.localUpdate);
        for (Variable v : bed.localUpdate) {
            multiconditional(v, context, "  ");
        }
        for (Variable v : bed.localBufferedInternalUpdate) {
            result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
        }
        // contained populations
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalUpdate) {
                result.append("  " + mangle(e.name) + ".update ();\n");
            }
        }
        pop_region(result);
        result.append("}\n");
        result.append("\n");
    }
    // Unit finalize
    if (bed.needLocalFinalize) {
        result.append("bool " + ns + "finalize ()\n");
        result.append("{\n");
        // contained populations
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalFinalize) {
                // ignore return value
                result.append("  " + mangle(e.name) + ".finalize ();\n");
            }
        }
        // Early-out if we are already dead
        if (// $live is stored in this part
        bed.liveFlag >= 0) {
            // early-out if we are already dead, to avoid another call to die()
            result.append("  if (! (flags & (" + bed.localFlagType + ") 0x1 << " + bed.liveFlag + ")) return false;\n");
        }
        // Preemptively fetch current event
        boolean needT = bed.eventSources.size() > 0 || s.lethalP || bed.localBufferedExternal.contains(bed.dt);
        if (needT) {
            result.append("  EventStep<" + T + "> * event = getEvent ();\n");
            context.hasEvent = true;
        }
        // Events
        for (EventSource es : bed.eventSources) {
            EventTarget et = es.target;
            String eventMonitor = "eventMonitor_" + prefix(et.container);
            if (es.monitorIndex > 0)
                eventMonitor += "_" + es.monitorIndex;
            if (es.testEach) {
                result.append("  for (Part * p : " + eventMonitor + ")\n");
                result.append("  {\n");
                result.append("    if (! p->eventTest (" + et.valueIndex + ")) continue;\n");
                eventGenerate("    ", et, context, false);
                result.append("  }\n");
            } else // All monitors share same condition, so only test one.
            {
                result.append("  if (! " + eventMonitor + ".empty ()  &&  " + eventMonitor + "[0]->eventTest (" + et.valueIndex + "))\n");
                result.append("  {\n");
                if (// Each target instance may require a different delay.
                es.delayEach) {
                    result.append("    for (auto p : " + eventMonitor + ")\n");
                    result.append("    {\n");
                    eventGenerate("      ", et, context, false);
                    result.append("    }\n");
                } else // All delays are the same.
                {
                    eventGenerate("    ", et, context, true);
                }
                result.append("  }\n");
            }
        }
        int eventCount = bed.eventTargets.size();
        if (eventCount > 0) {
            result.append("  flags &= ~(" + bed.localFlagType + ") 0 << " + eventCount + ";\n");
        }
        // Finalize variables
        if (bed.lastT) {
            result.append("  lastT = Simulator<" + T + ">::instance.currentEvent->t;\n");
        }
        for (Variable v : bed.localBufferedExternal) {
            if (v == bed.dt) {
                result.append("  if (" + mangle("next_", v) + " != event->dt) setPeriod (" + mangle("next_", v) + ");\n");
            } else {
                result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
            }
        }
        for (Variable v : bed.localBufferedExternalWrite) {
            result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
        }
        if (bed.type != null) {
            result.append("  switch (" + mangle("$type") + ")\n");
            result.append("  {\n");
            // Each "split" is one particular set of new parts to transform into.
            // Each combination requires a separate piece of code. Thus, the outer
            // structure here is a switch statement. Each case within the switch implements
            // a particular combination of new parts. At this point, $type merely indicates
            // which combination to process. Afterward, it will be set to an index within that
            // combination, per the N2A language document.
            int countSplits = s.splits.size();
            for (int i = 0; i < countSplits; i++) {
                ArrayList<EquationSet> split = s.splits.get(i);
                // Check if $type = me. Ignore this particular case, since it is a null operation
                if (split.size() == 1 && split.get(0) == s) {
                    continue;
                }
                result.append("    case " + (i + 1) + ":\n");
                result.append("    {\n");
                // indicates that this instance is one of the resulting parts
                boolean used = false;
                int countParts = split.size();
                for (int j = 0; j < countParts; j++) {
                    EquationSet to = split.get(j);
                    if (to == s && !used) {
                        used = true;
                        result.append("      " + mangle("$type") + " = " + (j + 1) + ";\n");
                    } else {
                        result.append("      " + containerOf(s, false, "") + mangle(s.name) + "_2_" + mangle(to.name) + " (this, " + (j + 1) + ");\n");
                    }
                }
                if (used) {
                    result.append("      break;\n");
                } else {
                    result.append("      die ();\n");
                    result.append("      return false;\n");
                }
                result.append("    }\n");
            }
            result.append("  }\n");
        }
        if (s.lethalP) {
            // lethalP implies that $p exists, so no need to check for null
            if (bed.p.hasAttribute("constant")) {
                double pvalue = ((Scalar) ((Constant) bed.p.equations.first().expression).value).value;
                if (pvalue != 0) {
                    // If $t' is exactly 1, then pow() is unnecessary here. However, that is a rare situation.
                    result.append("  if (pow (" + resolve(bed.p.reference, context, false) + ", " + resolve(bed.dt.reference, context, false));
                    if (context.useExponent) {
                        // second operand must have exponent=15
                        result.append(context.printShift(bed.dt.exponent - 15));
                        // exponentA
                        result.append(", " + bed.p.exponent);
                        // exponentResult
                        result.append(", " + bed.p.exponent);
                    }
                    result.append(") < uniform<" + T + "> ()");
                    // -1 is hard-coded from the Uniform function.
                    if (context.useExponent)
                        result.append(context.printShift(-1 - bed.p.exponent));
                    result.append(")\n");
                }
            } else {
                if (bed.p.hasAttribute("temporary")) {
                    // Assemble a minimal set of expressions to evaluate $p
                    List<Variable> list = new ArrayList<Variable>();
                    for (Variable t : s.ordered) if (t.hasAttribute("temporary") && bed.p.dependsOn(t) != null)
                        list.add(t);
                    list.add(bed.p);
                    s.simplify("$live", list, bed.p);
                    if (T.equals("int"))
                        EquationSet.determineExponentsSimplified(list);
                    for (Variable v : list) {
                        multiconditional(v, context, "  ");
                    }
                }
                result.append("  if (" + mangle("$p") + " <= 0  ||  " + mangle("$p") + " < " + context.print(1, bed.p.exponent) + "  &&  pow (" + mangle("$p") + ", " + resolve(bed.dt.reference, context, false));
                if (context.useExponent) {
                    result.append(context.printShift(bed.dt.exponent - 15));
                    result.append(", " + bed.p.exponent);
                    result.append(", " + bed.p.exponent);
                }
                result.append(") < uniform<" + T + "> ()");
                if (context.useExponent)
                    result.append(context.printShift(-1 - bed.p.exponent));
                result.append(")\n");
            }
            result.append("  {\n");
            result.append("    die ();\n");
            result.append("    return false;\n");
            result.append("  }\n");
        }
        if (s.lethalConnection) {
            for (ConnectionBinding c : s.connectionBindings) {
                VariableReference r = s.resolveReference(c.alias + ".$live");
                if (!r.variable.hasAttribute("constant")) {
                    result.append("  if (" + resolve(r, context, false, "", true) + " == 0)\n");
                    result.append("  {\n");
                    result.append("    die ();\n");
                    result.append("    return false;\n");
                    result.append("  }\n");
                }
            }
        }
        if (s.lethalContainer) {
            VariableReference r = s.resolveReference("$up.$live");
            if (!r.variable.hasAttribute("constant")) {
                result.append("  if (" + resolve(r, context, false, "", true) + " == 0)\n");
                result.append("  {\n");
                result.append("    die ();\n");
                result.append("    return false;\n");
                result.append("  }\n");
            }
        }
        result.append("  return true;\n");
        context.hasEvent = false;
        result.append("}\n");
        result.append("\n");
    }
    // Unit updateDerivative
    if (bed.needLocalUpdateDerivative) {
        result.append("void " + ns + "updateDerivative ()\n");
        result.append("{\n");
        push_region(result, ns + "updateDerivative()");
        for (Variable v : bed.localBufferedInternalDerivative) {
            result.append("  " + type(v) + " " + mangle("next_", v) + ";\n");
        }
        s.simplify("$live", bed.localDerivativeUpdate);
        if (T.equals("int"))
            EquationSet.determineExponentsSimplified(bed.localDerivativeUpdate);
        for (Variable v : bed.localDerivativeUpdate) {
            multiconditional(v, context, "  ");
        }
        for (Variable v : bed.localBufferedInternalDerivative) {
            result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
        }
        // contained populations
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalUpdateDerivative) {
                result.append("  " + mangle(e.name) + ".updateDerivative ();\n");
            }
        }
        pop_region(result);
        result.append("}\n");
        result.append("\n");
    }
    // Unit finalizeDerivative
    if (bed.needLocalFinalizeDerivative) {
        result.append("void " + ns + "finalizeDerivative ()\n");
        result.append("{\n");
        for (Variable v : bed.localBufferedExternalDerivative) {
            result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
        }
        for (Variable v : bed.localBufferedExternalWriteDerivative) {
            result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
        }
        // contained populations
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalFinalizeDerivative) {
                result.append("  " + mangle(e.name) + ".finalizeDerivative ();\n");
            }
        }
        result.append("}\n");
        result.append("\n");
    }
    if (bed.needLocalPreserve) {
        // Unit snapshot
        result.append("void " + ns + "snapshot ()\n");
        result.append("{\n");
        if (bed.needLocalPreserve) {
            result.append("  preserve = new Preserve;\n");
            for (Variable v : bed.localIntegrated) {
                result.append("  preserve->" + mangle(v) + " = " + mangle(v) + ";\n");
            }
            for (Variable v : bed.localDerivativePreserve) {
                result.append("  preserve->" + mangle(v) + " = " + mangle(v) + ";\n");
            }
            for (Variable v : bed.localBufferedExternalWriteDerivative) {
                result.append("  preserve->" + mangle("next_", v) + " = " + mangle("next_", v) + ";\n");
                result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
            }
        }
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalPreserve) {
                result.append("  " + mangle(e.name) + ".snapshot ();\n");
            }
        }
        result.append("}\n");
        result.append("\n");
        // Unit restore
        result.append("void " + ns + "restore ()\n");
        result.append("{\n");
        if (bed.needLocalPreserve) {
            for (Variable v : bed.localDerivativePreserve) {
                result.append("  " + mangle(v) + " = preserve->" + mangle(v) + ";\n");
            }
            for (Variable v : bed.localBufferedExternalWriteDerivative) {
                result.append("  " + mangle("next_", v) + " = preserve->" + mangle("next_", v) + ";\n");
            }
            result.append("  delete preserve;\n");
            result.append("  preserve = 0;\n");
        }
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalPreserve) {
                result.append("  " + mangle(e.name) + ".restore ();\n");
            }
        }
        result.append("}\n");
        result.append("\n");
    }
    if (bed.needLocalDerivative) {
        // Unit pushDerivative
        result.append("void " + ns + "pushDerivative ()\n");
        result.append("{\n");
        if (bed.localDerivative.size() > 0) {
            result.append("  Derivative * temp = new Derivative;\n");
            result.append("  temp->next = stackDerivative;\n");
            result.append("  stackDerivative = temp;\n");
            for (Variable v : bed.localDerivative) {
                result.append("  temp->" + mangle(v) + " = " + mangle(v) + ";\n");
            }
        }
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalDerivative) {
                result.append("  " + mangle(e.name) + ".pushDerivative ();\n");
            }
        }
        result.append("}\n");
        result.append("\n");
        // Unit multiplyAddToStack
        result.append("void " + ns + "multiplyAddToStack (" + T + " scalar)\n");
        result.append("{\n");
        for (Variable v : bed.localDerivative) {
            result.append("  stackDerivative->" + mangle(v) + " += ");
            if (T.equals("int")) {
                result.append("(int) ((int64_t) " + mangle(v) + " * scalar >> " + (Operator.MSB - 1) + ");\n");
            } else {
                result.append(mangle(v) + " * scalar;\n");
            }
        }
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalDerivative) {
                result.append("  " + mangle(e.name) + ".multiplyAddToStack (scalar);\n");
            }
        }
        result.append("}\n");
        result.append("\n");
        // Unit multiply
        result.append("void " + ns + "multiply (" + T + " scalar)\n");
        result.append("{\n");
        for (Variable v : bed.localDerivative) {
            if (T.equals("int")) {
                result.append("  " + mangle(v) + " = (int64_t) " + mangle(v) + " * scalar >> " + (Operator.MSB - 1) + ";\n");
            } else {
                result.append("  " + mangle(v) + " *= scalar;\n");
            }
        }
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalDerivative) {
                result.append("  " + mangle(e.name) + ".multiply (scalar);\n");
            }
        }
        result.append("}\n");
        result.append("\n");
        // Unit addToMembers
        result.append("void " + ns + "addToMembers ()\n");
        result.append("{\n");
        if (bed.localDerivative.size() > 0) {
            for (Variable v : bed.localDerivative) {
                result.append("  " + mangle(v) + " += stackDerivative->" + mangle(v) + ";\n");
            }
            result.append("  Derivative * temp = stackDerivative;\n");
            result.append("  stackDerivative = stackDerivative->next;\n");
            result.append("  delete temp;\n");
        }
        for (EquationSet e : s.parts) {
            if (((BackendDataC) e.backendData).needGlobalDerivative) {
                result.append("  " + mangle(e.name) + ".addToMembers ();\n");
            }
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit setPart
    if (s.connectionBindings != null) {
        result.append("void " + ns + "setPart (int i, Part * part)\n");
        result.append("{\n");
        result.append("  switch (i)\n");
        result.append("  {\n");
        for (ConnectionBinding c : s.connectionBindings) {
            result.append("    case " + c.index + ": " + mangle(c.alias) + " = (" + prefix(c.endpoint) + " *) part; return;\n");
        }
        result.append("  }\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit getPart
    if (s.connectionBindings != null) {
        result.append("Part<" + T + "> * " + ns + "getPart (int i)\n");
        result.append("{\n");
        result.append("  switch (i)\n");
        result.append("  {\n");
        for (ConnectionBinding c : s.connectionBindings) {
            result.append("    case " + c.index + ": return " + mangle(c.alias) + ";\n");
        }
        result.append("  }\n");
        result.append("  return 0;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit getCount
    if (bed.accountableEndpoints.size() > 0) {
        result.append("int " + ns + "getCount (int i)\n");
        result.append("{\n");
        result.append("  switch (i)\n");
        result.append("  {\n");
        for (ConnectionBinding c : s.connectionBindings) {
            if (bed.accountableEndpoints.contains(c.alias)) {
                result.append("    case " + c.index + ": return " + mangle(c.alias) + "->" + prefix(s) + "_" + mangle(c.alias) + "_count;\n");
            }
        }
        result.append("  }\n");
        result.append("  return 0;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit getProject
    if (bed.hasProject) {
        result.append("void " + ns + "getProject (int i, MatrixFixed<" + T + ",3,1> & xyz)\n");
        result.append("{\n");
        // $project is evaluated similar to $p. The result is not stored.
        s.setConnect(1);
        result.append("  switch (i)\n");
        result.append("  {\n");
        boolean needDefault = false;
        for (ConnectionBinding c : s.connectionBindings) {
            result.append("    case " + c.index + ":");
            Variable project = s.find(new Variable(c.alias + ".$project"));
            if (// fetch $xyz from endpoint
            project == null) {
                VariableReference fromXYZ = s.resolveReference(c.alias + ".$xyz");
                if (fromXYZ.variable == null) {
                    needDefault = true;
                } else {
                    if (// calculated value
                    fromXYZ.variable.hasAttribute("temporary")) {
                        result.append(" " + mangle(c.alias) + "->getXYZ (xyz); break;\n");
                    } else // stored value or "constant"
                    {
                        result.append(" xyz = " + resolve(fromXYZ, context, false) + "; break;\n");
                    }
                }
            } else // compute $project
            {
                // to complete the "case" line
                result.append("\n");
                result.append("    {\n");
                if (// it could also be "constant", but no other type
                project.hasAttribute("temporary")) {
                    // Assemble a minimal set of expressions to evaluate $project
                    List<Variable> list = new ArrayList<Variable>();
                    for (Variable t : s.ordered) {
                        if ((t.hasAttribute("temporary") || bed.localMembers.contains(t)) && project.dependsOn(t) != null)
                            list.add(t);
                    }
                    list.add(project);
                    s.simplify("$connect", list, project);
                    if (T.equals("int"))
                        EquationSet.determineExponentsSimplified(list);
                    for (Variable v : list) {
                        multiconditional(v, context, "      ");
                    }
                }
                result.append("      xyz = " + resolve(project.reference, context, false) + ";\n");
                result.append("      break;\n");
                result.append("    }\n");
            }
        }
        if (needDefault) {
            result.append("    default:\n");
            result.append("      xyz[0] = 0;\n");
            result.append("      xyz[1] = 0;\n");
            result.append("      xyz[2] = 0;\n");
        }
        result.append("  }\n");
        result.append("}\n");
        s.setConnect(0);
    }
    // Unit mapIndex
    if (s.connectionMatrix != null && s.connectionMatrix.needsMapping) {
        result.append("int " + ns + "mapIndex (int i, int rc)\n");
        result.append("{\n");
        Variable rc = new Variable("rc");
        rc.reference = new VariableReference();
        rc.reference.variable = rc;
        rc.container = s;
        rc.addAttribute("preexistent");
        AccessVariable av = new AccessVariable();
        av.reference = rc.reference;
        ConnectionMatrix cm = s.connectionMatrix;
        cm.rowMapping.replaceRC(av);
        cm.colMapping.replaceRC(av);
        result.append("  if (i == " + cm.rows.index + ") return ");
        cm.rowMapping.rhs.render(context);
        result.append(";\n");
        result.append("  return ");
        cm.colMapping.rhs.render(context);
        result.append(";\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit getNewborn
    if (bed.newborn >= 0) {
        result.append("bool " + ns + "getNewborn ()\n");
        result.append("{\n");
        result.append("  return flags & (" + bed.localFlagType + ") 0x1 << " + bed.newborn + ";\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit getLive
    if (bed.live != null && !bed.live.hasAttribute("constant")) {
        result.append(T + " " + ns + "getLive ()\n");
        result.append("{\n");
        if (// "accessor" indicates whether or not $value is actually stored
        !bed.live.hasAttribute("accessor")) {
            result.append("  if (" + resolve(bed.live.reference, context, false, "", true) + " == 0) return 0;\n");
        }
        if (s.lethalConnection) {
            for (ConnectionBinding c : s.connectionBindings) {
                VariableReference r = s.resolveReference(c.alias + ".$live");
                if (!r.variable.hasAttribute("constant")) {
                    result.append("  if (" + resolve(r, context, false, "", true) + " == 0) return 0;\n");
                }
            }
        }
        if (s.lethalContainer) {
            VariableReference r = s.resolveReference("$up.$live");
            if (!r.variable.hasAttribute("constant")) {
                result.append("  if (" + resolve(r, context, false, "", true) + " == 0) return 0;\n");
            }
        }
        result.append("  return 1;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit getP
    if (// Only connections need to provide an accessor
    bed.p != null && s.connectionBindings != null) {
        result.append(T + " " + ns + "getP ()\n");
        result.append("{\n");
        s.setConnect(1);
        if (!bed.p.hasAttribute("constant")) {
            // Assemble a minimal set of expressions to evaluate $p
            List<Variable> list = new ArrayList<Variable>();
            for (Variable t : s.ordered) {
                if ((t.hasAttribute("temporary") || bed.localMembers.contains(t)) && bed.p.dependsOn(t) != null)
                    list.add(t);
            }
            list.add(bed.p);
            s.simplify("$connect", list, bed.p);
            if (T.equals("int"))
                EquationSet.determineExponentsSimplified(list);
            for (Variable v : list) {
                multiconditional(v, context, "  ");
            }
        }
        result.append("  return " + resolve(bed.p.reference, context, false) + ";\n");
        s.setConnect(0);
        result.append("}\n");
        result.append("\n");
    }
    // Unit getXYZ
    if (// Connection targets need to provide an accessor.
    bed.xyz != null && s.connected) {
        result.append("void " + ns + "getXYZ (MatrixFixed<" + T + ",3,1> & xyz)\n");
        result.append("{\n");
        // If stored, then simply copy into the return value.
        if (bed.xyz.hasAttribute("temporary")) {
            // Assemble a minimal set of expressions to evaluate $xyz
            List<Variable> list = new ArrayList<Variable>();
            for (Variable t : s.ordered) if (t.hasAttribute("temporary") && bed.xyz.dependsOn(t) != null)
                list.add(t);
            list.add(bed.xyz);
            // evaluate in $live phase, because endpoints already exist when connection is evaluated.
            s.simplify("$live", list, bed.xyz);
            if (T.equals("int"))
                EquationSet.determineExponentsSimplified(list);
            for (Variable v : list) {
                multiconditional(v, context, "    ");
            }
        }
        result.append("  xyz = " + resolve(bed.xyz.reference, context, false) + ";\n");
        result.append("}\n");
        result.append("\n");
    }
    // Unit events
    if (bed.eventTargets.size() > 0) {
        result.append("bool " + ns + "eventTest (int i)\n");
        result.append("{\n");
        result.append("  switch (i)\n");
        result.append("  {\n");
        for (EventTarget et : bed.eventTargets) {
            result.append("    case " + et.valueIndex + ":\n");
            result.append("    {\n");
            // Not safe or useful to simplify et.dependencies before emitting.
            for (Variable v : et.dependencies) {
                multiconditional(v, context, "      ");
            }
            if (et.edge != EventTarget.NONZERO) {
                result.append("      " + T + " before = ");
                if (et.trackOne)
                    result.append(resolve(et.track.reference, context, false));
                else
                    result.append(mangle(et.track.name));
                result.append(";\n");
            }
            if (// This is a single variable, so check its value directly.
            et.trackOne) {
                result.append("      " + T + " after = " + resolve(et.track.reference, context, true) + ";\n");
            } else // This is an expression, so use our private auxiliary variable.
            {
                result.append("      " + T + " after = ");
                et.event.operands[0].render(context);
                result.append(";\n");
                if (et.edge != EventTarget.NONZERO) {
                    result.append("      " + mangle(et.track.name) + " = after;\n");
                }
            }
            switch(et.edge) {
                case EventTarget.NONZERO:
                    if (et.timeIndex >= 0) {
                        // Guard against multiple events in a given cycle.
                        // Note that other trigger types don't need this because they set the auxiliary variable,
                        // so the next test in the same cycle will no longer see change.
                        result.append("      if (after == 0) return false;\n");
                        if (T.equals("int")) {
                            // No need for modulo arithmetic. Rather, int time should be wrapped elsewhere.
                            result.append("      " + T + " moduloTime = Simulator<" + T + ">::instance.currentEvent->t;\n");
                        } else // float, double
                        {
                            // Wrap time at 1 second, to fit in float precision.
                            result.append("      " + T + " moduloTime = (" + T + ") fmod (Simulator<" + T + ">::instance.currentEvent->t, 1);\n");
                        }
                        result.append("      if (eventTime" + et.timeIndex + " == moduloTime) return false;\n");
                        result.append("      eventTime" + et.timeIndex + " = moduloTime;\n");
                        result.append("      return true;\n");
                    } else {
                        result.append("      return after != 0;\n");
                    }
                    break;
                case EventTarget.CHANGE:
                    result.append("      return before != after;\n");
                    break;
                case EventTarget.FALL:
                    result.append("      return before != 0  &&  after == 0;\n");
                    break;
                case EventTarget.RISE:
                default:
                    result.append("      return before == 0  &&  after != 0;\n");
            }
            result.append("    }\n");
        }
        result.append("  }\n");
        result.append("  return false;\n");
        result.append("}\n");
        result.append("\n");
        if (bed.needLocalEventDelay) {
            result.append(T + " " + ns + "eventDelay (int i)\n");
            result.append("{\n");
            result.append("  switch (i)\n");
            result.append("  {\n");
            for (EventTarget et : bed.eventTargets) {
                if (et.delay >= -1)
                    continue;
                // Need to evaluate expression
                result.append("    case " + et.valueIndex + ":\n");
                result.append("    {\n");
                for (Variable v : et.dependencies) {
                    multiconditional(v, context, "      ");
                }
                result.append("      " + T + " result = ");
                et.event.operands[1].render(context);
                result.append(";\n");
                result.append("      if (result < 0) return -1;\n");
                result.append("      return result;\n");
                result.append("    }\n");
            }
            result.append("  }\n");
            result.append("  return -1;\n");
            result.append("}\n");
            result.append("\n");
        }
        result.append("void " + ns + "setLatch (int i)\n");
        result.append("{\n");
        result.append("  flags |= (" + bed.localFlagType + ") 0x1 << i;\n");
        result.append("}\n");
        result.append("\n");
        if (bed.eventReferences.size() > 0) {
            result.append("void " + ns + "finalizeEvent ()\n");
            result.append("{\n");
            for (Variable v : bed.eventReferences) {
                String current = resolve(v.reference, context, false);
                String buffered = resolve(v.reference, context, true);
                result.append("  " + current);
                switch(v.assignment) {
                    case Variable.ADD:
                        result.append(" += " + buffered + ";\n");
                        result.append("  " + zero(buffered, v) + ";\n");
                        break;
                    case Variable.MULTIPLY:
                    case Variable.DIVIDE:
                        {
                            // The current and buffered values of the variable have the same exponent.
                            // raw = exponentV + exponentV - MSB
                            // shift = raw - exponentV = exponentV - MSB
                            int shift = v.exponent - Operator.MSB;
                            if (shift != 0 && T.equals("int")) {
                                result.append(" = (int64_t) " + current + " * " + buffered + context.printShift(shift) + ";\n");
                            } else {
                                result.append(" *= " + buffered + ";\n");
                            }
                            result.append("  " + clear(buffered, v, 1, context) + ";\n");
                            break;
                        }
                    case Variable.MIN:
                        // TODO: Write elementwise min() and max() for matrices.
                        result.append(" = min (" + current + ", " + buffered + ");\n");
                        result.append("  " + clear(buffered, v, Double.POSITIVE_INFINITY, context) + ";\n");
                        break;
                    case Variable.MAX:
                        result.append(" = max (" + current + ", " + buffered + ");\n");
                        result.append("  " + clear(buffered, v, Double.NEGATIVE_INFINITY, context) + ";\n");
                        break;
                    default:
                        // REPLACE
                        result.append(" = " + buffered + ";\n");
                        break;
                }
            }
            result.append("}\n");
            result.append("\n");
        }
    }
    // Unit path
    if (bed.needLocalPath) {
        result.append("void " + ns + "path (String & result)\n");
        result.append("{\n");
        if (// Not a connection, or a unary connection
        s.connectionBindings == null || s.connectionBindings.size() == 1) {
            // We assume that result is passed in as the empty string.
            if (s.container != null) {
                if (// Will our container provide a non-empty path?
                ((BackendDataC) s.container.backendData).needLocalPath) {
                    result.append("  container->path (result);\n");
                    result.append("  result += \"." + s.name + "\";\n");
                } else {
                    result.append("  result = \"" + s.name + "\";\n");
                }
            }
            if (bed.index != null) {
                result.append("  result += __24index;\n");
            } else if (s.connectionBindings != null) {
                ConnectionBinding c = s.connectionBindings.get(0);
                BackendDataC cbed = (BackendDataC) c.endpoint.backendData;
                if (cbed.index != null)
                    result.append("  result += " + mangle(c.alias) + "->__24index;\n");
            }
        } else // binary or higher connection
        {
            boolean first = true;
            boolean temp = false;
            for (ConnectionBinding c : s.connectionBindings) {
                if (first) {
                    result.append("  " + mangle(c.alias) + "->path (result);\n");
                    first = false;
                } else {
                    if (!temp) {
                        result.append("  String temp;\n");
                        temp = true;
                    }
                    result.append("  " + mangle(c.alias) + "->path (temp);\n");
                    result.append("  result += \"-\";\n");
                    result.append("  result += temp;\n");
                }
            }
        }
        result.append("}\n");
        result.append("\n");
    }
    // Unit conversions
    Set<Conversion> conversions = s.getConversions();
    for (Conversion pair : conversions) {
        EquationSet source = pair.from;
        EquationSet dest = pair.to;
        boolean connectionSource = source.connectionBindings != null;
        boolean connectionDest = dest.connectionBindings != null;
        if (connectionSource != connectionDest) {
            Backend.err.get().println("Can't change $type between connection and non-connection.");
            throw new Backend.AbortRun();
        // Why not? Because a connection *must* know the instances it connects, while
        // a compartment cannot know those instances. Thus, one can never be converted
        // to the other.
        }
        // The "2" functions only have local meaning, so they are never virtual.
        // Must do everything init() normally does, including increment $n.
        // Parameters:
        // from -- the source part
        // visitor -- the one managing the source part
        // $type -- The integer index, in the $type expression, of the current target part. The target part's $type field will be initialized with this number (and zeroed after one cycle).
        result.append("void " + ns + mangle(source.name) + "_2_" + mangle(dest.name) + " (" + mangle(source.name) + " * from, int " + mangle("$type") + ")\n");
        result.append("{\n");
        // if this is a recycled part, then clear() is called
        result.append("  " + mangle(dest.name) + " * to = " + mangle(dest.name) + ".allocate ();\n");
        if (connectionDest) {
            // Match connection bindings
            for (ConnectionBinding c : dest.connectionBindings) {
                ConnectionBinding d = source.findConnection(c.alias);
                if (d == null) {
                    Backend.err.get().println("Unfulfilled connection binding during $type change.");
                    throw new Backend.AbortRun();
                }
                result.append("  to->" + mangle(c.alias) + " = from->" + mangle(c.alias) + ";\n");
            }
        }
        // TODO: Convert contained populations from matching populations in the source part?
        result.append("  to->enterSimulation ();\n");
        result.append("  getEvent ()->enqueue (to);\n");
        // Match variables between the two sets.
        // TODO: a match between variables should be marked as a dependency. This might change some "dummy" variables into stored values.
        String[] forbiddenAttributes = new String[] { "global", "constant", "accessor", "reference", "temporary", "dummy", "preexistent" };
        for (Variable v : dest.variables) {
            if (v.name.equals("$type")) {
                // initialize new part with its position in the $type split
                result.append("  to->" + mangle(v) + " = " + mangle("$type") + ";\n");
                continue;
            }
            if (v.hasAny(forbiddenAttributes))
                continue;
            Variable v2 = source.find(v);
            if (v2 != null) {
                result.append("  to->" + mangle(v) + " = " + resolve(v2.reference, context, false, "from->", false) + ";\n");
            }
        }
        // Unless the user qualifies code with $type, the values just copied above will simply be overwritten.
        result.append("  to->init ();\n");
        result.append("}\n");
        result.append("\n");
    }
}
Also used : Variable(gov.sandia.n2a.eqset.Variable) AccessVariable(gov.sandia.n2a.language.AccessVariable) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) ArrayList(java.util.ArrayList) Scalar(gov.sandia.n2a.language.type.Scalar) ConnectionMatrix(gov.sandia.n2a.eqset.EquationSet.ConnectionMatrix) TreeSet(java.util.TreeSet) EquationEntry(gov.sandia.n2a.eqset.EquationEntry) EventTarget(gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget) EquationSet(gov.sandia.n2a.eqset.EquationSet) VariableReference(gov.sandia.n2a.eqset.VariableReference) AccessVariable(gov.sandia.n2a.language.AccessVariable) Conversion(gov.sandia.n2a.eqset.EquationSet.Conversion) ExtensionPoint(gov.sandia.n2a.plugins.ExtensionPoint) AbortRun(gov.sandia.n2a.plugins.extpoints.Backend.AbortRun) EventSource(gov.sandia.n2a.backend.internal.InternalBackendData.EventSource)

Example 2 with ConnectionMatrix

use of gov.sandia.n2a.eqset.EquationSet.ConnectionMatrix in project n2a by frothga.

the class JobC method generateDefinitionsGlobal.

public void generateDefinitionsGlobal(RendererC context) throws Exception {
    EquationSet s = context.part;
    BackendDataC bed = context.bed;
    StringBuilder result = context.result;
    context.global = true;
    String ps = prefix(s);
    // namespace for all functions associated with part s
    String ns = ps + "_Population::";
    // Population ctor
    if (bed.needGlobalCtor) {
        result.append(ns + ps + "_Population ()\n");
        result.append("{\n");
        if (!bed.singleton) {
            if (// and not singleton, so trackN is true
            bed.n != null) {
                result.append("  n = 0;\n");
            }
            if (!bed.trackInstances && bed.index != null) {
                result.append("  nextIndex = 0;\n");
            }
            if (bed.newborn >= 0) {
                result.append("  firstborn = 0;\n");
            }
        }
        if (bed.needGlobalDerivative) {
            result.append("  stackDerivative = 0;\n");
        }
        if (bed.needGlobalPreserve) {
            result.append("  preserve = 0;\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Population dtor
    if (bed.needGlobalDtor) {
        result.append(ns + "~" + ps + "_Population ()\n");
        result.append("{\n");
        if (bed.needGlobalDerivative) {
            result.append("  while (stackDerivative)\n");
            result.append("  {\n");
            result.append("    Derivative * temp = stackDerivative;\n");
            result.append("    stackDerivative = stackDerivative->next;\n");
            result.append("    delete temp;\n");
            result.append("  }\n");
        }
        if (bed.needGlobalPreserve) {
            result.append("  if (preserve) delete preserve;\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Population create
    if (// In the case of a singleton, this will remain a pure virtual function, and throw an exception if called.
    !bed.singleton) {
        result.append("Part<" + T + "> * " + ns + "create ()\n");
        result.append("{\n");
        result.append("  " + ps + " * p = new " + ps + ";\n");
        if (bed.pathToContainer == null)
            result.append("  p->container = (" + prefix(s.container) + " *) container;\n");
        result.append("  return p;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Population add / remove
    if (bed.index != null && !bed.singleton) {
        result.append("void " + ns + "add (Part<" + T + "> * part)\n");
        result.append("{\n");
        result.append("  " + ps + " * p = (" + ps + " *) part;\n");
        if (bed.trackInstances) {
            result.append("  if (p->__24index < 0)\n");
            result.append("  {\n");
            result.append("    p->__24index = instances.size ();\n");
            result.append("    instances.push_back (p);\n");
            result.append("  }\n");
            result.append("  else\n");
            result.append("  {\n");
            result.append("    instances[p->__24index] = p;\n");
            result.append("  }\n");
            if (bed.newborn >= 0) {
                result.append("  p->flags = (" + bed.localFlagType + ") 0x1 << " + bed.newborn + ";\n");
                result.append("  firstborn = min (firstborn, p->__24index);\n");
            }
        } else {
            result.append("  if (p->__24index < 0) p->__24index = nextIndex++;\n");
        }
        result.append("}\n");
        result.append("\n");
        if (bed.trackInstances) {
            result.append("void " + ns + "remove (Part<" + T + "> * part)\n");
            result.append("{\n");
            result.append("  " + ps + " * p = (" + ps + " *) part;\n");
            result.append("  instances[p->__24index] = 0;\n");
            result.append("  Population<" + T + ">::remove (part);\n");
            result.append("}\n");
            result.append("\n");
        }
    }
    // Population init
    if (bed.needGlobalInit) {
        result.append("void " + ns + "init ()\n");
        result.append("{\n");
        s.setInit(1);
        // Zero out members
        for (Variable v : bed.globalMembers) {
            result.append("  " + zero(mangle(v), v) + ";\n");
        }
        for (Variable v : bed.globalBufferedExternal) {
            result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
            result.append("  " + clearAccumulator(mangle(v), v, context) + ";\n");
        }
        if (!bed.globalFlagType.isEmpty()) {
            result.append("  flags = 0;\n");
        }
        // Compute variables
        if (// $n is not stored, so we need to declare a local variable to receive its value.
        bed.nInitOnly) {
            result.append("  " + type(bed.n) + " " + mangle(bed.n) + ";\n");
        }
        s.simplify("$init", bed.globalInit);
        if (T.equals("int"))
            EquationSet.determineExponentsSimplified(bed.globalInit);
        EquationSet.determineOrderInit(bed.globalInit);
        for (Variable v : bed.globalInit) {
            multiconditional(v, context, "  ");
        }
        // create instances
        if (bed.singleton) {
            if (bed.newborn >= 0) {
                result.append("  instance.flags = (" + bed.localFlagType + ") 0x1 << " + bed.newborn + ";\n");
            }
            result.append("  instance.enterSimulation ();\n");
            result.append("  container->getEvent ()->enqueue (&instance);\n");
            result.append("  instance.init ();\n");
        } else {
            if (// and not singleton, so trackN is true
            bed.n != null) {
                result.append("  resize (" + resolve(bed.n.reference, context, bed.nInitOnly));
                if (context.useExponent)
                    result.append(context.printShift(bed.n.exponent - Operator.MSB));
                result.append(");\n");
            }
        }
        // make connections
        if (s.connectionBindings != null) {
            // queue to evaluate our connections
            result.append("  Simulator<" + T + ">::instance.connect (this);\n");
        }
        s.setInit(0);
        result.append("}\n");
        result.append("\n");
    }
    // Population integrate
    if (bed.needGlobalIntegrate) {
        result.append("void " + ns + "integrate ()\n");
        result.append("{\n");
        push_region(result, ns + "integrate()");
        result.append("  EventStep<" + T + "> * event = getEvent ();\n");
        context.hasEvent = true;
        result.append("  " + T + " dt = event->dt;\n");
        result.append("  if (preserve)\n");
        result.append("  {\n");
        for (Variable v : bed.globalIntegrated) {
            result.append("    " + resolve(v.reference, context, false) + " = preserve->" + mangle(v) + " + ");
            // For fixed-point:
            // raw result = exponentDerivative+exponentTime-MSB
            // shift = raw-exponentVariable = exponentDerivative+exponentTime-MSB-exponentVariable
            int shift = v.derivative.exponent + bed.dt.exponent - Operator.MSB - v.exponent;
            if (shift != 0 && T.equals("int")) {
                result.append("(int) ((int64_t) " + resolve(v.derivative.reference, context, false) + " * dt" + context.printShift(shift) + ");\n");
            } else {
                result.append(resolve(v.derivative.reference, context, false) + " * dt;\n");
            }
        }
        result.append("  }\n");
        result.append("  else\n");
        result.append("  {\n");
        for (Variable v : bed.globalIntegrated) {
            result.append("    " + resolve(v.reference, context, false) + " += ");
            int shift = v.derivative.exponent + bed.dt.exponent - Operator.MSB - v.exponent;
            if (shift != 0 && T.equals("int")) {
                result.append("(int) ((int64_t) " + resolve(v.derivative.reference, context, false) + " * dt" + context.printShift(shift) + ");\n");
            } else {
                result.append(resolve(v.derivative.reference, context, false) + " * dt;\n");
            }
        }
        result.append("  }\n");
        context.hasEvent = false;
        pop_region(result);
        result.append("}\n");
        result.append("\n");
    }
    // Population update
    if (bed.needGlobalUpdate) {
        result.append("void " + ns + "update ()\n");
        result.append("{\n");
        push_region(result, ns + "update()");
        for (Variable v : bed.globalBufferedInternalUpdate) {
            result.append("  " + type(v) + " " + mangle("next_", v) + ";\n");
        }
        s.simplify("$live", bed.globalUpdate);
        if (T.equals("int"))
            EquationSet.determineExponentsSimplified(bed.globalUpdate);
        for (Variable v : bed.globalUpdate) {
            multiconditional(v, context, "  ");
        }
        for (Variable v : bed.globalBufferedInternalUpdate) {
            result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
        }
        pop_region(result);
        result.append("}\n");
        result.append("\n");
    }
    // Population finalize
    if (bed.needGlobalFinalize) {
        result.append("bool " + ns + "finalize ()\n");
        result.append("{\n");
        if (// $n shares control with other specials, so must coordinate with them
        bed.canResize && bed.n.derivative == null && bed.canGrowOrDie) {
            // $n may be assigned during the regular update cycle, so we need to monitor it.
            result.append("  if (" + mangle("$n") + " != " + mangle("next_", "$n") + ") Simulator<" + T + ">::instance.resize (this, max (0, " + mangle("next_", "$n"));
            if (context.useExponent)
                result.append(context.printShift(bed.n.exponent - Operator.MSB));
            result.append("));\n");
            result.append("  else Simulator<" + T + ">::instance.resize (this, -1);\n");
        }
        for (Variable v : bed.globalBufferedExternal) {
            result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
        }
        for (Variable v : bed.globalBufferedExternalWrite) {
            result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
        }
        // Return value is generally ignored, except for top-level population.
        boolean returnN = bed.needGlobalFinalizeN;
        if (bed.canResize) {
            if (bed.canGrowOrDie) {
                if (// $n' exists
                bed.n.derivative != null) {
                    // the rate of change in $n is pre-determined, so it relentlessly overrides any other structural dynamics
                    if (returnN) {
                        result.append("  if (n == 0) return false;\n");
                        returnN = false;
                    }
                    result.append("  Simulator<" + T + ">::instance.resize (this, max (0, " + mangle("$n"));
                    if (context.useExponent)
                        result.append(context.printShift(bed.n.exponent - Operator.MSB));
                    result.append("));\n");
                }
            } else // $n is the only kind of structural dynamics, so simply do a resize() when needed
            {
                if (returnN) {
                    result.append("  if (n == 0) return false;\n");
                    returnN = false;
                }
                result.append("  int floorN = max (0, ");
                if (context.useExponent)
                    result.append(mangle("$n") + context.printShift(bed.n.exponent - Operator.MSB));
                else
                    result.append("(int) " + mangle("$n"));
                result.append(");\n");
                result.append("  if (n != floorN) Simulator<" + T + ">::instance.resize (this, floorN);\n");
            }
        }
        if (returnN) {
            result.append("  return n;\n");
        } else {
            result.append("  return true;\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Population resize()
    if (bed.canResize) {
        result.append("void " + ns + "resize (int n)\n");
        result.append("{\n");
        if (bed.canGrowOrDie && bed.n.derivative == null) {
            result.append("  if (n < 0)\n");
            result.append("  {\n");
            result.append("    " + mangle("$n") + " = this->n;\n");
            result.append("    return;\n");
            result.append("  }\n");
            result.append("\n");
        }
        result.append("  Population<" + T + ">::resize (n);\n");
        result.append("\n");
        result.append("  for (int i = instances.size () - 1; this->n > n  &&  i >= 0; i--)\n");
        result.append("  {\n");
        result.append("    Part * p = instances[i];\n");
        result.append("    if (p  &&  p->getLive ()) p->die ();\n");
        result.append("  }\n");
        result.append("}\n");
        result.append("\n");
    }
    // Population getN
    if (bed.trackN) {
        result.append("int " + ns + "getN ()\n");
        result.append("{\n");
        result.append("  return n;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Population updateDerivative
    if (bed.needGlobalUpdateDerivative) {
        result.append("void " + ns + "updateDerivative ()\n");
        result.append("{\n");
        push_region(result, ns + "updateDerivative()");
        for (Variable v : bed.globalBufferedInternalDerivative) {
            result.append("  " + type(v) + " " + mangle("next_", v) + ";\n");
        }
        // This is unlikely to make any difference. Just being thorough before call to multiconditional().
        s.simplify("$live", bed.globalDerivativeUpdate);
        if (T.equals("int"))
            EquationSet.determineExponentsSimplified(bed.globalDerivativeUpdate);
        for (Variable v : bed.globalDerivativeUpdate) {
            multiconditional(v, context, "  ");
        }
        for (Variable v : bed.globalBufferedInternalDerivative) {
            result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
        }
        pop_region(result);
        result.append("}\n");
        result.append("\n");
    }
    // Population finalizeDerivative
    if (bed.needGlobalFinalizeDerivative) {
        result.append("void " + ns + "finalizeDerivative ()\n");
        result.append("{\n");
        for (Variable v : bed.globalBufferedExternalDerivative) {
            result.append("  " + mangle(v) + " = " + mangle("next_", v) + ";\n");
        }
        for (Variable v : bed.globalBufferedExternalWriteDerivative) {
            result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    if (bed.needGlobalPreserve) {
        // Population snapshot
        result.append("void " + ns + "snapshot ()\n");
        result.append("{\n");
        result.append("  preserve = new Preserve;\n");
        for (Variable v : bed.globalIntegrated) {
            result.append("  preserve->" + mangle(v) + " = " + mangle(v) + ";\n");
        }
        for (Variable v : bed.globalDerivativePreserve) {
            result.append("  preserve->" + mangle(v) + " = " + mangle(v) + ";\n");
        }
        for (Variable v : bed.globalBufferedExternalWriteDerivative) {
            result.append("  preserve->" + mangle("next_", v) + " = " + mangle("next_", v) + ";\n");
            result.append("  " + clearAccumulator(mangle("next_", v), v, context) + ";\n");
        }
        result.append("}\n");
        result.append("\n");
        // Population restore
        result.append("void " + ns + "restore ()\n");
        result.append("{\n");
        for (Variable v : bed.globalDerivativePreserve) {
            result.append("  " + mangle(v) + " = preserve->" + mangle(v) + ";\n");
        }
        for (Variable v : bed.globalBufferedExternalWriteDerivative) {
            result.append("  " + mangle("next_", v) + " = preserve->" + mangle("next_", v) + ";\n");
        }
        result.append("  delete preserve;\n");
        result.append("  preserve = 0;\n");
        result.append("}\n");
        result.append("\n");
    }
    if (bed.needGlobalDerivative) {
        // Population pushDerivative
        result.append("void " + ns + "pushDerivative ()\n");
        result.append("{\n");
        result.append("  Derivative * temp = new Derivative;\n");
        result.append("  temp->_next = stackDerivative;\n");
        result.append("  stackDerivative = temp;\n");
        for (Variable v : bed.globalDerivative) {
            result.append("  temp->" + mangle(v) + " = " + mangle(v) + ";\n");
        }
        result.append("}\n");
        result.append("\n");
        // Population multiplyAddToStack
        result.append("void " + ns + "multiplyAddToStack (" + T + " scalar)\n");
        result.append("{\n");
        for (Variable v : bed.globalDerivative) {
            result.append("  stackDerivative->" + mangle(v) + " += ");
            if (T.equals("int")) {
                result.append("(int) ((int64_t) " + mangle(v) + " * scalar >> " + (Operator.MSB - 1) + ");\n");
            } else {
                result.append(mangle(v) + " * scalar;\n");
            }
        }
        result.append("}\n");
        result.append("\n");
        // Population multiply
        result.append("void " + ns + "multiply (" + T + " scalar)\n");
        result.append("{\n");
        for (Variable v : bed.globalDerivative) {
            if (T.equals("int")) {
                result.append("  " + mangle(v) + " = (int64_t) " + mangle(v) + " * scalar >> " + (Operator.MSB - 1) + ";\n");
            } else {
                result.append("  " + mangle(v) + " *= scalar;\n");
            }
        }
        result.append("}\n");
        result.append("\n");
        // Population addToMembers
        result.append("void " + ns + "addToMembers ()\n");
        result.append("{\n");
        for (Variable v : bed.globalDerivative) {
            result.append("  " + mangle(v) + " += stackDerivative->" + mangle(v) + ";\n");
        }
        result.append("  Derivative * temp = stackDerivative;\n");
        result.append("  stackDerivative = stackDerivative->next;\n");
        result.append("  delete temp;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Population clearNew
    if (bed.newborn >= 0) {
        result.append("void " + ns + "clearNew ()\n");
        result.append("{\n");
        // Reset our clearNew flag
        result.append("  flags &= ~((" + bed.globalFlagType + ") 0x1 << " + bed.clearNew + ");\n");
        if (bed.singleton) {
            result.append("  instance.flags &= ~((" + bed.localFlagType + ") 0x1 << " + bed.newborn + ");\n");
        } else {
            result.append("  int count = instances.size ();\n");
            result.append("  for (int i = firstborn; i < count; i++)\n");
            result.append("  {\n");
            result.append("    " + ps + " * p = instances[i];\n");
            result.append("    if (p) p->flags &= ~((" + bed.localFlagType + ") 0x1 << " + bed.newborn + ");\n");
            result.append("  }\n");
            result.append("  firstborn = count;\n");
        }
        result.append("}\n");
        result.append("\n");
    }
    // Population getIterators
    if (s.connectionBindings != null) {
        class ConnectionHolder {

            public Operator k;

            public Operator min;

            public Operator max;

            public Operator radius;

            public boolean hasProject;

            public EquationSet endpoint;

            public List<Integer> indices = new ArrayList<Integer>();

            public List<Object> resolution;

            public boolean equivalent(Operator a, Operator b) {
                if (a == b)
                    return true;
                if (a == null || b == null)
                    return false;
                return a.equals(b);
            }

            public boolean equals(Object o) {
                // This is a safe assumption, since this is a local class.
                ConnectionHolder that = (ConnectionHolder) o;
                return equivalent(k, that.k) && equivalent(min, that.min) && equivalent(max, that.max) && equivalent(radius, that.radius) && hasProject == that.hasProject && endpoint == that.endpoint;
            }

            public void emit() {
                for (Integer index : indices) {
                    result.append("    case " + index + ":\n");
                }
                result.append("    {\n");
                if (k == null && radius == null) {
                    result.append("      result = new ConnectPopulation<" + T + "> (i);\n");
                } else {
                    // Pulls in KDTree dependencies, for full NN support.
                    result.append("      result = new ConnectPopulationNN<" + T + "> (i);\n");
                }
                boolean testK = false;
                boolean testRadius = false;
                boolean constantKR = false;
                if (k != null) {
                    result.append("      result->k = ");
                    k.render(context);
                    result.append(";\n");
                    testK = true;
                    if (k instanceof Constant) {
                        Constant c = (Constant) k;
                        if (c.value instanceof Scalar && ((Scalar) c.value).value != 0)
                            constantKR = true;
                    }
                }
                if (max != null) {
                    result.append("      result->Max = ");
                    max.render(context);
                    result.append(";\n");
                }
                if (min != null) {
                    result.append("      result->Min = ");
                    min.render(context);
                    result.append(";\n");
                }
                if (radius != null) {
                    result.append("      result->radius = ");
                    radius.render(context);
                    result.append(";\n");
                    testRadius = true;
                    if (radius instanceof Constant) {
                        Constant c = (Constant) radius;
                        if (c.value instanceof Scalar && ((Scalar) c.value).value != 0)
                            constantKR = true;
                    }
                }
                if (hasProject) {
                    result.append("      result->rank += 1;");
                }
                if (constantKR) {
                    result.append("      result->rank -= 2;\n");
                } else {
                    if (testK && testRadius) {
                        result.append("      if (result->k > 0  ||  result->radius > 0) result->rank -= 2;\n");
                    } else if (testK) {
                        result.append("      if (result->k > 0) result->rank -= 2;\n");
                    } else if (testRadius) {
                        result.append("      if (result->radius > 0) result->rank -= 2;\n");
                    }
                }
                assembleInstances(s, "", resolution, 0, "      ", result);
                result.append("      result->size = result->instances->size ();\n");
                result.append("      break;\n");
                result.append("    }\n");
            }
        }
        List<ConnectionHolder> connections = new ArrayList<ConnectionHolder>();
        // TODO: Should determine this across the entire simulation, so that only one of getIteratorsSimple() or getIteratorsNN() is linked.
        boolean needNN = false;
        for (ConnectionBinding c : s.connectionBindings) {
            ConnectionHolder h = new ConnectionHolder();
            Variable v = s.find(new Variable(c.alias + ".$k"));
            EquationEntry e = null;
            if (v != null)
                e = v.equations.first();
            if (e != null)
                h.k = e.expression;
            v = s.find(new Variable(c.alias + ".$max"));
            e = null;
            if (v != null)
                e = v.equations.first();
            if (e != null)
                h.max = e.expression;
            v = s.find(new Variable(c.alias + ".$min"));
            e = null;
            if (v != null)
                e = v.equations.first();
            if (e != null)
                h.min = e.expression;
            v = s.find(new Variable(c.alias + ".$radius"));
            e = null;
            if (v != null)
                e = v.equations.first();
            if (e != null)
                h.radius = e.expression;
            h.hasProject = s.find(new Variable(c.alias + ".$project")) != null;
            h.endpoint = c.endpoint;
            int i = connections.indexOf(h);
            if (i < 0) {
                connections.add(h);
                h.resolution = c.resolution;
            } else {
                h = connections.get(i);
            }
            h.indices.add(c.index);
            if (h.k != null || h.radius != null)
                needNN = true;
        }
        result.append("ConnectIterator<" + T + "> * " + ns + "getIterators ()\n");
        result.append("{\n");
        if (s.connectionMatrix == null) {
            if (needNN) {
                result.append("  return getIteratorsNN ();\n");
            } else {
                result.append("  return getIteratorsSimple ();\n");
            }
        } else {
            ConnectionMatrix cm = s.connectionMatrix;
            result.append("  ConnectPopulation<" + T + "> * rows = getIterator (" + cm.rows.index + ");\n");
            result.append("  ConnectPopulation<" + T + "> * cols = getIterator (" + cm.cols.index + ");\n");
            // Will be deleted when ConnectMatrix is deleted.
            result.append("  " + ps + " * dummy = (" + ps + " *) create ();\n");
            result.append("  dummy->setPart (" + cm.rows.index + ", (*rows->instances)[0]);\n");
            result.append("  dummy->setPart (" + cm.cols.index + ", (*cols->instances)[0]);\n");
            // We don't actually want $p. This just forces "dummy" to initialize any local matrix variables.
            result.append("  dummy->getP ();\n");
            // Create iterator
            result.append("  IteratorNonzero<" + T + "> * it = ");
            boolean found = false;
            for (ProvideOperator po : extensions) {
                if (po.getIterator(cm.A, context)) {
                    found = true;
                    break;
                }
            }
            if (!found && cm.A instanceof AccessElement) {
                AccessElement ae = (AccessElement) cm.A;
                Operator op0 = ae.operands[0];
                result.append("::getIterator (");
                if (op0 instanceof AccessVariable) {
                    AccessVariable av = (AccessVariable) op0;
                    Variable v = av.reference.variable;
                    if (v.hasAttribute("temporary")) {
                        // Just assume that v is an alias for ReadMatrix.
                        // Also, matrix must be a static object. Enforced by AccessElement.hasCorrectForm().
                        ReadMatrix r = (ReadMatrix) v.equations.first().expression;
                        result.append(r.name + "->A");
                    } else {
                        result.append("& ");
                        context.global = false;
                        result.append(resolve(av.reference, context, false, "dummy->", false));
                        context.global = true;
                    }
                } else // Must be a constant. Enforced by AccessElement.hasCorrectForm().
                {
                    Constant c = (Constant) op0;
                    result.append(c.name);
                }
                result.append(");\n");
            }
            result.append("  return new ConnectMatrix<" + T + "> (rows, cols, " + cm.rows.index + ", " + cm.cols.index + ", it, dummy);\n");
        }
        result.append("}\n");
        result.append("\n");
        result.append("ConnectPopulation<" + T + "> * " + ns + "getIterator (int i)\n");
        result.append("{\n");
        result.append("  ConnectPopulation<" + T + "> * result = 0;\n");
        result.append("  switch (i)\n");
        result.append("  {\n");
        for (ConnectionHolder h : connections) h.emit();
        result.append("  }\n");
        result.append("  return result;\n");
        result.append("}\n");
        result.append("\n");
    }
    // Population path
    if (bed.needGlobalPath) {
        result.append("void " + ns + "path (String & result)\n");
        result.append("{\n");
        if (// Will our container provide a non-empty path?
        ((BackendDataC) s.container.backendData).needLocalPath) {
            result.append("  container->path (result);\n");
            result.append("  result += \"." + s.name + "\";\n");
        } else {
            result.append("  result = \"" + s.name + "\";\n");
        }
        result.append("}\n");
        result.append("\n");
    }
}
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) AccessVariable(gov.sandia.n2a.language.AccessVariable) Constant(gov.sandia.n2a.language.Constant) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) ArrayList(java.util.ArrayList) ExtensionPoint(gov.sandia.n2a.plugins.ExtensionPoint) ReadMatrix(gov.sandia.n2a.language.function.ReadMatrix) Scalar(gov.sandia.n2a.language.type.Scalar) ConnectionMatrix(gov.sandia.n2a.eqset.EquationSet.ConnectionMatrix) List(java.util.List) ArrayList(java.util.ArrayList) AccessElement(gov.sandia.n2a.language.AccessElement) EquationEntry(gov.sandia.n2a.eqset.EquationEntry)

Example 3 with ConnectionMatrix

use of gov.sandia.n2a.eqset.EquationSet.ConnectionMatrix in project n2a by frothga.

the class Population method getIterators.

public ConnectIterator getIterators(Simulator simulator, boolean poll) {
    InternalBackendData bed = (InternalBackendData) equations.backendData;
    int count = equations.connectionBindings.size();
    ArrayList<ConnectPopulation> iterators = new ArrayList<ConnectPopulation>(count);
    boolean nothingNew = true;
    boolean spatialFiltering = false;
    for (int i = 0; i < count; i++) {
        ConnectionBinding target = equations.connectionBindings.get(i);
        ConnectPopulation it = new ConnectPopulation(i, target, bed, simulator, poll);
        // Nothing to connect. This should never happen.
        if (it.instances == null || it.instances.size() == 0)
            return null;
        iterators.add(it);
        if (it.firstborn < it.size)
            nothingNew = false;
        if (it.k > 0 || it.radius > 0)
            spatialFiltering = true;
    }
    if (nothingNew && !poll)
        return null;
    ConnectionMatrix cm = equations.connectionMatrix;
    if (// Use sparse-matrix optimization
    cm != null) {
        // cm takes precedence over any other iteration method.
        return new ConnectMatrix(cm, iterators.get(cm.rows.index), iterators.get(cm.cols.index), simulator);
    }
    // That allows the most number of old entries to be skipped.
    if (!poll) {
        // This is a simple insertion sort ...
        for (int i = 1; i < count; i++) {
            for (int j = i; j > 0; j--) {
                ConnectPopulation A = iterators.get(j - 1);
                ConnectPopulation B = iterators.get(j);
                if (A.firstborn >= B.firstborn)
                    break;
                iterators.set(j - 1, B);
                iterators.set(j, A);
            }
        }
    }
    // For spatial filtering, make the innermost iterator be the one that best defines C.$xyz
    if (spatialFiltering) {
        double[] xyz = new double[3];
        for (int i = 0; i < count; i++) iterators.get(i).xyz = xyz;
        if (// connection's own $xyz is not defined, so must get it from some $project
        bed.xyz == null || bed.xyz.equations.size() == 0) {
            int last = count - 1;
            ConnectPopulation A = iterators.get(last);
            int bestIndex = last;
            double bestRank = A.rank;
            for (int i = 0; i < last; i++) {
                A = iterators.get(i);
                if (A.rank > bestRank) {
                    bestIndex = i;
                    bestRank = A.rank;
                }
            }
            if (bestIndex != last) {
                A = iterators.remove(bestIndex);
                iterators.add(A);
            }
        }
    }
    for (int i = 1; i < count; i++) {
        ConnectPopulation A = iterators.get(i - 1);
        ConnectPopulation B = iterators.get(i);
        A.permute = B;
        B.contained = true;
        if (A.k > 0 || A.radius > 0)
            A.prepareNN();
    }
    return iterators.get(0);
}
Also used : ConnectionMatrix(gov.sandia.n2a.eqset.EquationSet.ConnectionMatrix) ConnectionBinding(gov.sandia.n2a.eqset.EquationSet.ConnectionBinding) ArrayList(java.util.ArrayList)

Aggregations

ConnectionBinding (gov.sandia.n2a.eqset.EquationSet.ConnectionBinding)3 ConnectionMatrix (gov.sandia.n2a.eqset.EquationSet.ConnectionMatrix)3 ArrayList (java.util.ArrayList)3 EquationEntry (gov.sandia.n2a.eqset.EquationEntry)2 EquationSet (gov.sandia.n2a.eqset.EquationSet)2 Variable (gov.sandia.n2a.eqset.Variable)2 AccessVariable (gov.sandia.n2a.language.AccessVariable)2 Scalar (gov.sandia.n2a.language.type.Scalar)2 ExtensionPoint (gov.sandia.n2a.plugins.ExtensionPoint)2 EventSource (gov.sandia.n2a.backend.internal.InternalBackendData.EventSource)1 EventTarget (gov.sandia.n2a.backend.internal.InternalBackendData.EventTarget)1 Conversion (gov.sandia.n2a.eqset.EquationSet.Conversion)1 VariableReference (gov.sandia.n2a.eqset.VariableReference)1 AccessElement (gov.sandia.n2a.language.AccessElement)1 Constant (gov.sandia.n2a.language.Constant)1 Operator (gov.sandia.n2a.language.Operator)1 ReadMatrix (gov.sandia.n2a.language.function.ReadMatrix)1 AbortRun (gov.sandia.n2a.plugins.extpoints.Backend.AbortRun)1 List (java.util.List)1 TreeSet (java.util.TreeSet)1