Example #1
0
void
Stokhos::RecurrenceBasis<ordinal_type,value_type>::
getQuadPoints(ordinal_type quad_order,
              Teuchos::Array<value_type>& quad_points,
              Teuchos::Array<value_type>& quad_weights,
              Teuchos::Array< Teuchos::Array<value_type> >& quad_values) const
{

    //This is a transposition into C++ of Gautschi's code for taking the first
    // N recurrance coefficient and generating a N point quadrature rule.
    // The MATLAB version is available at
    // http://www.cs.purdue.edu/archives/2002/wxg/codes/gauss.m
    ordinal_type num_points =
        static_cast<ordinal_type>(std::ceil((quad_order+1)/2.0));
    Teuchos::Array<value_type> a(num_points,0);
    Teuchos::Array<value_type> b(num_points,0);
    Teuchos::Array<value_type> c(num_points,0);
    Teuchos::Array<value_type> d(num_points,0);

    // If we don't have enough recurrance coefficients, get some more.
    if(num_points > p+1) {
        bool is_normalized = computeRecurrenceCoefficients(num_points, a, b, c, d);
        if (!is_normalized)
            normalizeRecurrenceCoefficients(a, b, c, d);
    }
    else {  //else just take the ones we already have.
        for(ordinal_type n = 0; n<num_points; n++) {
            a[n] = alpha[n];
            b[n] = beta[n];
            c[n] = delta[n];
            d[n] = gamma[n];
        }
        if (!normalize)
            normalizeRecurrenceCoefficients(a, b, c, d);
    }

    // With normalized coefficients, A is symmetric and tri-diagonal, with
    // diagonal = a, and off-diagonal = b, starting at b[1]
    Teuchos::SerialDenseMatrix<ordinal_type,value_type> eig_vectors(num_points,
            num_points);
    Teuchos::Array<value_type> workspace(2*num_points);
    ordinal_type info_flag;
    Teuchos::LAPACK<ordinal_type,value_type> my_lapack;

    // compute the eigenvalues (stored in a) and right eigenvectors.
    if (num_points == 1)
        my_lapack.STEQR('I', num_points, &a[0], &b[0], eig_vectors.values(),
                        num_points, &workspace[0], &info_flag);
    else
        my_lapack.STEQR('I', num_points, &a[0], &b[1], eig_vectors.values(),
                        num_points, &workspace[0], &info_flag);

    // eigenvalues are sorted by STEQR
    quad_points.resize(num_points);
    quad_weights.resize(num_points);
    for (ordinal_type i=0; i<num_points; i++) {
        quad_points[i] = a[i];
        if (std::abs(quad_points[i]) < quad_zero_tol)
            quad_points[i] = 0.0;
        quad_weights[i] = beta[0]*eig_vectors[i][0]*eig_vectors[i][0];
    }

    // Evalute basis at gauss points
    quad_values.resize(num_points);
    for (ordinal_type i=0; i<num_points; i++) {
        quad_values[i].resize(p+1);
        evaluateBases(quad_points[i], quad_values[i]);
    }
}
Example #2
0
void eig_hess(double *A, size_t n, size_t low, size_t high,
         double *wr, double *wi, int matq, double *Q, size_t *iter, size_t *rc)
{
  size_t i, j, m, k, l, na, ll, en;
  int cur_iter, flag, MAXIT;
  double p, q, r, s, t, w, x, y, z;
  double mach_eps;

  mach_eps = MACH_EPS();

  MAXIT = 30;
  
  p = q = r = 0.0; 

  for(i = 0; i < n; i++)
  {
    if (i < low || i > high)
    {
      wr[i] = A[i*n + i];
      wi[i] = 0.0;
      iter[i] = 0;
    }
  }

  en = high;
  t = 0.0;

  flag = 1;
  while (en >= low && flag)
  {
    cur_iter = 0;
    na = en - 1;

    while(1)
    {
      ll = 0;                          
      for(l = en; l > low; l--) /* search for small subdiagonal element */
      {
        if (fabs(A[l*n + l - 1]) <= mach_eps * (fabs(A[(l - 1)*n + l - 1]) + fabs(A[l*n + l])))
        {
          ll = l; /* save current index */
          break;
        }
      }
      l = ll; /* restore l */

      x = A[en*n + en];
      if (l == en) /* found one evalue */
      {
        wr[en] = x + t;
        A[en*n + en] = x + t;
        wi[en] = 0.0;
        iter[en] = cur_iter;
        if (en > 0) 
          en--;
        else
          flag = 0;
        break; /* exit from loop while(1) */
      }

      y = A[na*n + na];
      w = A[en*n + na] * A[na*n + en];

      if (l == na) /* found two evalues */
      {
        p = (y - x) * 0.5;
        q = p * p + w;
        z = sqrt(fabs(q));
        x = x + t;
        A[en*n + en] = x + t;
        A[na*n + na] = y + t;
        iter[en] = -cur_iter;
        iter[na] = cur_iter;
        if (q >= 0.0) /* real eigenvalues */
        {
          if (p < 0.0) 
            z = p - z; 
	  else 
            z = p + z;
          wr[na] = x + z;
          wr[en] = x - w / z;
          wi[na] = 0.0;
          wi[en] = 0.0;
          x = A[en*n + na];
          r = sqrt(x * x + z * z);

          if (matq) 
          {
            p = x / r;
            q = z / r;
            for(j = na; j < n; j++)
            {
              z = A[na*n + j];
              A[na*n + j] = q * z + p * A[en*n + j];
              A[en*n + j] = q * A[en*n + j] - p * z;
            }

            for(i = 0; i <= en; i++)
            {
              z = A[i*n + na];
              A[i*n + na] = q * z + p * A[i*n + en];
              A[i*n + en] = q * A[i*n + en] - p * z;
            }

            if (matq) for(i = low; i <= high; i++)
            {
              z = Q[i*n + na];
              Q[i*n + na] = q * z + p * Q[i*n + en];
              Q[i*n + en] = q * Q[i*n + en] - p * z;
            }
          } 
        }
        else
        {  /* pair of complex */
          wr[na] = x + p;
          wr[en] = x + p;
          wi[na] =   z;
          wi[en] = - z;
        } 

        if (en > 1) 
          en -= 2;
        else
          flag = 0;
        break; /* exit while(1) */
      } /* if l = na */

      if (cur_iter >= MAXIT) 
      {
        iter[en] = MAXIT + 1;
        *rc = en;
        return;
      }                                  

      if (cur_iter == 10 || cur_iter == 20) 
      {
        t += x;
        for(i = low; i <= en; i++)
           A[i*n + i] -= x;
        s = fabs(A[en*n + na]) + fabs(A[na*n + en - 2]);
        x = 0.75 * s; 
        y = x;
        w = -0.4375 * s * s;
      }

      cur_iter++;

      for(m = en - 1; m > l; m--)
      {
        z = A[(m - 1)*n + m - 1];
        r = x - z;
        s = y - z;
        p = (r*s - w)/A[m*n + m - 1] + A[(m - 1)*n + m];
        q = A[m*n + m] - z - r - s;
        r = A[(m + 1)*n + m];
        s = fabs(p) + fabs(q) + fabs (r);
        p = p / s;
        q = q / s;
        r = r / s;
        if (m == l + 1) break;
        if (fabs(A[(m - 1)*n + m - 2]) * (fabs(q) + fabs(r)) <= mach_eps * fabs(p)
                 * (fabs(A[(m - 2)*n + m - 2]) + fabs(z) + fabs(A[m*n + m]))) 
          break;
      }
   
      for(i = m + 1; i <= en; i++)
        A[i*n + i - 2] = 0.0;
      for(i = m + 2; i <= en; i++)
        A[i*n + i - 3] = 0.0;

      for(k = m - 1; k <= na; k++)
      {
        if (k != m - 1) /* double QR step, for rows l to en */
        {               /* and columns m to en */
          p = A[k*n + k - 1];
          q = A[(k + 1)*n + k - 1];
          if (k != na)
            r = A[(k + 2)*n + k - 1]; 
          else 
            r = 0.0;
          x = fabs(p) + fabs(q) + fabs(r);
          if (x == 0.0) 
            continue; /* next k */
          p = p / x;
          q = q / x;
          r = r / x;
        }
        s = sqrt(p*p + q*q + r*r);
        if (p < 0.0) 
          s = -s;

        if (k != m - 1) 
          A[k*n + k - 1] = -s * x;
        else if (l != m - 1) 
          A[k*n + k - 1] = -A[k*n + k - 1];

        p = p + s;
        x = p / s;
        y = q / s;
        z = r / s;
        q = q / p;
        r = r / p;

        for(j = k; j < n; j++) /* modify rows */
        {
          p = A[k*n + j] + q * A[(k + 1)*n + j];
          if (k != na) 
          {
            p = p + r * A[(k + 2)*n + j];
            A[(k + 2)*n + j] = A[(k + 2)*n + j] - p * z;
          }
          A[(k + 1)*n + j] = A[(k + 1)*n + j] - p * y;
          A[k*n + j]   = A[k*n + j] - p * x;
        }

        if (k + 3 < en)  
           j = k + 3; 
        else 
           j = en;
        for(i = 0; i <= j; i++) /* modify columns */
        {
          p = x * A[i*n + k] + y * A[i*n + k+1];
          if (k != na) 
          {
            p = p + z * A[i*n + k+2];
            A[i*n + k+2] = A[i*n + k+2] - p * r;
          }
          A[i*n + k+1] = A[i*n + k+1] - p * q;
          A[i*n + k]   = A[i*n + k] - p;
        }

        if (matq) /* if eigenvectors are needed */
        {
          for(i = low; i <= high; i++)
          {
            p = x * Q[i*n + k] + y * Q[i*n + k+1];
            if (k != na)
            {
              p = p + z * Q[i*n + k+2];
              Q[i*n + k+2] = Q[i*n + k+2] - p * r;
            }
            Q[i*n + k+1] = Q[i*n + k+1] - p * q;
            Q[i*n + k]   = Q[i*n + k] - p;
          }
        }
      } /* k loop */

    } /* while (1<2) */

 } /* while en >= low All evalues found */


  if (matq) /* transform evectors back */
    eig_vectors(A, n, low, high, wr, wi, Q);

  *rc = 0;
}