src/lambda2.h

    static void eigsrt (double d[dimension],
    		    double v[dimension][dimension])
    {
      int k, j, i;
      double p;
    
      for (i = 0; i < dimension - 1; i++) {
        p = d[k = i];
    
        for (j = i + 1; j < dimension; j++)
          if (d[j] >= p) 
    	p = d[k = j];
        if (k != i) {
          d[k] = d[i];
          d[i] = p;
          for (j = 0; j < dimension; j++) {
    	p = v[j][i];
    	v[j][i] = v[j][k];
    	v[j][k] = p;
          }
        }
      }
    }
    
    #define ROTATE(a,i,j,k,l) {\
        g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);a[k][l]=h+s*(g-h*tau);}
    • eigenvalues:
    • @a: a symmetric matrix.
    • @d: a vector.
    • @v: another matrix.
    • Fills @d (resp. @v) with the eigenvalues (resp. eigenvectors) of
    • matrix @a.
    void eigenvalues (double a[dimension][dimension],
    		  double d[dimension],
    		  double v[dimension][dimension])
    {
      int j, iq, ip, i;
      double tresh, theta, tau, t, sm, s, h, g, c, b[dimension], z[dimension];
    
      for (ip = 0; ip < dimension; ip++) {
        for (iq = 0; iq < dimension; iq++)
          v[ip][iq] = 0.0;
        v[ip][ip] = 1.0;
      }
    
      for (ip = 0; ip < dimension; ip++) {
        b[ip] = d[ip] = a[ip][ip];
        z[ip] = 0.0;
      }
    
      for (i = 1; i <= 50; i++) {
        sm = 0.0;
        for (ip = 0; ip < dimension - 1; ip++) {
          for (iq = ip + 1; iq < dimension; iq++)
    	sm += fabs (a[ip][iq]);
        }
        if (sm == 0.0) {
          eigsrt (d, v);
          return;
        }
        if (i < 4)
          tresh = 0.2*sm/(dimension*dimension);
        else
          tresh = 0.0;
        for (ip = 0; ip < dimension - 1; ip++) {
          for (iq = ip + 1; iq < dimension; iq++) {
    	g = 100.0*fabs (a[ip][iq]);
    	if (i > 4 && fabs(d[ip]) + g == fabs(d[ip]) &&
    	    fabs(d[iq]) + g == fabs(d[iq]))
    	  a[ip][iq] = 0.0;
    	else if (fabs (a[ip][iq]) > tresh) {
    	  h = d[iq] - d[ip];
    	  if (fabs(h) + g == fabs(h))
    	    t = a[ip][iq]/h;
    	  else {
    	    theta = 0.5*h/a[ip][iq];
    	    t = 1.0/(fabs (theta) + sqrt (1.0 + theta*theta));
    	    if (theta < 0.0) t = -t;
    	  }
    	  c = 1.0/sqrt (1 + t*t);
    	  s = t*c;
    	  tau = s/(1.0 + c);
    	  h = t*a[ip][iq];
    	  z[ip] -= h;
    	  z[iq] += h;
    	  d[ip] -= h;
    	  d[iq] += h;
    	  a[ip][iq] = 0.0;
    	  for (j = 0; j <= ip - 1; j++)
    	    ROTATE (a, j, ip, j, iq);
    	  for (j = ip + 1; j <= iq - 1; j++)
    	    ROTATE (a, ip, j, j, iq);
    	  for (j = iq + 1; j < dimension; j++)
    	    ROTATE(a, ip, j, iq, j);
    	  for (j = 0; j < dimension; j++)
    	    ROTATE(v, j, ip, j, iq);
    	}
          }
        }
        for (ip = 0; ip < dimension; ip++) {
          b[ip] += z[ip];
          d[ip] = b[ip];
          z[ip] = 0.0;
        }
      }
      /* Too many iterations */
      for (i = 0; i < dimension; i++) {
        for (j = 0; j < dimension; j++)
          fprintf (stderr, "%10.3g ", a[i][j]);
        fprintf (stderr, "\n");
      }
      assert (false);
    }
    
    void lambda2 (const vector u, scalar l2)
    {
      foreach() {
        double JJ[dimension][dimension];
        scalar s = u.x;
        int i = 0;
        foreach_dimension()
          JJ[0][i++] = center_gradient (s);
        s = u.y; i = 0;
        foreach_dimension()
          JJ[1][i++] = center_gradient (s);
        s = u.z; i = 0;
        foreach_dimension()
          JJ[2][i++] = center_gradient (s);
        double S2O2[dimension][dimension];
        for (int i = 0; i < dimension; i++)
          for (int j = 0; j < dimension; j++) {
    	S2O2[i][j] = 0.;
    	for (int k = 0; k < dimension; k++)
    	  S2O2[i][j] += JJ[i][k]*JJ[k][j] + JJ[k][i]*JJ[j][k];
          }
        double lambda[dimension], ev[dimension][dimension];
        eigenvalues (S2O2, lambda, ev);
        l2[] = lambda[1]/2.;
      }
    }

    Usage

    Examples