示例#1
0
///Calculate Exp[I*m]
LaGenMatComplex snake::math::expm2(LaGenMatDouble &m)
{
  //std::cout<<m<<std::endl;
  int dim = m.size(0);
  LaGenMatComplex r(dim,dim);
  LaGenMatDouble eigvec(dim,dim);
  LaGenMatComplex eigvecC(dim,dim);
  LaVectorDouble eigval(dim);
  LaVectorComplex eigvalim(dim);
  eigvec = m;
  snake::math::SSMED(eigvec.addr(),dim,eigval.addr());

  for(int i = 0;i<dim;i++)
    eigvalim(i) = LaComplex(cos(eigval(i)),sin(eigval(i)));
  LaGenMatComplex temp(dim,dim);
  temp = LaComplex(0,0);
  for(int i = 0;i<dim;i++)
    temp(i,i) = eigvalim(i);

  chop(temp,1e-15);
  //std::cout<<temp<<std::endl;
  eigvecC = eigvec.to_LaGenMatComplex();
  LaGenMatComplex tempx(dim,dim);
  Blas_Mat_Mat_Trans_Mult(temp,eigvecC,tempx);
  Blas_Mat_Mat_Mult(eigvecC,tempx,r);
  chop(r,1e-15);
  return r;
}
int main(int argc, char *argv[]) {
  std::string library_routine(rokko::serial_dense_solver::default_solver());
  std::string library, routine;
  unsigned int dim = 10;
  if (argc >= 2) library_routine = argv[1];
  if (argc >= 3) dim = boost::lexical_cast<int>(argv[2]);
  rokko::split_solver_name(library_routine, library, routine);

  std::cout.precision(5);
  std::cout << "Eigenvalue decomposition of Frank matrix" << std::endl
            << "library:routine = " << library_routine << std::endl
	    << "library = " << library << std::endl
	    << "routine = " << routine << std::endl
	    << "dimension = " << dim << std::endl;

  rokko::serial_dense_solver solver(library);
  solver.initialize(argc, argv);

  rokko::localized_matrix<double, matrix_major> mat(dim, dim);
  rokko::frank_matrix::generate(mat);
  std::cout << "Frank matrix:\n" << mat << std::endl;

  rokko::localized_vector<double> eigval(dim);
  rokko::localized_matrix<double, matrix_major> eigvec(dim, dim);
  rokko::parameters params;
  params.set("upper_value", 1.2);
  params.set("lower_value", 0.1);
  //params.set("upper_index", 5);
  //params.set("lower_index", 3);
  params.set("uplow", 'L');
  //params.set("uplow", 'lower');
  params.set("verbose", true);
  try {
    default_diagonalize(mat, eigval, eigvec, params);
    //default_diagonalize(mat, eigval, params);
  }
  catch (const char *e) {
    std::cout << "Exception : " << e << std::endl;
    exit(22);
  }
  rokko::frank_matrix::generate(mat);

  bool sorted = true;
  for (unsigned int i = 1; i < dim; ++i) sorted &= (eigval(i-1) <= eigval(i));
  if (!sorted) std::cout << "Warning: eigenvalues are not sorted in ascending order!\n";

  std::cout << "eigenvalues:\n" << eigval.transpose() << std::endl
            << "eigvectors:\n" << eigvec << std::endl;
  std::cout << "orthogonality of eigenvectors:" << std::endl
            << eigvec.transpose() * eigvec << std::endl;
  std::cout << "residual of the smallest eigenvalue/vector (A x - lambda x):" << std::endl
            << (mat * eigvec.col(0) - eigval(0) * eigvec.col(0)).transpose() << std::endl;

  solver.finalize();
}
示例#3
0
Real
RankTwoScalarAux::calcEigenValues()
{
    std::vector<Real> eigval(LIBMESH_DIM);
    Real val = 0.0;
    unsigned int max_index = 2;
    unsigned int mid_index = 1;
    unsigned int min_index = 0;

    if (LIBMESH_DIM == 2)
        max_index = 1;

    _tensor[_qp].symmetricEigenvalues(eigval);

    switch (_scalar_type)
    {
    case 4:
        val = eigval[max_index];
        break;
    case 5:
        if (LIBMESH_DIM == 2)
            mooseError("RankTwoScalarAux Error: No Mid Principal value when LIBMESH_DIM is 2");
        val = eigval[mid_index];
        break;
    case 6:
        val = eigval[min_index];
        break;
    default:
        mooseError("RankTwoScalarAux Error: Pass valid scalar type - VonMisesStress, EquivalentPlasticStrain, Hydrostatic, L2norm MaxPrincipal MidPrincipal MinPrincipal");
    }
    return val;
}
示例#4
0
void ClassicalScaling::run( PointWiseMapping* mymap ){
   // Retrieve the distances from the dimensionality reduction object
   double half=(-0.5); Matrix<double> distances( half*mymap->modifyDmat() ); 
 
   // Apply centering transtion
   unsigned n=distances.nrows(); double sum;
   // First HM
   for(unsigned i=0;i<n;++i){
       sum=0; for(unsigned j=0;j<n;++j) sum+=distances(i,j);
       for(unsigned j=0;j<n;++j) distances(i,j) -= sum/n;
   }
   // Now (HM)H
   for(unsigned i=0;i<n;++i){
      sum=0; for(unsigned j=0;j<n;++j) sum+=distances(j,i);
      for(unsigned j=0;j<n;++j) distances(j,i) -= sum/n; 
   }

   // Diagonalize matrix
   std::vector<double> eigval(n); Matrix<double> eigvec(n,n);
   diagMat( distances, eigval, eigvec );

   // Pass final projections to map object
   for(unsigned i=0;i<n;++i){
      for(unsigned j=0;j<mymap->getNumberOfProperties();++j) mymap->setProjectionCoordinate( i, j, sqrt(eigval[n-1-j])*eigvec(n-1-j,i) ); 
   }
}
示例#5
0
int main(int argc, char *argv[]) {
  std::string solver_name(rokko::serial_dense_solver::default_solver());
  std::string lattice_file("xyz.dat");
  if (argc >= 2) solver_name = argv[1];
  if (argc >= 3) lattice_file = argv[2];

  std::cout.precision(5);

  int num_sites;
  std::vector<std::pair<int, int> > lattice;
  std::vector<boost::tuple<double, double, double> > coupling;
  rokko::read_lattice_file(lattice_file, num_sites, lattice, coupling);
  int dim = 1 << num_sites;

  rokko::serial_dense_solver solver(solver_name);
  solver.initialize(argc, argv);
  std::cout << "Eigenvalue decomposition of XYZ model" << std::endl
            << "solver = " << solver_name << std::endl
            << "lattice file = " << lattice_file << std::endl
            << "number of sites = " << num_sites << std::endl
            << "number of bonds = " << lattice.size() << std::endl
            << "matrix dimension = " << dim << std::endl;

  rokko::localized_matrix<double, matrix_major> mat(dim, dim);
  rokko::xyz_hamiltonian::generate(num_sites, lattice, coupling, mat);

  rokko::localized_vector<double> eigval(dim);
  rokko::localized_matrix<double, matrix_major> eigvec(dim, dim);
  try {
    solver.diagonalize(mat, eigval, eigvec);
  }
  catch (const char *e) {
    std::cout << "Exception : " << e << std::endl;
    exit(22);
  }
  rokko::xyz_hamiltonian::generate(num_sites, lattice, coupling, mat);

  std::cout << "smallest eigenvalues:";
  for (int i = 0; i < std::min(dim, 10); ++i) std::cout << ' ' << eigval(i);
  std::cout << std::endl;
  std::cout << "residual of the smallest eigenvalue/vector: |x A x - lambda| = "
            << std::abs(eigvec.col(0).transpose() * mat * eigvec.col(0) - eigval(0))
            << std::endl;

  solver.finalize();
}
示例#6
0
///Calculate square matrix exponent
LaGenMatDouble snake::math::expm(LaGenMatDouble &m)
{
  //std::cout<<m<<std::endl;
  int dim = m.size(0);
  LaGenMatDouble r(dim,dim);
  LaGenMatDouble eigvec(dim,dim);
  LaVectorDouble eigval(dim);
  eigvec = m;
  snake::math::SSMED(eigvec.addr(),dim,eigval.addr());

  for(int i = 0;i<dim;i++)
    eigval(i) = exp(eigval(i));
    LaGenMatDouble temp(dim,dim);
  temp = temp.from_diag(eigval);
  //std::cout<<temp<<std::endl;

  Blas_Mat_Mat_Trans_Mult(temp,eigvec,m);
  Blas_Mat_Mat_Mult(eigvec,m,r);
  chop(r,1e-15);
  return r;
}
示例#7
0
arma::rowvec rmvnormx(arma::mat R, arma::rowvec Z){
	Rcpp::RNGScope scope;
	int m = R.n_rows;
	arma::vec eigval(m);
	arma::mat eigvec(m, m);
	arma::mat temp(m, m);
	arma::eig_sym(eigval, eigvec, R);
	arma::rowvec ans(m);
	temp = ( eigvec * arma::diagmat( arma::sqrt( eigval ) ) * arma::inv( eigvec ) );
	ans = Z * temp;
	return ans;
}
示例#8
0
文件: pca.cpp 项目: bloomen/armapca
armapca::pca_result<T> pca(const arma::Mat<T>& data,
                           bool compute_eigenvectors) {
  EXPECTS(data.n_rows >= 2);
  EXPECTS(data.n_cols >= 1);
  const auto n_vars = data.n_cols;
  armapca::pca_result<T> result;
  arma::Mat<T> eigvec;
  if (compute_eigenvectors) {
    result.eigenvectors.set_size(n_vars, n_vars);
    eigvec.set_size(n_vars, n_vars);
  }
  result.eigenvalues.set_size(n_vars);
  arma::Col<T> eigval(n_vars);

  const auto cov_mat = armapca::covariance_matrix(data);

  if (compute_eigenvectors) {
    arma::eig_sym(eigval, eigvec, cov_mat);
  } else {
    arma::eig_sym(eigval, cov_mat);
  }

  const arma::uvec indices = arma::sort_index(eigval, 1);

  for (std::size_t i=0; i < n_vars; ++i) {
    result.eigenvalues(i) = eigval(indices(i));
  }

  if (compute_eigenvectors) {
    for (std::size_t i=0; i < n_vars; ++i) {
      result.eigenvectors.col(i) = eigvec.col(indices(i));
    }
    armapca::enforce_positive_sign_by_column(&result.eigenvectors);
  }

  result.energy = arma::sum(result.eigenvalues);
  result.eigenvalues *= T {1} / result.energy;

  return result;
}
示例#9
0
文件: pca.cpp 项目: curranw/Core
void pca::solve() {
    assert_num_vars_();
    printf("%i", num_records_);
    if (num_records_ < 2)
        throw std::logic_error("Number of records smaller than two.");

    data_.resize(num_records_, num_vars_);

    mean_ = utils::compute_column_means(data_);
    //mean_ = utils::compute_column_means(data_, w_);
    utils::remove_column_means(data_, mean_);
    mean_.print();
    sigma_ = utils::compute_column_rms(data_);
    if (do_normalize_) utils::normalize_by_column(data_, sigma_);

    arma::Col<double> eigval(num_vars_);
    arma::Mat<double> eigvec(num_vars_, num_vars_);

    arma::Mat<double> cov_mat = utils::make_covariance_matrix(data_);
    arma::eig_sym(eigval, eigvec, cov_mat, solver_.c_str());
    arma::uvec indices = arma::sort_index(eigval, 1);

    for (long i=0; i<num_vars_; ++i) {
        eigval_(i) = eigval(indices(i));
        eigvec_.col(i) = eigvec.col(indices(i));
    }

    utils::enforce_positive_sign_by_column(eigvec_);
    proj_eigvec_ = eigvec_;
    proj_eigvec_.print();
    princomp_ = data_ * eigvec_;

    energy_(0) = arma::sum(eigval_);
    eigval_ *= 1./energy_(0);

    if (do_bootstrap_) bootstrap_eigenvalues_();
}
示例#10
0
文件: pca.cpp 项目: curranw/Core
void pca::bootstrap_eigenvalues_() {
    std::srand(bootstrap_seed_);

    arma::Col<double> eigval(num_vars_);
    arma::Mat<double> dummy(num_vars_, num_vars_);

    for (long b=0; b<num_bootstraps_; ++b) {
        const arma::Mat<double> shuffle = utils::make_shuffled_matrix(data_);

        const arma::Mat<double> cov_mat = utils::make_covariance_matrix(shuffle);
        arma::eig_sym(eigval, dummy, cov_mat, solver_.c_str());
        eigval = arma::sort(eigval, 1);

        energy_boot_(b) = arma::sum(eigval);
        eigval *= 1./energy_boot_(b);
        eigval_boot_.row(b) = eigval.t();
    }
}
示例#11
0
int main () {

  // Define symmetric matrix
  PLMD::Matrix<double> mat1(3,3); PLMD::OFile out; out.open("output");
  mat1(0,0)=1.0; mat1(0,1)=0.2; mat1(0,2)=0.3;
  mat1(1,0)=0.2; mat1(1,1)=0.2; mat1(1,2)=0.6;
  mat1(2,0)=0.3; mat1(2,1)=0.6; mat1(2,2)=0.4;

  // Test diagonalize
  std::vector<double> eigval(3); PLMD::Matrix<double> eigvec(3,3); 
  diagMat( mat1, eigval, eigvec ); 
  out<<"Eigenvalues "<<eigval[0]<<" "<<eigval[1]<<" "<<eigval[2]<<"\n";
  out<<"Eigenvectors : \n";
  for(unsigned i=0;i<3;++i){
      out<<eigvec(i,0)<<" "<<eigvec(i,1)<<" "<<eigvec(i,2)<<"\n";
  }

  // Test inverse
  out<<"Inverse : \n";
  PLMD::Matrix<double> inverse(3,3); Invert( mat1, inverse );
  for(unsigned i=0;i<3;++i){ 
      for(unsigned j=0;j<3;++j) out<<inverse(i,j)<<" ";
      out<<"\n";
  }

  // Test pseudoinverse 
  out<<"Pseudoinverse : \n";
  PLMD::Matrix<double> mat(3,2);
  mat(0,0)=0.1; mat(0,1)=0.2; 
  mat(1,0)=0.3; mat(1,1)=0.5;
  mat(2,0)=0.4; mat(2,1)=0.6;
  PLMD::Matrix<double> pseu(2,3);
  pseudoInvert( mat, pseu );
  for(unsigned i=0;i<pseu.nrows();++i){
     for(unsigned j=0;j<pseu.ncols();++j) out<<" "<<pseu(i,j);
     out<<"\n";
  }
  out.close();

  return 0;
}
示例#12
0
PCA&
PCA::fit( const std::vector< std::vector< double > >& data )
{
    const size_t nSamples = data.size();
    const size_t nFeatures = data.front().size();
    
    // Calculate the means vector
    arma::mat meansVector( nFeatures, 1 );
    for ( size_t iFeature = 0; iFeature < nFeatures; ++iFeature ) {
        double sx = 0;
        for ( size_t iSample = 0; iSample < nSamples; ++iSample ) {
            const double value = data[iSample][iFeature];
            if ( std::isnan(value) )
                throw std::runtime_error( "PCA::fit : nan value encountered at input!" );
            sx += value;
        }
        meansVector(iFeature, 0) = sx / nSamples;
    }
    
    // Construct the covariance matrix from the scatter matrix
    arma::mat covMatrix( nFeatures, nFeatures, arma::fill::zeros );
    for ( size_t iSample = 0; iSample < nSamples; ++iSample ) {
        arma::mat sampleData( data[iSample ] );
        arma::mat d = sampleData - meansVector;
        covMatrix += d * d.t();
    }
    covMatrix /= nSamples;
    
    // Now find the eigenvalues and eigenvectors
    arma::cx_vec eigval;
    arma::cx_mat eigvec;
    bool result = arma::eig_gen(eigval, eigvec, covMatrix );
    if (! result ) {
        throw std::runtime_error("PCA::fit : eigenvalue decomposition failed!");
    }
    
    // Normalise the eigenvalues
    m_eigPairs.clear();
    m_eigPairs.reserve( nFeatures );
    double eigSum = 0;
    for ( size_t iFeature = 0; iFeature < nFeatures; ++iFeature ) {
        const double eigMagnitude = std::abs( eigval(iFeature) );

        arma::cx_vec eigenVectorFromCalculation = eigvec.row( iFeature );
        std::vector<double> eigenVector( nFeatures, 0.0 );
        for (size_t j = 0; j < nFeatures; ++j ) eigenVector[j] = eigenVectorFromCalculation(j).real();
        
        m_eigPairs.push_back( std::make_pair( eigMagnitude,
                                             eigenVector ) );
        eigSum += eigMagnitude;
    }
    
    for ( size_t iFeature = 0; iFeature < nFeatures; ++iFeature ) {
        m_eigPairs[iFeature].first /= eigSum;
    }
    
    // Sort the eigenValues
    std::sort( m_eigPairs.begin(), m_eigPairs.end(),
              [] (const std::pair<double, std::vector<double> >&a,
                  const std::pair<double, std::vector<double> >&b ) { return a.first > b.first; } );
    
    return *this;
}
示例#13
0
int main(int argc, char *argv[]) {
  int provided;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
  MPI_Comm comm = MPI_COMM_WORLD;
  std::string solver_name(rokko::parallel_dense_solver::default_solver());
  int L = 8;
  if (argc >= 2) solver_name = argv[1];
  if (argc >= 3) L = boost::lexical_cast<int>(argv[2]);

  rokko::grid g(comm);
  int myrank = g.get_myrank();

  std::cout.precision(5);

  int dim = 1 << L;
  std::vector<std::pair<int, int> > lattice;
  for (int i = 0; i < L; ++i) {
    lattice.push_back(std::make_pair(i, (i+1) % L));
  }

  rokko::parallel_dense_solver solver(solver_name);
  solver.initialize(argc, argv);
  if (myrank == 0)
    std::cout << "Eigenvalue decomposition of antiferromagnetic Heisenberg chain" << std::endl
              << "num_procs = " << g.get_nprocs() << std::endl
              #ifdef _OPENMP
              << "num_threads per process = " << omp_get_max_threads() << std::endl
              #endif
              << "solver = " << solver_name << std::endl
              << "L = " << L << std::endl
              << "dimension = " << dim << std::endl;

  rokko::distributed_matrix<double, matrix_major> mat(dim, dim, g, solver);
  rokko::heisenberg_hamiltonian::generate(L, lattice, mat);
  rokko::localized_matrix<double, matrix_major> mat_loc(dim, dim);
  rokko::gather(mat, mat_loc, 0);

  rokko::localized_vector<double> eigval(dim);
  rokko::distributed_matrix<double, matrix_major> eigvec(dim, dim, g, solver);
  try {
    solver.diagonalize(mat, eigval, eigvec);
  }
  catch (const char *e) {
    if (myrank == 0) std::cout << "Exception : " << e << std::endl;
    MPI_Abort(MPI_COMM_WORLD, 22);
  }

  rokko::localized_matrix<double, matrix_major> eigvec_loc(dim, dim);
  rokko::gather(eigvec, eigvec_loc, 0);
  if (myrank == 0) {
    std::cout << "smallest eigenvalues:";
    for (int i = 0; i < std::min(dim, 10); ++i) std::cout << ' ' << eigval(i);
    std::cout << std::endl;
    std::cout << "residual of the smallest eigenvalue/vector: |x A x - lambda| = "
              << std::abs(eigvec_loc.col(0).transpose() * mat_loc * eigvec_loc.col(0) - eigval(0))
              << std::endl;
  }

  solver.finalize();
  MPI_Finalize();
}
/**

     \brief Compute the eigenvalues of a real symmetric matrix A.

     \param  a = pointer to array of symmetric n by n input matrix A. The computation alters these values.
     \param  ev = pointer to array of the output eigenvalues
     \param  n = dimension parameter (dim(a)= n*n, dim(ev)= n)
*/
void G_math_eigval(double **a,double *ev,int n)
{
    eigval(a[0], ev, n);
    return;
}
示例#15
0
//------------------------------------------------------------------------------
void PD_LPS_porosity_adrmc::evaluateStatic(int id, int i) {
  if (m_data(i, m_indexUnbreakable) >= 1)
    return;
#if CALCULATE_NUMMERICAL_PRINCIPAL_STRESS
  arma::vec eigval(m_dim);
#endif
  vector<pair<int, vector<double>>> &PDconnections =
      m_particles.pdConnections(id);
  const double shearCrit = m_C0 - m_ks * m_T;
  //    const double s_crit = 3.*m_T/40.e9;

  bool broken = false;
  if (m_dim == 2) {
    for (auto &con : PDconnections) {
      const int id_j = con.first;
      const int j = m_idToCol_v[id_j];

      if (m_data(j, m_indexUnbreakable) >= 1)
        continue;

      if (con.second[m_indexConnected] <= 0.5)
        continue;

      //            const double s = con.second[m_iStretch];

      const double sx = 0.5 * (m_data(i, m_indexStress[0]) + m_data(j, m_indexStress[0]));
      const double sy = 0.5 * (m_data(i, m_indexStress[1]) + m_data(j, m_indexStress[1]));
      const double sxy = 0.5 * (m_data(i, m_indexStress[2]) + m_data(j, m_indexStress[2]));

      const double first = 0.5 * (sx + sy);
      const double second = sqrt(0.25 * (sx - sy) * (sx - sy) + sxy * sxy);

      const double p_1 = first + second; // max
      const double p_2 = first - second; // min
#if USE_PRINCIPAL_STRESS
      const int criticalShear = p_2 <= m_C0 - m_ks * p_1;
#else
      const double shear_max = 0.5 * (p_1 - p_2);
      const double shear = shear_max * m_cos_theta;
      const double normal = 0.5 * (p_1 + p_2) + shear_max * m_sin_theta;
      const double criticalShear = shear > m_S0 - m_d * normal;
//            const double criticalShear = shear + m_d*normal - m_S0;
//            const double criticalTensile = p_1 - m_T;
#endif
      const int MC_valid = p_2 < shearCrit;
      const int criticalTensile = p_1 >= m_T;
      //            const int criticalTensile = s >= s_crit;

      if (MC_valid) {
        if (criticalShear) {
          m_data(i, m_indexBrokenNow) = 1;
          con.second[m_indexConnected] = 0;
          m_continueState = true;
          broken = true;
          //                    cout << "Shear\t " << id << " - " << id_j <<
          //                    "\tp1:" << p_1 << ", " << p_2 << endl;
        }
      }
      //            } else {
      //            }
      if (criticalTensile) {
        m_data(i, m_indexBrokenNow) = 1;
        con.second[m_indexConnected] = 0;
        m_continueState = true;
        broken = true;
        //                cout << "Tensile\t " << id << " - " << id_j <<
        //                "\tp1:" << p_1 << ", " << p_2 << endl;
      }
    }
  } else if (m_dim == 3) {
    arma::mat S(m_dim, m_dim);

    for (auto &con : PDconnections) {
      const int id_j = con.first;
      const int j = m_idToCol_v[id_j];

      if (m_data(j, m_indexUnbreakable) >= 1)
        continue;

      if (con.second[m_indexConnected] <= 0.5)
        continue;

      S(0, 0) = 0.5 * (m_data(i, m_indexStress[0]) + m_data(j, m_indexStress[0]));
      S(1, 1) = 0.5 * (m_data(i, m_indexStress[1]) + m_data(j, m_indexStress[1]));
      S(0, 1) = 0.5 * (m_data(i, m_indexStress[2]) + m_data(j, m_indexStress[2]));
      S(1, 0) = S(0, 1);
      S(2, 2) = 0.5 * (m_data(i, m_indexStress[3]) + m_data(j, m_indexStress[3]));
      S(0, 2) = 0.5 * (m_data(i, m_indexStress[4]) + m_data(j, m_indexStress[4]));
      S(2, 0) = S(0, 2);
      S(1, 2) = 0.5 * (m_data(i, m_indexStress[5]) + m_data(j, m_indexStress[5]));
      S(2, 1) = S(1, 2);

#if CALCULATE_NUMMERICAL_PRINCIPAL_STRESS
      arma::eig_sym(eigval, S);
      const double p_1 = eigval(2);
      const double p_2 = eigval(0);
#else
      const double I1 = S(0, 0) + S(1, 1) + S(2, 2);
      const double I2 = S(0, 0) * S(1, 1) + S(1, 1) * S(2, 2) +
                        S(3, 3) * S(0, 0) - pow(S(0, 1), 2) - pow(S(1, 2), 2) -
                        pow(S(0, 2), 2);
      const double I3 = S(0, 0) * S(1, 1) * S(2, 2) -
                        S(0, 0) * pow(S(1, 2), 2) - S(1, 1) * pow(S(0, 2), 2) -
                        S(2, 2) * pow(S(0, 1), 2) +
                        2 * S(0, 1) * S(1, 2) * S(0, 2);
      const double phi =
          1. / 3. * acos(0.5 * (2 * pow(I1, 3) - 9 * I1 * I2 + 27 * I3) /
                         pow(pow(I1, 2) - 3 * I2, 1.5));

      const double core = 2. / 3. * (sqrt(I1 * I1 - 3 * I2));
      const double s1 = I1 / 3. + core * cos(phi);
      const double s2 = I1 / 3. + core * cos(phi - 2. * M_PI / 3.);
      const double s3 = I1 / 3. + core * cos(phi - 4. * M_PI / 3.);

      double p_1 = s1;
      double p_2 = s2;

      if (s2 > p_1) {
        p_1 = s2;
        p_2 = s1;
      }
      if (s3 > p_1) {
        p_1 = s3;
      }

      if (p_2 < s3) {
        p_2 = s3;
      }
#endif
      const int criticalShear = p_2 <= m_C0 - m_ks * p_1;
      const int MC_valid = p_2 < shearCrit;
      const int criticalTensile = p_1 >= m_T;

      if (MC_valid) {
        if (criticalShear) {
          m_data(i, m_indexBrokenNow) = 1;
          con.second[m_indexConnected] = 0;
          broken = true;
        }
      } else {
        if (criticalTensile) {
          m_data(i, m_indexBrokenNow) = 1;
          con.second[m_indexConnected] = 0;
          broken = true;
        }
      }
    }
  }

  if (broken) {
    updateWeightedVolume(id, i);
    computeK(id, i);
    m_data(i, m_indexBrokenNow) = 0;
  }
}
示例#16
0
文件: usp.c 项目: sabeiro/Allink
void usp_eval_print(struct beads *b, struct usp *usp)
{
        if (usp == NULL) return;
        int i, j, k;
        int idx = 0;
        double xrel[3];

        const int dim[3] = {TANG1,TANG2,NORMAL};

        for (j=0 ; j<2 ; j++)
                for (k=0 ; k<9 ; k++)
                        usp->tt[j][k]=0.;
        //DETERMINE ORIENTATION
	for (i = 0; i < b->local_n; i++) {
                //FOR EACH ATOM CHECK IF THE BLOCK IS SUBJECT TO THE UMBRELLA POTENTIAL
                int thisblock = b->local_n_b[i];
		int N = b->N[thisblock];
                if (thisblock==usp->blocks[0] || thisblock==usp->blocks[1]) {
                        int blck=1; //IDENTIFY BLOCK AS 2nd OR 1st OF THE SPECIFIED BLOCKS IN THE HEADER
                        if (thisblock==usp->blocks[0])
                                blck=0;


		        for (j = idx; j < idx + N; j++) {
                                for (k=0 ; k<3 ; k++) { //dimension, 3d
                                        xrel[k] = b->x_intra[j][dim[k]] - usp->coms[3*blck+k];  // Transformation to relative coordinates
                                        //fprintf(stderr,"block:%d bead:%d xrel[%d]=%lg\n",blck,j,k,xrel[k]);
                                }

                                usp->tt[blck][0*3+0] += ((xrel[1]*xrel[1]) + (xrel[2]*xrel[2]));   // Traegheitstensor
                                usp->tt[blck][0*3+1] -= (xrel[0]*xrel[1]);
                                usp->tt[blck][0*3+2] -= (xrel[0]*xrel[2]);

                                usp->tt[blck][1*3+1] += ((xrel[0]*xrel[0]) + (xrel[2]*xrel[2]));
                                usp->tt[blck][1*3+2] -= (xrel[1]*xrel[2]);

                                usp->tt[blck][2*3+2] += ((xrel[0]*xrel[0]) + (xrel[1]*xrel[1]));

		        }
                }
		idx += N;
	}
        if(ismaster)
                fprintf(usp->fh,"%lg",b->time);

        for (k=0 ; k<2 ; k++) { //blocks
	        MPI_Allreduce(MPI_IN_PLACE, usp->tt[k], 9, MPI_DOUBLE, MPI_SUM, comm_grid);

                usp->tt[k][1*3+0]  = usp->tt[k][0*3+1]; //symmetry
                usp->tt[k][2*3+0]  = usp->tt[k][0*3+2];
                usp->tt[k][2*3+1]  = usp->tt[k][1*3+2]; //tt[k] is now complete!

                //for (i=0 ; i<3 ; i++) {
                //        for (j=0 ; j<3 ; j++) {
                //                fprintf(stderr,"block:%d tt[%d][%d]:%lg\n",k,i,j,usp->tt[k][3*i+j]);
                //        }
                //}


                // Diagonalisieren des Tr??heitstensors durch L??ung einer kubischen Gleichung
                // kubische cardanische Gleichung:
                // x^3 + ra*x^2 + sa*x + ta = 0

                /*
                double ra,sa,ta,p,q,rho,phi;
                ra = -(usp->tt[k][0*3+0] + usp->tt[k][1*3+1] + usp->tt[k][2*3+2]);
                sa = (usp->tt[k][0*3+0] * (usp->tt[k][1*3+1] + usp->tt[k][2*3+2])
                    - usp->tt[k][1*3+0]*usp->tt[k][0*3+1] - usp->tt[k][2*3+0]*usp->tt[k][0*3+2]
                    + usp->tt[k][1*3+1]*usp->tt[k][2*3+2] - usp->tt[k][2*3+1]*usp->tt[k][1*3+2]);
                ta = -(usp->tt[k][1*3+0]*(usp->tt[k][2*3+1]*usp->tt[k][0*3+2] - usp->tt[k][0*3+1]*usp->tt[k][2*3+2]) 
                     + usp->tt[k][2*3+0]*(usp->tt[k][0*3+1]*usp->tt[k][1*3+2] - usp->tt[k][1*3+1]*usp->tt[k][0*3+2])
                     + usp->tt[k][0*3+0]*(usp->tt[k][1*3+1]*usp->tt[k][2*3+2] - usp->tt[k][2*3+1]*usp->tt[k][1*3+2]) );

                // reduzierte Form der kubischen Gleichung y^3 + p*y + q = 0
                // rho = sqrt(-p^3/27.)  cos phi = -q/(2*rho)

                p = (3.*sa - ra*ra)/3.;
                q = ((2.*ra*ra*ra)/27.) - (ra*sa/3.) + ta;

                rho = sqrt(-(p*p*p)/27.);
                phi = acos(-q/(2.*rho));

                //fprintf(stderr,"ra:%lg sa:%lg ta:%lg p:%lg q:%lg rho:%lg phi:%lg\n",ra,sa,ta,p,q,rho,phi);

                double y[3];
                double lambda[3];
                double maxlambda[3];
                double evec[3];
                y[0] = 2.*pow(rho,1./3.)*cos(phi/3.);
                y[1] = 2.*pow(rho,1./3.)*cos(phi/3. + 2.*M_PI/3.);
                y[2] = 2.*pow(rho,1./3.)*cos(phi/3. + 4.*M_PI/3.);
                */

                double evec[3];
                double lambda2[3];
                double maxlambda[3];

                eigval(usp->tt[k],lambda2); // get Eigenvalues

                maxlambda[0] = MAX(lambda2[0], MAX(lambda2[1],lambda2[2])); // groesstes Tragheitsmoment

                if (maxlambda[0] == lambda2[0])
                {
                    maxlambda[1] = MAX(lambda2[1],lambda2[2]);
                    maxlambda[2] = MIN(lambda2[1],lambda2[2]); 
                }
                else if (maxlambda[0] == lambda2[1])
                {
                    maxlambda[1] = MAX(lambda2[0],lambda2[2]);
                    maxlambda[2] = MIN(lambda2[0],lambda2[2]); 
                }
                else
                {
                    maxlambda[1] = MAX(lambda2[0],lambda2[1]);
                    maxlambda[2] = MIN(lambda2[0],lambda2[1]);
                }

                //fprintf(stderr,"block %d has eigenvalues in descending order %lg %lg %lg\n",k,maxlambda[0],maxlambda[1],maxlambda[2]);
                //for (i=0;i<3;i++) {
                //        for (j=0;j<3;j++) {
                //                fprintf(stderr,"%lg ",usp->tt[k][i*3+j]);
                //        }
                //        fprintf(stderr,"\n");
                //}



                //fprintf(stderr,"y:%lg %lg %lg\n",y[0],y[1],y[2]);

                /*
                for(j=0; j<3; j++)
                        lambda[j] = y[j] - ra/3.; // Eigenwerte (Haupttraegheitsmomente)

                //fprintf(stderr,"lambda:%lg %lg %lg\n",lambda[0],lambda[1],lambda[2]);

                maxlambda[0] = MAX(lambda[0], MAX(lambda[1],lambda[2])); // groesstes Tragheitsmoment

                    if (maxlambda[0] == lambda[0])
                    {
                  	maxlambda[1] = MAX(lambda[1],lambda[2]);
                  	maxlambda[2] = MIN(lambda[1],lambda[2]); 
                    }
                    else if (maxlambda[0] == lambda[1])
                    {
                  	maxlambda[1] = MAX(lambda[0],lambda[2]);
                  	maxlambda[2] = MIN(lambda[0],lambda[2]); 
                    }
                    else
                    {
                  	maxlambda[1] = MAX(lambda[0],lambda[1]);
                  	maxlambda[2] = MIN(lambda[0],lambda[1]);
                    }

                */

                //fprintf(stderr,"maxlambda:%lg %lg %lg\n",maxlambda[0],maxlambda[1],maxlambda[2]);

                // Bestimmung des Eigenvektors zum gr??ten Eigenwert, e.g. oblates Objekt
                //evec[2] = 1.;
                //evec[1] = ((usp->tt[k][0*3+0]-maxlambda[0])*usp->tt[k][1*3+2]*evec[2] - usp->tt[k][1*3+0]*usp->tt[k][0*3+2]*evec[2]);
                //evec[1] = evec[1] / (usp->tt[k][1*3+0]*usp->tt[k][0*3+1] + (maxlambda[0]-usp->tt[k][0*3+0])*(usp->tt[k][1*3+1]-maxlambda[0]));
                //evec[0] = (usp->tt[k][0*3+1]*evec[1] + usp->tt[k][0*3+2]*evec[2]) / (maxlambda[0]-usp->tt[k][0*3+0]);

                // Bestimmung des Eigenvektors zum kleinsten Eigenwert, e.g. prolates Objekt
                evec[2] = 1.;
                evec[1] = ((usp->tt[k][0*3+0]-maxlambda[2])*usp->tt[k][1*3+2]*evec[2] - usp->tt[k][1*3+0]*usp->tt[k][0*3+2]*evec[2]);
                evec[1] = evec[1] / (usp->tt[k][1*3+0]*usp->tt[k][0*3+1] + (maxlambda[2]-usp->tt[k][0*3+0])*(usp->tt[k][1*3+1]-maxlambda[2]));
                evec[0] = (usp->tt[k][0*3+1]*evec[1] + usp->tt[k][0*3+2]*evec[2]) / (maxlambda[2]-usp->tt[k][0*3+0]);

                double xlen = sqrt(evec[0]*evec[0]+evec[1]*evec[1]+evec[2]*evec[2]);

                for(j=0; j<3; j++)
                        evec[j] /= xlen;    // normierter Eigenvektor = Richtungsvektor der Haupttr??heitsachse

                //OUTPUT
                if(ismaster)
                        fprintf(usp->fh," %lg %lg %lg %lg %lg %lg",usp->coms[3*k],usp->coms[3*k+1],usp->coms[3*k+2],evec[0],evec[1],evec[2]);

        }
        if(ismaster)
                fprintf(usp->fh,"\n");
}
示例#17
0
//------------------------------------------------------------------------------
void ADRmohrCoulombFracture::evaluateStepTwo(const pair<int, int> &id_col)
{
    // First calculating the total stress on an material point. The stress is averaged
    // all its bonds, and the stress state on a bond is the mean of the
    // stress at each material point.

    const int id_i = id_col.first;
    const int col_i = id_col.second;

    if((*m_data)(col_i, m_indexUnbreakable) >= 1)
        return;

    vector<pair<int, vector<double>>> & PDconnections = m_particles->pdConnections(id_i);

    /*
    if(m_dim == 2)
    {
        arma::mat S_i(2, 2);
        arma::mat S(2, 2);
        S_i(0, 0) = (*m_data)(col_i, m_indexStress[0]);
        S_i(1, 1) = (*m_data)(col_i, m_indexStress[1]);
        S_i(0, 1) = (*m_data)(col_i, m_indexStress[3]);
        S_i(1, 0) = S_i(0, 1);
        arma::vec eigval;

        for(auto &con:PDconnections)
        {
            const int id_j = con.first;
            const int j = (*m_pIds)[id_j];

            if((*m_data)(j, m_indexUnbreakable) >= 1)
                continue;

            if(con.second[m_indexConnected] <= 0.5)
                continue;

            S(0, 0) = 0.5*(S_i(0, 0) + (*m_data)(j, m_indexStress[0]));
            S(1, 1) = 0.5*(S_i(1, 1) + (*m_data)(j, m_indexStress[1]));
            S(0, 1) = 0.5*(S_i(0, 1) + (*m_data)(j, m_indexStress[3]));
    //            S(0, 0) = max(S_i(0, 0), (*m_data)(j, m_indexStress[0]));
    //            S(1, 1) = max(S_i(1, 1), (*m_data)(j, m_indexStress[1]));
    //            S(0, 1) = max(S_i(0, 1), (*m_data)(j, m_indexStress[3]));
            S(1, 0) = S(0, 1);
            const double first = 0.5*(S(0, 0) + S(1, 1));
            const double second = sqrt(0.25*(S(0, 0) - S(1, 1))*(S(0, 0) - S(1, 1)) + S(0, 1)*S(0, 1));
            const double s1 = first + second;
            const double s2 = first - second;
            const double p_1 = max(s1, s2);
            const double p_2 = min(s1, s2);

    //            arma::eig_sym(eigval, S);
    //            const double p_1 = eigval(1);
    //            const double p_2 = eigval(0);

    //            if(m_d*p_1 - p_2 - m_C > 0)
    //            {
    //                con.second[m_indexConnected] = 0;
    //                m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con);
    //            }
    //            else if(p_1 > m_T)
            if(p_1 > m_T)
            {
    //                con.second[m_indexConnected] = 0;
                if(p_1 > m_maxStress)
                {
                    m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con);
                    m_maxStress = p_1;
                }
            }
        }
    }
    */
    arma::vec eigval(m_dim);
    arma::mat S_i(m_dim, m_dim);
    arma::mat S(m_dim, m_dim);

    if(m_dim == 2)
    {
        S_i(0, 0) = (*m_data)(col_i, m_indexStress[0]);
        S_i(1, 1) = (*m_data)(col_i, m_indexStress[1]);
        S_i(0, 1) = (*m_data)(col_i, m_indexStress[3]);
        S_i(1, 0) = S_i(0, 1);

        for(auto &con:PDconnections)
        {
            const int id_j = con.first;
            const int j = (*m_pIds)[id_j];

            if((*m_data)(j, m_indexUnbreakable) >= 1)
                continue;

            if(con.second[m_indexConnected] <= 0.5)
                continue;

            S(0, 0) = 0.5*(S_i(0, 0) + (*m_data)(j, m_indexStress[0]));
            S(1, 1) = 0.5*(S_i(1, 1) + (*m_data)(j, m_indexStress[1]));
            S(0, 1) = 0.5*(S_i(0, 1) + (*m_data)(j, m_indexStress[3]));
            S(1, 0) = S(0, 1);
#if 0
            arma::eig_sym(eigval, S);
            const double p_1 = eigval(1);
            const double p_2 = eigval(0);
#else
            const double first = 0.5*(S(0, 0) + S(1, 1));
            const double second = sqrt(0.25*(S(0, 0) - S(1, 1))*(S(0, 0) - S(1, 1)) + S(0, 1)*S(0, 1));
            const double s1 = first + second;
            const double s2 = first - second;
            const double p_1 = max(s1, s2);
            const double p_2 = min(s1, s2);
#endif

            if(m_d*p_1 - p_2 - m_C > 0)
            {
                con.second[m_indexConnected] = 0;
                m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con);
            }
            else if(p_1 > m_T)
            {
                con.second[m_indexConnected] = 0;
                m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con);
            }
        }
    }
    else if(m_dim == 3)
    {
        S_i(0, 0) = (*m_data)(col_i, m_indexStress[0]);
        S_i(1, 1) = (*m_data)(col_i, m_indexStress[1]);
        S_i(2, 2) = (*m_data)(col_i, m_indexStress[2]);
        S_i(0, 1) = (*m_data)(col_i, m_indexStress[3]);
        S_i(1, 0) = S_i(0, 1);
        S_i(0, 2) = (*m_data)(col_i, m_indexStress[4]);
        S_i(2, 0) = S_i(0, 2);
        S_i(1, 2) = (*m_data)(col_i, m_indexStress[5]);
        S_i(2, 1) = S_i(1, 2);

        for(auto &con:PDconnections)
        {
            const int id_j = con.first;
            const int col_j = (*m_pIds)[id_j];

            if((*m_data)(col_j, m_indexUnbreakable) >= 1)
                continue;

            if(con.second[m_indexConnected] <= 0.5)
                continue;

            S(0, 0) = 0.5*(S_i(0, 0) + (*m_data)(col_j, m_indexStress[0]));
            S(1, 1) = 0.5*(S_i(1, 1) + (*m_data)(col_j, m_indexStress[1]));
            S(2, 2) = 0.5*(S_i(2, 2) + (*m_data)(col_j, m_indexStress[2]));
            S(0, 1) = 0.5*(S_i(0, 1) + (*m_data)(col_j, m_indexStress[3]));
            S(1, 0) = S(0, 1);
            S(0, 2) = 0.5*(S_i(0, 2) + (*m_data)(col_j, m_indexStress[4]));
            S(2, 0) = S(0, 2);
            S(1, 2) = 0.5*(S_i(1, 2) + (*m_data)(col_j, m_indexStress[5]));
            S(2, 1) = S(1, 2);

#if 0
            arma::eig_sym(eigval, S);
            const double p_1 = eigval(2);
            const double p_2 = eigval(0);
#else
            const double I1 = S(0, 0) + S(1, 1) + S(2, 2);
            const double I2 = S(0, 0)*S(1, 1) + S(1, 1)*S(2, 2) + S(3, 3)*S(0, 0) - pow(S(0, 1), 2) - pow(S(1, 2), 2) - pow(S(0, 2), 2);
            const double I3 = S(0, 0)*S(1, 1)*S(2, 2) - S(0, 0)*pow(S(1, 2), 2) - S(1, 1)*pow(S(0, 2), 2) - S(2, 2)*pow(S(0, 1), 2) + 2*S(0, 1)*S(1, 2)*S(0, 2);
            const double phi = 1./3.*acos(0.5*(2*pow(I1, 3) -9*I1*I2 + 27*I3)/pow(pow(I1, 2) - 3*I2, 1.5));

            const double core = 2./3.*(sqrt(I1*I1 - 3*I2));
            const double s1 = I1/3. + core*cos(phi);
            const double s2 = I1/3. + core*cos(phi + 2.*M_PI/3.);
            const double s3 = I1/3. + core*cos(phi + 4.*M_PI/3.);

            double p_1 = s1;
            double p_2 = s2;

            if(s2>p_1)
            {
                p_1 = s2;
                p_2 = s1;
            }
            if(s3>p_1)
            {
                p_1 = s3;
            }
            else if(p_2 < s3) {
                p_2 = s3;
            }
#endif
            if(m_d*p_1 - p_2 - m_C > 0)
            {
                con.second[m_indexConnected] = 0;
                m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con);
            }
            else if(p_1 > m_T)
            {
                con.second[m_indexConnected] = 0;
                m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con);
            }
        }
    }
    //--------------------------------------------------------------------------
}
示例#18
0
void perform_main_computation (const bool fast, const bool verbose, 
    const arma::mat & coord, const arma::mat & param, 
    const std::string & cfname, const std::string & qfname,
    pca::pcafitter & fitter)
{
  // ordered 
  arma::vec eigval;
  // by row or by column ?
  arma::mat eigvec;

  if (!fast)
  {
    std::cout << "Perform PCA " << std::endl;
    // projection 
    arma::mat score;
  
    arma::princomp(eigvec, score, eigval, coord);
    std::cout << score.n_rows << " " << score.n_cols << std::endl;
    
    std::cout << "Writing Scoreplot" << std::endl;
    std::ofstream myfilesc("scoreplot.txt");
    
    for (int i=0; i<(int)score.n_rows; ++i)
    { 
      myfilesc << score(i,0)  << " "
               << score(i,1) << " " << score(i,2) << std::endl;
    
      if (verbose)
      {
        double mainr = 0.0e0;
        for (int j=1; j<5; ++j)
          mainr += score(i,j) * score(i,j);
        
        double residue = 0.0;
        for (int j=5; j<fitter.get_coordim(); ++j)
          residue += score(i,j) * score(i,j);
        
        std::cout << "Track " << i+1 << " residue " << residue <<
                     " mainr " << mainr << std::endl;
      }
    }
    
    myfilesc.close();
  }
  else
  {
    std::cout << "Compute correlation mtx" << std::endl;
    arma::mat coordm = arma::zeros<arma::mat>(fitter.get_coordim());
    arma::mat hca = arma::zeros<arma::mat>(fitter.get_coordim(),
        fitter.get_coordim());
    arma::vec eigvaltmp = arma::zeros<arma::vec>(fitter.get_coordim());

    eigvec = arma::zeros<arma::mat>(fitter.get_coordim(),
        fitter.get_coordim());
    eigval = arma::zeros<arma::vec>(fitter.get_coordim());

    hca = arma::cov(coord);

    /* double check 
    double sum = 1.0e0;
    for (int l=0; l<(int)coord.n_rows; ++l) 
    {
      sum += 1.0e0;
      for (int i=0; i<fitter.get_coordim(); ++i)
        coordm(i) += (coord(l,i)-coordm(i))/sum;
    
      for (int i=0; i<fitter.get_coordim(); ++i)
      {
        for (int j=0; j<fitter.get_coordim(); ++j)
        {
          hca(i,j) += ((coord(l,i) - coordm(i))*
                       (coord(l,j) - coordm(j))-
                       (sum-1.0e0)*hca(i,j)/sum)/(sum-1.0e0);
        }
      }
    }
    */

    std::cout << "Eigensystem" << std::endl;
    arma::eig_sym(eigvaltmp, eigvec, hca);
 
    for (int i=0; i<fitter.get_coordim(); ++i)
      eigval(i) = eigvaltmp(fitter.get_coordim()-i-1);
  }


  double totval = 0.0e0;
  for (int i=0; i<fitter.get_coordim(); ++i)
    totval += eigval(i);

  std::cout << "Eigenvalues: " << std::endl;
  double totvar = 0.0e0; 
  for (int i=0; i<fitter.get_coordim(); ++i)
  {
    if (i < fitter.get_paramdim())
      totvar += 100.0e0*(eigval(i)/totval);

    std::cout << i+1 << " ==> " << 100.0e0*(eigval(i)/totval) 
              << "% value: " << eigval(i) <<  std::endl;
  }
  std::cout << "PARAMDIM eigenvalues: " << totvar << std::endl;

  std::cout << fitter.get_paramdim() << " X " << fitter.get_coordim() << std::endl;

  arma::mat cmtx = arma::zeros<arma::mat>(fitter.get_paramdim(),
      fitter.get_coordim());
  arma::rowvec q = arma::zeros<arma::rowvec>(fitter.get_paramdim());

  std::cout << "Compute PCA constants " << std::endl;
  fitter.compute_pca_constants (param,
      coord, cmtx, q);

  std::cout << "Write constant to file" << std::endl;
  pca::write_armmat(cfname.c_str(), cmtx);
  pca::write_armvct(qfname.c_str(), q);
}
示例#19
0
void
ComputeSmearedCrackingStress::computeCrackStrainAndOrientation(
    RealVectorValue & strain_in_crack_dir)
{
  // The rotation tensor is ordered such that directions for pre-existing cracks appear first
  // in the list of columns.  For example, if there is one existing crack, its direction is in the
  // first column in the rotation tensor.
  const unsigned int num_known_dirs = getNumKnownCrackDirs();

  if (num_known_dirs == 0)
  {
    std::vector<Real> eigval(3, 0.0);
    RankTwoTensor eigvec;

    _elastic_strain[_qp].symmetricEigenvaluesEigenvectors(eigval, eigvec);

    // If the elastic strain is beyond the cracking strain, save the eigen vectors as
    // the rotation tensor. Reverse their order so that the third principal strain
    // (most tensile) will correspond to the first crack.
    _crack_rotation[_qp].fillColumn(0, eigvec.column(2));
    _crack_rotation[_qp].fillColumn(1, eigvec.column(1));
    _crack_rotation[_qp].fillColumn(2, eigvec.column(0));

    strain_in_crack_dir(0) = eigval[2];
    strain_in_crack_dir(1) = eigval[1];
    strain_in_crack_dir(2) = eigval[0];
  }
  else if (num_known_dirs == 1)
  {
    // This is easily the most complicated case.
    // 1.  Rotate the elastic strain to the orientation associated with the known
    //     crack.
    // 2.  Extract the lower 2x2 block into a separate tensor.
    // 3.  Run the eigen solver on the result.
    // 4.  Update the rotation tensor to reflect the effect of the 2 eigenvectors.

    // 1.
    const RankTwoTensor & R = _crack_rotation[_qp];
    RankTwoTensor ePrime(_elastic_strain[_qp]);
    ePrime.rotate(R.transpose()); // elastic strain in crack coordinates

    // 2.
    ColumnMajorMatrix e2x2(2, 2);
    e2x2(0, 0) = ePrime(1, 1);
    e2x2(1, 0) = ePrime(2, 1);
    e2x2(0, 1) = ePrime(1, 2);
    e2x2(1, 1) = ePrime(2, 2);

    // 3.
    ColumnMajorMatrix e_val2x1(2, 1);
    ColumnMajorMatrix e_vec2x2(2, 2);
    e2x2.eigen(e_val2x1, e_vec2x2);

    // 4.
    RankTwoTensor eigvec(
        1.0, 0.0, 0.0, 0.0, e_vec2x2(0, 1), e_vec2x2(1, 1), 0.0, e_vec2x2(0, 0), e_vec2x2(1, 0));

    _crack_rotation[_qp] = _crack_rotation_old[_qp] * eigvec; // Roe implementation

    strain_in_crack_dir(0) = ePrime(0, 0);
    strain_in_crack_dir(1) = e_val2x1(1, 0);
    strain_in_crack_dir(2) = e_val2x1(0, 0);
  }
  else if (num_known_dirs == 2 || num_known_dirs == 3)
  {
    // Rotate to cracked orientation and pick off the strains in the rotated
    // coordinate directions.
    const RankTwoTensor & R = _crack_rotation[_qp];
    RankTwoTensor ePrime(_elastic_strain[_qp]);
    ePrime.rotate(R.transpose()); // elastic strain in crack coordinates

    strain_in_crack_dir(0) = ePrime(0, 0);
    strain_in_crack_dir(1) = ePrime(1, 1);
    strain_in_crack_dir(2) = ePrime(2, 2);
  }
  else
    mooseError("Invalid number of known crack directions");
}
void ATO::ModalObjective<PHAL::AlbanyTraits::Residual, Traits>::
evaluateFields(typename Traits::EvalData workset)
{

  Albany::MDArray F    = (*workset.stateArrayPtr)[FName];
  Albany::MDArray dEdp = (*workset.stateArrayPtr)[dFdpName];
  Albany::MDArray topo = (*workset.stateArrayPtr)[topology->getName()];
  std::vector<int> dims;
  gradX.dimensions(dims);
  int size = dims.size();

  int numCells = dims[0];
  int numQPs = dims[1];
  int numDims = dims[2];
  int numNodes = topo.dimension(1);

  if( size == 4 ){
    for(int cell=0; cell<numCells; cell++){
      double dE = 0.0;
      double dmass_term = 0.;
      double dstiffness_term = 0.;
      for(int qp=0; qp<numQPs; qp++){
        double topoVal = 0.0;
        for(int node=0; node<numNodes; node++)
          topoVal += topo(cell,node)*BF(cell,node,qp);
        double P = topology->Penalize(functionIndex,topoVal);
        double dP = topology->dPenalize(functionIndex,topoVal);
        double dE = 0.0;
        double dmass_term = 0.;
        double dstiffness_term = 0.;
        for(int i=0; i<numDims; i++) {
          dmass_term += val_qp(cell,qp,i)*val_qp(cell,qp,i) * qp_weights(cell,qp);
          for(int j=0; j<numDims; j++)
            dstiffness_term += dP*gradX(cell,qp,i,j)*workConj(cell,qp,i,j)*qp_weights(cell,qp);
        }
        for(int node=0; node<numNodes; node++)
        dEdp(cell,node) = -(dstiffness_term - dmass_term*eigval(0))*BF(cell,node,qp);
      }
//tevhack        std::cout << "dEdp(" << cell << ") = " << dEdp(cell) << std::endl;
    }
  } else {
    TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
      "Unexpected array dimensions in StiffnessObjective:" << size << std::endl);
  }

/*
  if( size == 3 ){
    for(int cell=0; cell<numCells; cell++){
      double dE = 0.0;
      double P = topology->Penalize(topo(cell));
      for(int qp=0; qp<numQPs; qp++) {
        for(int i=0; i<numDims; i++) {
          dE += val_qp(cell,qp,i) * val_qp(cell,qp,i);
        }
        for(int node=0; node<numNodes; node++)
          dEdp(cell,node) = dE/P*BF(cell,node,qp);
      }
      std::cout << "dEdp(" << cell << ") = " << dEdp(cell) << std::endl;
    }
  } else {
    TEUCHOS_TEST_FOR_EXCEPTION(
      true, 
      Teuchos::Exceptions::InvalidParameter,
      "Unexpected array dimensions in ModalObjective:" << size << std::endl
    );
  }
*/

  F(0) = -eigval(0);

}