/** * Constructs tensors from the specified tensors. * @param t the tensors from which to copy eigenvectors and eigenvalues. */ public EigenTensors3(EigenTensors3 t) { this(t._n1,t._n2,t._n3,t._compressed); float[] a = new float[3]; float[] u = new float[3]; float[] w = new float[3]; for (int i3=0; i3<_n3; ++i3) { for (int i2=0; i2<_n2; ++i2) { for (int i1=0; i1<_n1; ++i1) { t.getEigenvalues(i1,i2,i3,a); t.getEigenvectorU(i1,i2,i3,u); t.getEigenvectorW(i1,i2,i3,w); setEigenvalues(i1,i2,i3,a); setEigenvectorU(i1,i2,i3,u); setEigenvectorW(i1,i2,i3,w); } } } }
/** * Gets tensor elements for specified indices. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @return a array {a11,a12,a13,a22,a23,a33} of tensor elements. */ public float[] getTensor(int i1, int i2, int i3) { float[] a = new float[6]; getTensor(i1,i2,i3,a); return a; }
/** * Sets tensor elements for specified indices. * This method first computes an eigen-decomposition of the specified * tensor, and then stores the computed eigenvectors and eigenvalues. * The eigenvalues are ordered such that au >= av >= aw >= 0. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @param a array {a11,a12,a13,a22,a23,a33} of tensor elements. */ public void setTensor(int i1, int i2, int i3, float[] a) { setTensor(i1,i2,i3,a[0],a[1],a[2],a[3],a[4],a[5]); }
/** * Gets the eigenvector v for the tensor with specified indices. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @param v array {v1,v2,v3} of eigenvector components. */ public void getEigenvectorV(int i1, int i2, int i3, float[] v) { float[] u = getEigenvectorU(i1,i2,i3); float[] w = getEigenvectorW(i1,i2,i3); v[0] = w[1]*u[2]-w[2]*u[1]; // v = w cross u v[1] = w[2]*u[0]-w[0]*u[2]; v[2] = w[0]*u[1]-w[1]*u[0]; }
/** * Inverts these tensors by inverting their eigenvalues. * Takes no care to avoid division by zero eigenvalues. */ public void invert() { float[] a = new float[3]; for (int i3=0; i3<_n3; ++i3) { for (int i2=0; i2<_n2; ++i2) { for (int i1=0; i1<_n1; ++i1) { getEigenvalues(i1,i2,i3,a); a[0] = 1.0f/a[0]; a[1] = 1.0f/a[1]; a[2] = 1.0f/a[2]; setEigenvalues(i1,i2,i3,a); } } } }
private static void testRandom( boolean compressed, double errorAngle, double errorValue, double errorTensor) { int n1 = 19, n2 = 20, n3 = 21; EigenTensors3 et = new EigenTensors3(n1,n2,n3,compressed); for (int i3=0; i3<n3; ++i3) { for (int i2=0; i2<n2; ++i2) { for (int i1=0; i1<n1; ++i1) { float[] a = makeRandomEigenvalues(); float[] u = makeRandomEigenvector(); float[] w = makeOrthogonalVector(u); et.setEigenvalues(i1,i2,i3,a); et.setEigenvectorU(i1,i2,i3,u); et.setEigenvectorW(i1,i2,i3,w); float[] c; c = et.getEigenvectorU(i1,i2,i3); checkEigenvectors(u,c,errorAngle); c = et.getEigenvectorW(i1,i2,i3); checkEigenvectors(w,c,errorAngle); c = et.getEigenvalues(i1,i2,i3); checkEigenvalues(a,c,errorValue); float[] t1 = et.getTensor(i1,i2,i3); et.setTensor(i1,i2,i3,t1); float[] t2 = et.getTensor(i1,i2,i3); checkTensors(t1,t2,errorTensor); } } } }
public static void demo3() { int n1 = 111; int n2 = 111; int n3 = 1; EigenTensors3 et = new EigenTensors3(n1,n2,n3,false); float eu = 0.01f, ev = 1.00f, ew = 1.00f; float u1 = 1.00f, u2 = 0.00f, u3 = 0.00f; float w1 = 0.00f, w2 = 0.00f, w3 = 1.00f; int i3 = 0; for (int i2=0; i2<n2; ++i2) { float a = i2*FLT_PI/2.0f/(n2-1); u1 = cos(a); u2 = sin(a); for (int i1=0; i1<n1; ++i1) { et.setEigenvalues(i1,i2,i3,eu,ev,ew); et.setEigenvectorU(i1,i2,i3,u1,u2,u3); et.setEigenvectorW(i1,i2,i3,w1,w2,w3); } } TensorsPanel tp = new TensorsPanel(et); AxisAlignedQuad aaq = new AxisAlignedQuad(Axis.X, new Point3(i3, 0, 0), new Point3(i3,n2-1,n1-1)); aaq.getFrame().addChild(tp); show(aaq); }
float u1i = u1[i3][i2][i1]; float u2i = u2[i3][i2][i1]; float u3i = c3(u1i,u2i); float w1i = w1[i3][i2][i1]; float w2i = w2[i3][i2][i1]; float w3i = c3(w1i,w2i); setEigenvalues(i1,i2,i3,aui,avi,awi); setEigenvectorU(i1,i2,i3,u1i,u2i,u3i); setEigenvectorW(i1,i2,i3,w1i,w2i,w3i);
float av = (float)ev[1]; if (av<0.0f) av = 0.0f; float aw = (float)ev[2]; if (aw<0.0f) aw = 0.0f; setEigenvectorU(i1,i2,i3,u1,u2,u3); setEigenvectorW(i1,i2,i3,w1,w2,w3); setEigenvalues(i1,i2,i3,au,av,aw);
float zc = (float)(fz+iz*dz); if (zmin<zc-dzmax && zc+dzmax<zmax) { float[] e = _et.getEigenvalues(iz,iy,ix); float[] u = _et.getEigenvectorU(iz,iy,ix); float[] v = _et.getEigenvectorV(iz,iy,ix); float[] w = _et.getEigenvectorW(iz,iy,ix); float eu = e[0], ev = e[1], ew = e[2]; if (eu<=etiny) eu = etiny; float zc = (float)(fz+iz*dz); if (zmin<zc-dzmax && zc+dzmax<zmax) { float[] e = _et.getEigenvalues(iz,iy,ix); float[] u = _et.getEigenvectorU(iz,iy,ix); float[] v = _et.getEigenvectorV(iz,iy,ix); float[] w = _et.getEigenvectorW(iz,iy,ix); float eu = e[0], ev = e[1], ew = e[2]; if (eu<=etiny) eu = etiny; float yc = (float)(fy+iy*dy); if (ymin<yc-dymax && yc+dymax<ymax) { float[] e = _et.getEigenvalues(iz,iy,ix); float[] u = _et.getEigenvectorU(iz,iy,ix); float[] v = _et.getEigenvectorV(iz,iy,ix); float[] w = _et.getEigenvectorW(iz,iy,ix); float eu = e[0], ev = e[1], ew = e[2]; if (eu<=etiny) eu = etiny;
/** * Finds the largest eigenvalue to be used for scaling. */ private float findMaxEigenvalue() { int n1 = _et.getN1(); int n2 = _et.getN2(); int n3 = _et.getN3(); float[] e = new float[3]; float emax = 0.0f; for (int i3=0; i3<n3; ++i3) { for (int i2=0; i2<n2; ++i2) { for (int i1=0; i1<n1; ++i1) { _et.getEigenvalues(i1,i2,i3,e); float emaxi = max(e[0],e[1],e[2]); if (emax<emaxi) emax = emaxi; } } } return emax; } }
/** * Sets eigenvalues for the tensor with specified indices. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @param a array {au,av,aw} of eigenvalues. */ public void setEigenvalues(int i1, int i2, int i3, float[] a) { setEigenvalues(i1,i2,i3,a[0],a[1],a[2]); }
/** * Sets the eigenvector u for the tensor with specified indices. * The specified vector is assumed to have length one. If the 3rd * component is negative, this method stores the negative of the * specified vector, so that the 3rd component is positive. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @param u {u1,u2,u3} of eigenvector components. */ public void setEigenvectorU(int i1, int i2, int i3, float[] u) { setEigenvectorU(i1,i2,i3,u[0],u[1],u[2]); }
/** * Sets the eigenvector w for the tensor with specified indices. * The specified vector is assumed to have length one. If the 3rd * component is negative, this method stores the negative of the * specified vector, so that the 3rd component is positive. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @param w {w1,w2,w3} of eigenvector components. */ public void setEigenvectorW(int i1, int i2, int i3, float[] w) { setEigenvectorW(i1,i2,i3,w[0],w[1],w[2]); }
return new EigenTensors3(u1,u2,w1,w2,eu,ev,ew,compressed);
/** * Gets eigenvalues for the tensor with specified indices. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @return array {au,av,aw} of eigenvalues. */ public float[] getEigenvalues(int i1, int i2, int i3) { float[] a = new float[3]; getEigenvalues(i1,i2,i3,a); return a; }
/** * Gets the eigenvector u for the tensor with specified indices. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @return array {u1,u2,u3} of eigenvector components. */ public float[] getEigenvectorU(int i1, int i2, int i3) { float[] u = new float[3]; getEigenvectorU(i1,i2,i3,u); return u; }
/** * Gets the eigenvector w for the tensor with specified indices. * @param i1 index for 1st dimension. * @param i2 index for 2nd dimension. * @param i3 index for 3rd dimension. * @return array {w1,w2,w3} of eigenvector components. */ public float[] getEigenvectorW(int i1, int i2, int i3) { float[] w = new float[3]; getEigenvectorW(i1,i2,i3,w); return w; }
public static void demo1() { int n1 = 1; int n2 = 111; int n3 = 111; EigenTensors3 et = new EigenTensors3(n1,n2,n3,false); float eu = 1.00f, ev = 1.00f, ew = 0.01f; float u1 = 1.00f, u2 = 0.00f, u3 = 0.00f; float w1 = 0.00f, w2 = 0.00f, w3 = 1.00f; int i1 = 0; for (int i3=0; i3<n3; ++i3) { float a = i3*FLT_PI/2.0f/(n3-1); w2 = sin(a); w3 = cos(a); for (int i2=0; i2<n2; ++i2) { et.setEigenvalues(i1,i2,i3,eu,ev,ew); et.setEigenvectorU(i1,i2,i3,u1,u2,u3); et.setEigenvectorW(i1,i2,i3,w1,w2,w3); } } TensorsPanel tp = new TensorsPanel(et); AxisAlignedQuad aaq = new AxisAlignedQuad(Axis.Z, new Point3( 0, 0,i1), new Point3(n3-1,n2-1,i1)); aaq.getFrame().addChild(tp); show(aaq); }
/** * Scales eigenvalues of these tensors by specified factors. * @param s array of scale factors. */ public void scale(float[][][] s) { float[] a = new float[3]; for (int i3=0; i3<_n3; ++i3) { for (int i2=0; i2<_n2; ++i2) { for (int i1=0; i1<_n1; ++i1) { float si = s[i3][i2][i1]; getEigenvalues(i1,i2,i3,a); a[0] *= si; a[1] *= si; a[2] *= si; setEigenvalues(i1,i2,i3,a); } } } }