use of gov.sandia.n2a.language.EvaluationException in project n2a by frothga.
the class InternalBackendData method analyze.
public void analyze(final EquationSet s) {
System.out.println(s.name);
if (s.connectionBindings != null) {
// Note that populations have already been allocated in the constructor.
endpoints = countLocalObject;
countLocalObject += s.connectionBindings.size();
}
for (// we want the sub-lists to be ordered correctly
Variable v : // we want the sub-lists to be ordered correctly
s.ordered) {
String className = "null";
if (v.type != null)
className = v.type.getClass().getSimpleName();
System.out.println(" " + v.nameString() + " " + v.attributeString() + " " + className);
if (v.name.equals("$index"))
index = v;
else if (v.name.equals("$init"))
init = v;
else if (v.name.equals("$live"))
live = v;
else if (v.name.equals("$n") && v.order == 0)
n = v;
else if (v.name.equals("$p") && v.order == 0)
p = v;
else if (v.name.equals("$type"))
type = v;
else if (v.name.equals("$xyz") && v.order == 0)
xyz = v;
else if (v.name.equals("$t")) {
if (v.order == 0)
t = v;
else if (v.order == 1)
dt = v;
}
if (v.hasAttribute("global")) {
v.global = true;
v.visit(new Visitor() {
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
if (av.reference.resolution.size() > 0)
addReferenceGlobal(av.reference, s);
return false;
}
if (op instanceof Output) {
Output o = (Output) op;
if (o.operands.length < 3) {
o.index = countGlobalObject++;
namesGlobalObject.add("columnName" + o.index);
}
// Continue descent, because parameters of output() may contain variable references
return true;
}
return true;
}
});
if (// eliminate non-computed values, unless they refer to a variable outside the immediate equation set
!v.hasAny(new String[] { "constant", "accessor", "readOnly" }) || v.hasAll(new String[] { "constant", "reference" })) {
boolean initOnly = v.hasAttribute("initOnly");
boolean updates = !initOnly && v.equations.size() > 0 && (v.derivative == null || v.hasAttribute("updates"));
if (updates)
globalUpdate.add(v);
if (v.hasAttribute("reference")) {
addReferenceGlobal(v.reference, s);
} else {
boolean temporary = v.hasAttribute("temporary");
if (!temporary || v.hasUsers())
globalInit.add(v);
if (!temporary && !v.hasAttribute("dummy")) {
if (!v.hasAttribute("preexistent"))
globalMembers.add(v);
boolean external = false;
if (v.hasAttribute("externalWrite") || v.assignment != Variable.REPLACE) {
external = true;
globalBufferedExternalWrite.add(v);
}
if (external || (v.hasAttribute("externalRead") && updates)) {
external = true;
globalBufferedExternal.add(v);
}
if (external || v.hasAttribute("cycle")) {
globalBuffered.add(v);
if (!external) {
globalBufferedInternal.add(v);
if (!initOnly)
globalBufferedInternalUpdate.add(v);
}
}
}
}
}
} else // local
{
v.visit(new Visitor() {
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
if (av.reference.resolution.size() > 0)
addReferenceLocal(av.reference, s);
return false;
}
if (op instanceof Output) {
Output o = (Output) op;
if (o.operands.length < 3) {
o.index = countLocalObject++;
namesLocalObject.add("columnName" + o.index);
}
// Continue descent, because parameters of output() may contain variable references
return true;
}
return true;
}
});
if (!v.hasAny(new String[] { "constant", "accessor", "readOnly" }) || v.hasAll(new String[] { "constant", "reference" })) {
boolean initOnly = v.hasAttribute("initOnly");
boolean updates = !initOnly && v.equations.size() > 0 && (v.derivative == null || v.hasAttribute("updates"));
if (updates)
localUpdate.add(v);
if (v.hasAttribute("reference")) {
addReferenceLocal(v.reference, s);
} else {
boolean temporary = v.hasAttribute("temporary");
if (!temporary || v.hasUsers()) {
if (v.name.startsWith("$") || (temporary && v.neededBySpecial())) {
if (!v.name.equals("$index") && !v.name.equals("$live"))
localInitSpecial.add(v);
} else {
localInitRegular.add(v);
}
}
if (!temporary && !v.hasAttribute("dummy")) {
if (!v.hasAttribute("preexistent"))
localMembers.add(v);
boolean external = false;
if (v.hasAttribute("externalWrite") || v.assignment != Variable.REPLACE) {
external = true;
localBufferedExternalWrite.add(v);
}
if (external || (v.hasAttribute("externalRead") && updates)) {
external = true;
localBufferedExternal.add(v);
}
if (external || v.hasAttribute("cycle")) {
if (v.name.startsWith("$"))
localBufferedSpecial.add(v);
else
localBufferedRegular.add(v);
if (// v got here only by being a "cycle", not "externalRead" or "externalWrite"
!external) {
localBufferedInternal.add(v);
if (!initOnly)
localBufferedInternalUpdate.add(v);
}
}
}
}
}
}
}
for (// we need these to be in order by differential level, not by dependency
Variable v : // we need these to be in order by differential level, not by dependency
s.variables) {
if (v.derivative != null && !v.hasAny(new String[] { "constant", "initOnly" })) {
if (v.hasAttribute("global"))
globalIntegrated.add(v);
else
localIntegrated.add(v);
}
}
populationCanGrowOrDie = s.lethalP || s.lethalType || s.canGrow();
if (n != null) {
populationCanResize = globalMembers.contains(n);
// See EquationSet.forceTemporaryStorageForSpecials() for a related issue.
if (!populationCanResize && populationCanGrowOrDie && n.hasUsers()) {
Backend.err.get().println("WARNING: $n can change (due to structural dynamics) but it was detected as a constant. Equations that depend on $n may give incorrect results.");
}
}
if (index != null) {
indexNext = countGlobalFloat++;
namesGlobalFloat.add("indexNext");
indexAvailable = countGlobalObject++;
namesGlobalObject.add("indexAvailable");
}
if (// track instances
s.connected || s.needInstanceTracking || populationCanResize) {
// The reason populationCanResize forces use of the instances array is to enable pruning of parts when $n decreases.
instances = countGlobalObject++;
namesGlobalObject.add("instances");
if (// in addition, track newly created instances
s.connected) {
firstborn = countGlobalFloat++;
namesGlobalFloat.add("firstborn");
newborn = countLocalFloat++;
namesLocalFloat.add("newborn");
}
}
if (p != null) {
Pdependencies = new ArrayList<Variable>();
for (Variable t : s.ordered) {
if (t.hasAttribute("temporary") && p.dependsOn(t) != null) {
Pdependencies.add(t);
}
}
}
populationIndex = 0;
if (// check for null specifically to guard against the Wrapper equation set (which is not fully constructed)
s.container != null && s.container.parts != null) {
for (EquationSet p : s.container.parts) {
if (p == s)
break;
populationIndex++;
}
}
if (// connection-specific stuff
s.connectionBindings != null) {
int size = s.connectionBindings.size();
// endpoints is allocated at the top of this function, because it is needed for reference handling in the variable analysis loop
projectDependencies = new Object[size];
projectReferences = new Object[size];
count = new int[size];
k = new Variable[size];
max = new Variable[size];
min = new Variable[size];
project = new Variable[size];
radius = new Variable[size];
for (int i = 0; i < s.connectionBindings.size(); i++) {
ConnectionBinding c = s.connectionBindings.get(i);
count[i] = -1;
k[i] = s.find(new Variable(c.alias + ".$k"));
max[i] = s.find(new Variable(c.alias + ".$max"));
min[i] = s.find(new Variable(c.alias + ".$min"));
project[i] = s.find(new Variable(c.alias + ".$project"));
radius[i] = s.find(new Variable(c.alias + ".$radius"));
if (c.endpoint.accountableConnections != null) {
AccountableConnection query = new AccountableConnection(s, c.alias);
AccountableConnection ac = c.endpoint.accountableConnections.floor(query);
if (// Only true if this endpoint is accountable.
ac.equals(query)) {
// Allocate space for counter in target part
InternalBackendData endpointBed = (InternalBackendData) c.endpoint.backendData;
count[i] = endpointBed.countLocalFloat++;
endpointBed.namesLocalFloat.add(s.prefix() + ".$count");
if (// $count is referenced explicitly, so need to finish setting it up
ac.count != null) {
ac.count.readIndex = ac.count.writeIndex = count[i];
}
}
}
// Note that countLocalObject has already been incremented above
namesLocalObject.add(c.alias);
if (project[i] != null) {
ArrayList<Variable> dependencies = new ArrayList<Variable>();
// Always assign, even if empty.
projectDependencies[i] = dependencies;
for (Variable t : s.ordered) {
if (t.hasAttribute("temporary") && project[i].dependsOn(t) != null) {
dependencies.add(t);
}
}
final TreeSet<VariableReference> references = new TreeSet<VariableReference>(referenceComparator);
class ProjectVisitor extends Visitor {
public boolean visit(Operator op) {
if (op instanceof AccessVariable) {
AccessVariable av = (AccessVariable) op;
if (av.reference.resolution.size() > 0)
references.add(av.reference);
return false;
}
return true;
}
}
ProjectVisitor visitor = new ProjectVisitor();
project[i].visit(visitor);
for (Variable v : dependencies) v.visit(visitor);
if (references.size() > 0)
projectReferences[i] = references;
}
c.resolution = translateResolution(c.resolution, s);
}
}
// Locals
for (Variable v : localMembers) {
// in the type array rather than the float array.
if (v.type instanceof Scalar && v.reference.variable == v) {
v.readIndex = v.writeIndex = countLocalFloat++;
namesLocalFloat.add(v.nameString());
} else {
v.readIndex = v.writeIndex = countLocalObject++;
namesLocalObject.add(v.nameString());
}
}
for (Variable v : localBufferedExternal) {
if (v.type instanceof Scalar && v.reference.variable == v) {
v.writeIndex = countLocalFloat++;
namesLocalFloat.add("next_" + v.nameString());
} else {
v.writeIndex = countLocalObject++;
namesLocalObject.add("next_" + v.nameString());
}
}
for (Variable v : localBufferedInternal) {
v.writeTemp = true;
if (v.type instanceof Scalar && v.reference.variable == v) {
v.writeIndex = countLocalTempFloat++;
namesLocalTempFloat.add("next_" + v.nameString());
} else {
v.writeIndex = countLocalTempObject++;
namesLocalTempObject.add("next_" + v.nameString());
}
}
// Globals
for (Variable v : globalMembers) {
if (v.type instanceof Scalar && v.reference.variable == v) {
v.readIndex = v.writeIndex = countGlobalFloat++;
namesGlobalFloat.add(v.nameString());
} else {
v.readIndex = v.writeIndex = countGlobalObject++;
namesGlobalObject.add(v.nameString());
}
}
for (Variable v : globalBufferedExternal) {
if (v.type instanceof Scalar && v.reference.variable == v) {
v.writeIndex = countGlobalFloat++;
namesGlobalFloat.add("next_" + v.nameString());
} else {
v.writeIndex = countGlobalObject++;
namesGlobalObject.add("next_" + v.nameString());
}
}
for (Variable v : globalBufferedInternal) {
v.writeTemp = true;
if (v.type instanceof Scalar && v.reference.variable == v) {
v.writeIndex = countGlobalTempFloat++;
namesGlobalTempFloat.add("next_" + v.nameString());
} else {
v.writeIndex = countGlobalTempObject++;
namesGlobalTempObject.add("next_" + v.nameString());
}
}
// fully temporary values
for (Variable v : s.variables) {
if (!v.hasAttribute("temporary"))
continue;
v.readTemp = v.writeTemp = true;
if (v.hasAttribute("global")) {
if (v.type instanceof Scalar && v.reference.variable == v) {
v.readIndex = v.writeIndex = countGlobalTempFloat++;
namesGlobalTempFloat.add(v.nameString());
} else {
v.readIndex = v.writeIndex = countGlobalTempObject++;
namesGlobalTempObject.add(v.nameString());
}
} else {
if (v.type instanceof Scalar && v.reference.variable == v) {
v.readIndex = v.writeIndex = countLocalTempFloat++;
namesLocalTempFloat.add(v.nameString());
} else {
v.readIndex = v.writeIndex = countLocalTempObject++;
namesLocalTempObject.add(v.nameString());
}
}
}
if (live.hasAttribute("constant"))
liveStorage = LIVE_CONSTANT;
else if (live.hasAttribute("accessor"))
liveStorage = LIVE_ACCESSOR;
else
// $live is "initOnly"
liveStorage = LIVE_STORED;
for (VariableReference r : localReference) r.resolution = translateResolution(r.resolution, s);
for (VariableReference r : globalReference) r.resolution = translateResolution(r.resolution, s);
// Type conversions
String[] forbiddenAttributes = new String[] { "global", "constant", "accessor", "reference", "temporary", "dummy", "preexistent" };
for (EquationSet target : s.getConversionTargets()) {
if (s.connectionBindings == null) {
if (target.connectionBindings != null)
throw new EvaluationException("Can't change $type from compartment to connection.");
} else {
if (target.connectionBindings == null)
throw new EvaluationException("Can't change $type from connection to compartment.");
}
Conversion conversion = new Conversion();
conversions.put(target, conversion);
// Match variables
for (Variable v : target.variables) {
if (v.name.equals("$type"))
continue;
if (v.hasAny(forbiddenAttributes))
continue;
Variable v2 = s.find(v);
if (v2 != null && v2.equals(v)) {
conversion.to.add(v);
conversion.from.add(v2);
}
}
// Match connection bindings
if (// Since we checked above, we know that target is also a connection.
s.connectionBindings != null) {
conversion.bindings = new int[s.connectionBindings.size()];
int i = 0;
for (ConnectionBinding c : s.connectionBindings) {
conversion.bindings[i] = -1;
int j = 0;
for (ConnectionBinding d : target.connectionBindings) {
if (c.alias.equals(d.alias)) {
conversion.bindings[i] = j;
break;
}
j++;
}
// Note: ALL bindings must match. There is no other mechanism for initializing the endpoints.
if (conversion.bindings[i] < 0)
throw new EvaluationException("Unfulfilled connection binding during $type change.");
i++;
}
}
// TODO: Match populations?
// Currently, any contained populations do not carry over to new instance. Instead, it must create them from scratch.
}
}
use of gov.sandia.n2a.language.EvaluationException in project n2a by frothga.
the class InternalBackendData method translateResolution.
/**
* Convert resolution to a form that can be processed quickly at runtime.
*/
public ArrayList<Object> translateResolution(ArrayList<Object> resolution, EquationSet current) {
ArrayList<Object> newResolution = new ArrayList<Object>();
Iterator<Object> it = resolution.iterator();
while (it.hasNext()) {
Object o = it.next();
if (// We are following the containment hierarchy.
o instanceof EquationSet) {
EquationSet next = (EquationSet) o;
if (// ascend to our container
next == current.container) {
newResolution.add(new ResolveContainer());
} else // descend to one of our contained populations
{
int i = 0;
for (EquationSet p : current.parts) {
if (p == next) {
newResolution.add(new ResolvePart(i));
break;
}
i++;
}
if (i >= current.parts.size())
throw new EvaluationException("Could not find connection target.");
}
current = next;
} else if (// We are following a part reference, which means "current" is a connection.
o instanceof ConnectionBinding) {
ConnectionBinding c = (ConnectionBinding) o;
InternalBackendData bed = (InternalBackendData) current.backendData;
newResolution.add(new ResolvePart(bed.endpoints + c.index));
current = c.endpoint;
}
}
return newResolution;
}
use of gov.sandia.n2a.language.EvaluationException in project n2a by frothga.
the class Matrix method NOT.
public Type NOT() throws EvaluationException {
int w = columns();
int h = rows();
// should create pseudo-inverse
if (h != w)
throw new EvaluationException("Can't invert non-square matrix (because we don't know about pseudo-inverse).");
if (h == 1)
return new Scalar(1 / get(0, 0));
if (h == 2) {
MatrixDense result = new MatrixDense(2, 2);
double q = determinant();
if (q == 0)
throw new EvaluationException("invert: Matrix is singular!");
result.value[0][0] = get(1, 1) / q;
result.value[0][1] = get(1, 0) / -q;
result.value[1][0] = get(0, 1) / -q;
result.value[1][1] = get(0, 0) / q;
return result;
}
if (h == 3) {
MatrixDense result = new MatrixDense(3, 3);
double q = determinant();
if (q == 0)
throw new EvaluationException("invert: Matrix is singular!");
result.value[0][0] = det22(1, 2, 1, 2) / q;
result.value[0][1] = det22(1, 2, 2, 0) / q;
result.value[0][2] = det22(1, 2, 0, 1) / q;
result.value[1][0] = det22(0, 2, 2, 1) / q;
result.value[1][1] = det22(0, 2, 0, 2) / q;
result.value[1][2] = det22(0, 2, 1, 0) / q;
result.value[2][0] = det22(0, 1, 1, 2) / q;
result.value[2][1] = det22(0, 1, 2, 0) / q;
result.value[2][2] = det22(0, 1, 0, 1) / q;
return result;
}
throw new EvaluationException("Can't invert matrices larger then 3x3 (because we are not using a good numerical library).");
}
use of gov.sandia.n2a.language.EvaluationException in project n2a by frothga.
the class MatrixDense method load.
public void load(Reader stream, boolean units) throws EvaluationException {
try {
ArrayList<ArrayList<Double>> temp = new ArrayList<ArrayList<Double>>();
ArrayList<Double> row = new ArrayList<Double>();
int columns = 0;
boolean transpose = false;
// Scan for opening "["
char token;
do {
token = (char) stream.read();
if (token == '~')
transpose = true;
} while (token != '[' && stream.ready());
// Read rows until closing "]"
// for one floating-point number, so far more than enough
char[] buffer = new char[1024];
int index = 0;
boolean done = false;
while (stream.ready() && !done) {
token = (char) stream.read();
switch(token) {
case '\r':
// ignore CR characters
break;
case ' ':
case '\t':
// ignore leading whitespace (equivalent to trim)
if (index == 0)
break;
case ',':
// Process element
if (index == 0) {
row.add(0.0);
} else {
String value = String.valueOf(buffer, 0, index);
index = 0;
if (units)
row.add(Scalar.convert(value));
else
row.add(Double.valueOf(value));
}
break;
case ']':
done = true;
case ';':
case '\n':
// Process any final element
if (index > 0) {
String value = String.valueOf(buffer, 0, index);
index = 0;
if (units)
row.add(Scalar.convert(value));
else
row.add(Double.valueOf(value));
}
// Process line
int c = row.size();
if (c > 0) {
temp.add(row);
columns = Math.max(columns, c);
row = new ArrayList<Double>(columns);
}
break;
default:
// If we overrun the buffer, we should automatically get an index out of range error.
buffer[index++] = token;
}
}
// Assign elements to "value"
int rows = temp.size();
if (transpose) {
value = new double[rows][columns];
for (int r = 0; r < rows; r++) {
row = temp.get(r);
for (int c = 0; c < row.size(); c++) {
value[r][c] = row.get(c);
}
}
} else {
value = new double[columns][rows];
for (int r = 0; r < rows; r++) {
row = temp.get(r);
for (int c = 0; c < row.size(); c++) {
value[c][r] = row.get(c);
}
}
}
if (value.length == 0 || value[1].length == 0)
throw new EvaluationException("Empty matrix");
} catch (IOException error) {
throw new EvaluationException("Failed to convert input to matrix");
}
}
use of gov.sandia.n2a.language.EvaluationException in project n2a by frothga.
the class MatrixDense method determinant.
public double determinant() throws EvaluationException {
int w = value.length;
int h = value[0].length;
if (h != w)
throw new EvaluationException("Can't compute determinant of non-square matrix.");
if (h == 1)
return value[0][0];
if (h == 2)
return value[0][0] * value[1][1] - value[0][1] * value[1][0];
if (h == 3) {
return value[0][0] * value[1][1] * value[2][2] - value[0][0] * value[2][1] * value[1][2] - value[1][0] * value[0][1] * value[2][2] + value[1][0] * value[2][1] * value[0][2] + value[2][0] * value[0][1] * value[1][2] - value[2][0] * value[1][1] * value[0][2];
}
throw new EvaluationException("Can't compute deteminant of matrices larger then 3x3 (because we are lazy).");
}
Aggregations