-
Amira Abdel-Rahman authoredAmira Abdel-Rahman authored
utils.js 6.32 KiB
// Amira Abdel-Rahman
// (c) Massachusetts Institute of Technology 2019
////////////utils/////////////////////
function map (value, x1, y1, x2, y2) {
return (value - x1) * (y2 - x2) / (y1 - x1) + x2;
}
function enforceBounds(x) {
if (x < 0) {
return 0;
} else if (x > 1){
return 1;
} else {
return x;
}
}
function interpolateLinearly(x, values) {
// Split values into four lists
var x_values = [];
var r_values = [];
var g_values = [];
var b_values = [];
for (i in values) {
x_values.push(values[i][0]);
r_values.push(values[i][1][0]);
g_values.push(values[i][1][1]);
b_values.push(values[i][1][2]);
}
var i = 1;
while (x_values[i] < x) {
i = i+1;
}
i = i-1;
var width = Math.abs(x_values[i] - x_values[i+1]);
var scaling_factor = (x - x_values[i]) / width;
// Get the new color values though interpolation
var r = r_values[i] + scaling_factor * (r_values[i+1] - r_values[i])
var g = g_values[i] + scaling_factor * (g_values[i+1] - g_values[i])
var b = b_values[i] + scaling_factor * (b_values[i+1] - b_values[i])
return [enforceBounds(r), enforceBounds(g), enforceBounds(b)];
}
function getColor(viz,stress){
var val=map(stress,viz.minStress,viz.maxStress,1.0,0.0);
color=interpolateLinearly(val, viz.colorMaps[viz.colorMap]);
return new THREE.Color(color[0],color[1],color[2]).getHex();
}
function toThreeVec(point){
return new THREE.Vector3(point.x,point.y,point.z);
}
function toPosition(array){
return { x:array[0] ,y:array[1],z:array[2]};
}
function toTf3D(point){
return tf.tensor([point.x,point.y,point.z]);
}
function toPos(point){
return { x:point.x ,y:point.y,z:point.z};
}
function tf_delete(tensor,remove_indices,axis){
var unstacked=tf.unstack(tensor,axis);
var newTensor=[];
for(var i=0;i<unstacked.length;i++){
if(!remove_indices.includes(i)){
newTensor.push(unstacked[i]);
}
}
return tf.stack(newTensor,axis);
}
function add(p1,p2){
return {x:p1.x+p2.x,y:p1.y+p2.y,z:p1.z+p2.z};
}
//////////nodes///////////////
function nodeAt(setup,pos){
var tolerance=1e-6;
return setup.nodes.find(node =>
(node.position.x>pos.x-tolerance && node.position.x<pos.x+tolerance) &&
(node.position.y>pos.y-tolerance && node.position.y<pos.y+tolerance) &&
(node.position.z>pos.z-tolerance && node.position.z<pos.z+tolerance)
);
return setup.nodes.find(node =>
(node.position.x==pos.x) &&
(node.position.y== pos.y) &&
(node.position.z== pos.z)
);
return setup.nodes.filter(node => node.position.x==pos.x && node.position.y== pos.y && node.position.z== pos.z);
}
function getNodebyName(setup,name){
return setup.nodes.find(node => node.name===name);
}
function edgeNeeded(setup,source,target){
var e=setup.edges.find(edge => (edge.source===source && edge.target===target) || (edge.source===target && edge.target===source));
var b=(typeof e === 'undefined');
return b;
}
//////////////
function updateDisplacement(X){
var count=0;
for(var i=0;i<setup.nodes.length;i++){
if(!setup.nodes[i].restrained_degrees_of_freedom[0]){
setup.nodes[i].displacement.x =X[count++];
}
if(!setup.nodes[i].restrained_degrees_of_freedom[1]){
setup.nodes[i].displacement.y =X[count++];
}
if(!setup.nodes[i].restrained_degrees_of_freedom[2]){
setup.nodes[i].displacement.z =X[count++];
}
if(!setup.bar){
if(!setup.nodes[i].restrained_degrees_of_freedom[3]){
setup.nodes[i].angle.x =X[count++];
}
if(!setup.nodes[i].restrained_degrees_of_freedom[4]){
setup.nodes[i].angle.y =X[count++];
}
if(!setup.nodes[i].restrained_degrees_of_freedom[5]){
setup.nodes[i].angle.z =X[count++];
}
}
}
}
function updateStresses(S){
setup.viz.minStress=Math.min(...S)*1.1;
setup.viz.maxStress=Math.max(...S)*1.1;
var count=0;
for(var ii=0;ii<setup.edges.length;ii++){
var element=setup.edges[ii];
element.stress=S[ii];
}
if(!node){
three.colorEdges(); //todo check!!
}
}
//////////inverse///////////////
// Lower Upper Solver
function lusolve(A, b, update) {
var lu = ludcmp(A, update)
if (lu === undefined){
console.log("Singular Matrix!")
return // Singular Matrix!
}
return lubksb(lu, b, update)
}
// Lower Upper Decomposition
function ludcmp(A, update) {
// A is a matrix that we want to decompose into Lower and Upper matrices.
var d = true;
var n = A.length;
// var n= A.shape[0];
var idx = new Array(n) // Output vector with row permutations from partial pivoting
var vv = new Array(n) // Scaling information
for (var i=0; i<n; i++) {
var max = 0
for (var j=0; j<n; j++) {
var temp = Math.abs(A[i][j])
if (temp > max) max = temp
}
if (max == 0) return // Singular Matrix!
vv[i] = 1 / max // Scaling
}
if (!update) { // make a copy of A
var Acpy = new Array(n)
for (var i=0; i<n; i++) {
var Ai = A[i]
Acpyi = new Array(Ai.length)
for (j=0; j<Ai.length; j+=1) Acpyi[j] = Ai[j]
Acpy[i] = Acpyi
}
A = Acpy
}
var tiny = 1e-20 // in case pivot element is zero
for (var i=0; ; i++) {
for (var j=0; j<i; j++) {
var sum = A[j][i]
for (var k=0; k<j; k++) sum -= A[j][k] * A[k][i];
A[j][i] = sum
}
var jmax = 0
var max = 0;
for (var j=i; j<n; j++) {
var sum = A[j][i]
for (var k=0; k<i; k++) sum -= A[j][k] * A[k][i];
A[j][i] = sum
var temp = vv[j] * Math.abs(sum)
if (temp >= max) {
max = temp
jmax = j
}
}
if (i <= jmax) {
for (var j=0; j<n; j++) {
var temp = A[jmax][j]
A[jmax][j] = A[i][j]
A[i][j] = temp
}
d = !d;
vv[jmax] = vv[i]
}
idx[i] = jmax;
if (i == n-1) break;
var temp = A[i][i]
if (temp == 0) A[i][i] = temp = tiny
temp = 1 / temp
for (var j=i+1; j<n; j++) A[j][i] *= temp
}
return {A:A, idx:idx, d:d}
}
// Lower Upper Back Substitution
function lubksb(lu, b, update) {
// solves the set of n linear equations A*x = b.
// lu is the object containing A, idx and d as determined by the routine ludcmp.
var A = lu.A
var idx = lu.idx
var n = idx.length
if (!update) { // make a copy of b
var bcpy = new Array(n)
for (var i=0; i<b.length; i+=1) bcpy[i] = b[i]
b = bcpy
}
for (var ii=-1, i=0; i<n; i++) {
var ix = idx[i]
var sum = b[ix]
b[ix] = b[i]
if (ii > -1)
for (var j=ii; j<i; j++) sum -= A[i][j] * b[j]
else if (sum)
ii = i
b[i] = sum
}
for (var i=n-1; i>=0; i--) {
var sum = b[i]
for (var j=i+1; j<n; j++) sum -= A[i][j] * b[j]
b[i] = sum / A[i][i]
}
return b // solution vector x
}