예제 #1
0
파일: cg.cpp 프로젝트: baptiste/cda
//
// Solves a linear system iteratively via conjugate-gradient
//
// A: complex matrix
// y:  right-hand side
// x0:  initial guess
// nmax:  max number of iterations
// tol:  tolerance
// [[Rcpp::export]]
arma::cx_mat cpp_cg_solve(const arma::cx_mat& A,
			 const arma::cx_mat& y,
			 arma::cx_mat& x0,
			 const double nmax,
			 const double tol)
{

  int n = 0, ii = 0; // counter
  const int nr = y.n_cols; // number of right-hand side cols
  double rel_error = 1e4; // large value
  const int N = y.n_rows;

  // temporary variables
  double alpha_i, beta_i;
  const arma::cx_mat B = A.t(); // Hermitian transpose.
                                // Note: diag blocks not symmetric, so no easier way
  arma::cx_colvec y_i(N), z_i(N), g_i(N), p_i(N), w_i(N), v_i(N), x_i(N);
  arma::cx_colvec g_ip1(N), p_ip1(N), w_ip1(N), v_ip1(N), x_ip1(N);

  // loop over RHS cols
  for (ii=0; ii < nr; ii++){

    // initial step
    y_i = y.col(ii);
    z_i = B * y_i;
    x_i = x0.col(ii);
    g_i = z_i - B * A * x_i;
    p_i = g_i;
    w_i = A * x_i;
    v_i = A * p_i;

    n = 0; rel_error = 1e4;
    while ((n < nmax) && (rel_error > tol)){

      alpha_i = real(cdot(g_i, g_i) / cdot(v_i, v_i));
      x_ip1 = x_i + alpha_i * p_i;
      w_ip1 = w_i + alpha_i * v_i;
      g_ip1 = z_i - B * w_ip1;
      beta_i = real(cdot(g_ip1,g_ip1) / cdot(g_i,g_i));
      // updating
      p_i = g_ip1 + beta_i * p_i;
      v_i = A * p_i;
      rel_error = norm(x_ip1 - x_i) / norm(x_ip1) ;
      x_i = x_ip1;
      if(rel_error < tol) break; // skip cost of next line
      w_i = A * x_i;
      g_i = g_ip1;
      n++;
    }; // end while
    x0.col(ii) = x_i;
  }; //end loop

  return x0;
}
예제 #2
0
파일: dispersion.cpp 프로젝트: baptiste/cda
    //
    // Angle-resolved spectra for linear or circular polarisations
    //
    // kn: vector of incident wavenumbers
    // medium: surrounding refractive index
    // R: Nx3 matrix of positions
    // Alpha: 3NxNl matrix of principal polarisabilities
    // Angles:  Nx3 matrix of particle rotation angles
    // Incidence:  Ni vector of incident beam directions
    // Axes:  Ni vector of incident beam axes
    // ScatteringNodes:  2xNs matrix of scattered field directions
    // ScatteringWeights:  Ns vector of scattered field quadrature weights
    // polarisation: integer flag to switch between linear and circular polarisation
    // inversion: integer flag to use different inversion methods
    // maxiter:  max number of iterations
    // tol:  tolerance
    // progress: logical flag to display progress bars
    // [[Rcpp::export]]
    arma::cube cpp_dispersion_spectrum(const arma::colvec kn,
      const double medium,
      const arma::mat& R,
      const arma::cx_mat& Alpha,
      const arma::mat& Angles,
      const arma::vec& Incidence,
      const arma::ivec& Axes,
      const arma::mat& ScatteringNodes,
      const arma::vec& ScatteringWeights,
      const int polarisation,
      const int inversion,
      const int maxiter,
      const double tol,
      const bool progress)
      {

        const int Ni = Incidence.n_elem;
        int Nl = kn.n_elem, Nr = R.n_cols, ll;
        arma::cube res(Ni, 6, Nl);
        arma::mat tmp(Ni, 6);

        // global, will update at each wavelength
        arma::cx_cube AlphaBlocks = arma::zeros<arma::cx_cube>(3, 3, Nr);

        // global, will update at each wavelength
        arma::cx_mat A(3*Nr, 3*Nr );
        if(inversion < 2) { // full interaction matrix
          A.eye();
        } else if (inversion == 2){ // only propagator G = I - A
          A.zeros();
        }

        for(ll=0; ll<Nl; ll++){ // loop over kn
          if(progress)
          progress_bar(ll+1,Nl);

          // update in place
          cpp_alpha_blocks_update(Alpha.col(ll), Angles, AlphaBlocks);

          // if solve or cg, need full A, otherwise just G
          if(inversion < 2) { // full interaction matrix
            // update in place
            cpp_interaction_matrix_update(R, kn(ll), AlphaBlocks, A);
          } else if (inversion == 2){ // only propagator G = I - A
            // update in place
            cpp_propagator_update(R, kn(ll), AlphaBlocks, A);
          }

          tmp = cpp_dispersion(R, A, AlphaBlocks, kn(ll), medium,
          Incidence, Axes, ScatteringNodes, ScatteringWeights, polarisation, inversion, maxiter, tol);
          // Rcpp::Rcout << tmp << "\n";

          res.slice(ll) = 1.0/Nr * tmp;
        }
        if(progress)
        Rcpp::Rcout << "\n";

        return res ;
      }
예제 #3
0
파일: cI.cpp 프로젝트: sjjko/ksdft
arma::cx_mat cI::operator*(arma::cx_mat  input)
{


arma::cx_mat outputMAT(prod(_S),input.n_cols);


if(input.n_rows==prod(_S))
{
    for(unsigned int i=0;i<input.n_cols;i++)
    {
        //func_fftn(arma::cx_vec vec_Inp,arma::Col<int> S,const string forward_or_backward)
        //check(_Faktor,input.col(i),"*"); // check if _Faktor has as many cols as input rows
        outputMAT.col(i)=func_fftn(input.col(i),this->_S,"backward");
    }
}
else
{
   // verbosity(*_Pa,"CI: do the transform",2,__FILE__,__LINE__);

    for(unsigned int i=0;i<input.n_cols;i++)
    {
    //verbosity(*_Pa,"CI: do it for column"+std::to_string(i),2,__FILE__,__LINE__);

        //func_fftn(arma::cx_vec vec_Inp,arma::Col<int> S,const string forward_or_backward)
        //check(_Faktor,input.col(i),"*"); // check if _Faktor has as many cols as input rows
//        cout << size(full(_Pa->activeIndices)) << endl;
//                cout << size(input) << endl;
//                cout << size(input.col(i)) << endl;
//                cout << size(test) << endl;

//        for(int j=0;j<_Pa->numberOfActiveIndices;j++)
//        {
//        cout << uv(j) << " " << j << endl;
//        full(uv(j),0)=input(j,i);
//        }
        _full=arma::zeros<arma::cx_mat>(arma::prod(_S),1);
        _full(_uv)=input.col(i);
        outputMAT.col(i)=func_fftn(_full,this->_S,"backward");
    }
}

return outputMAT;
}