コード例 #1
0
void Wfcgrid::update_propagator_2D(double dt,double m0){
/**
  \brief Update real-space propagators for 2D grid
  \param[in] dt Integration time
  \param[in] m0 Mass of the particle (effective DOF)

  working in atomic units: hbar = 1
*/

  int nst, nst1;

  MATRIX* diaH; diaH = new MATRIX(nstates,nstates);
  MATRIX* adiH; adiH = new MATRIX(nstates,nstates);
  MATRIX* S; S = new MATRIX(nstates, nstates);  S->Init_Unit_Matrix(1.0);
  MATRIX* C; C = new MATRIX(nstates, nstates);  *C = 0.0;
  MATRIX* si; si = new MATRIX(nstates, nstates);  *si = 0.0; // cos(-dt*E), where E is adiabatic Ham.
  MATRIX* cs; cs = new MATRIX(nstates, nstates);  *cs = 0.0; // sin(-dt*E), where E is adiabatic Ham.



  // For each 2D grid point
  for(int nx=0;nx<Nx;nx++){
    for(int ny=0;ny<Ny;ny++){


      // Get diabatic Hamiltonian (in real form)
      for(nst=0;nst<nstates;nst++){  
        for(nst1=0;nst1<nstates;nst1++){  
          diaH->M[nst*nstates+nst1] = H[nst][nst1].M[nx*Ny+ny].real();
        }
      }

      // Transformation to adiabatic basis
      solve_eigen(nstates, diaH, S, adiH, C);  // diaH * C = S * C * adiH


      // Now compute sin and cos matrixes: diagonal
      *cs = 0.0;  *si = 0.0;
      for(int nst=0;nst<nstates;nst++){  
        cs->M[nst*nstates+nst] = std::cos(-dt*adiH->M[nst*nstates+nst]);
        si->M[nst*nstates+nst] = std::sin(-dt*adiH->M[nst*nstates+nst]);
      }
 
      // Transform cs and si according to matrix C:
      *cs = (*C) * (*cs) * ((*C).T());
      *si = (*C) * (*si) * ((*C).T());



      // Finally construct complex exp(-i*dt*H) matrix from real cs and si matrices
      for(nst=0;nst<nstates;nst++){  
        for(nst1=0;nst1<nstates;nst1++){  

          expH[nst][nst1].M[nx*Ny+ny] = complex<double>(cs->M[nst*nstates+nst1], si->M[nst*nstates+nst1]);  // exp(-i*H*dt)

        }
      }//for nst


    }// for ny
  }// for nx


  delete S;
  delete C;
  delete diaH;
  delete adiH;
  delete cs;
  delete si;


}// update_propagator_2D
コード例 #2
0
void Hamiltonian_Extern::compute_adiabatic(){
/** This function "computes" adiabatic PESs (energies and derivatives) and derivative couplings
  Here, we have 2 options:
  - adiabatic Hamiltonian and its derivatives are bound - we simply use them ("adiabatic_opt==0")
  - diabatic Hamiltonian and its derivatives are bound (bud we use "adiabatic_opt ==1" ) -
    - we need to perfrom diabatic -> adiabatic transformation, like in the Hamiltonian_Model case

 To distinguish these two cases, we use additional parameter - "adiabatic_opt"
*/
 
  if(adiabatic_opt==0){ 
    // Everything is done already - don't do anything special, other than check the bindings

    if(status_adi == 0){ // only compute this is the result if not up to date

      // setup ham_adi, d1ham_adi, and d2ham_adi matrices, so below we will basically 
      // check regarding the status of bindings

      if(bs_ham_adi == 0){  
        cout<<"Error in Hamiltonian_Extern::compute_adiabatic (with option adiabatic_opt == 0)\n";
        cout<<"Adiabatic Hamiltonian has not been bound to the Hamiltonian_Extern object\n";
        cout<<"use \"bind_ham_adi\" function\n";
        exit(0);
      }
      if(bs_d1ham_adi == 0){  
        cout<<"Error in Hamiltonian_Extern::compute_adiabatic (with option adiabatic_opt == 0)\n";
        cout<<"Derivatives of adiabatic Hamiltonian have not been bound to the Hamiltonian_Extern object\n";
        cout<<"use \"bind_d1ham_dia\" function\n";
        exit(0);
      }

      // Now it is ok, so far we don't care about d2ham_dia matrices!!!  

      // Set status flag 
      status_adi = 1;

    }//   status_dia == 0

  }// adiabatic_opt == 0

  else if(adiabatic_opt==1){

    compute_diabatic();

    if(status_adi == 0){

      MATRIX* S; S = new MATRIX(nelec, nelec);  S->Init_Unit_Matrix(1.0);
      MATRIX* C; C = new MATRIX(nelec, nelec);  *C = 0.0;

      // Transformation to adiabatic basis
      solve_eigen(nelec, ham_dia, S, ham_adi, C);  // H_dia * C = S * C * H_adi

      // Now compute the derivative couplings (off-diagonal, multiplied by energy difference) and adiabatic gradients (diagonal)
      for(int n=0;n<nnucl;n++){

        *d1ham_adi[n] = (*C).T() * (*d1ham_dia[n]) * (*C);

      }// for n

      delete S;
      delete C;

      // Set status flag
      status_adi = 1;

    }// status_adi == 0

  }// adiabatic_opt == 1
  
}