1 #ifndef QNANO_NEW_MANYBODY_PERTURBATIVE_CORRECTION_TEMPLATE_DEFINED_H     2 #define QNANO_NEW_MANYBODY_PERTURBATIVE_CORRECTION_TEMPLATE_DEFINED_H     5 template <
class Tsolver> 
void Communicate_Complex_Vector_Template(Tsolver *solver, std::vector<std::complex<double> > &EV2){
     8 #ifdef QNANO_NEW_SLEPC_SOLVER_DEFINED_H_     9 template <> 
void Communicate_Complex_Vector_Template<SLEPc_Solver>(
SLEPc_Solver* solver, std::vector<std::complex<double> > &EV2){
    10   MPI_Allreduce(MPI_IN_PLACE, &EV2[0], EV2.size()*2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
    16 template <
class Tsolver> 
void Communicate_Append_Int_Vector_Template(Tsolver *solver, std::vector<int> &newstates_indices){
    18 #ifdef QNANO_NEW_SLEPC_SOLVER_DEFINED_H_    19 template <> 
void Communicate_Append_Int_Vector_Template<SLEPc_Solver>(
SLEPc_Solver *solver, std::vector<int> &newstates_indices){
    20   int MPI_rank, MPI_size;
    21   MPI_Comm_size(MPI_COMM_WORLD, &MPI_size);
    22   MPI_Comm_rank(MPI_COMM_WORLD, &MPI_rank);
    25     for(
size_t j=1; (int)j<MPI_size; j++){
    27       MPI_Recv(&vectorsize, 1, MPI_INT, j, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    28       size_t oldsize=newstates_indices.size();
    29       newstates_indices.resize(oldsize+vectorsize);
    30       MPI_Recv(&newstates_indices[oldsize], vectorsize, MPI_INT, j, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    33     int vectorsize=newstates_indices.size();
    34     MPI_Send(&vectorsize, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
    35     MPI_Send(&newstates_indices[0], vectorsize, MPI_INT, 0, 0, MPI_COMM_WORLD);
    42   std::string PT_outfile=param_map.get_as_string(
"PT_outfile",
"");
    43   if(PT_outfile==
"")
return;
    45   int nr_print=EVprinter->get_actual_nr_print();
    46   nr_print=param_map.get_as_double(
"nr_PT",nr_print);
    47   if(nr_print>EVprinter->get_n_converged())nr_print=EVprinter->get_n_converged();
    50   bool should_print=solver->should_print();  
    52   double small_denominator_threshold=param_map.get_as_double(
"small_denominator_threshold", 1e-5);
    56   if(should_print)std::cout<<
"Setting up manybody Hamiltonian for perturbative corrections..."<<std::endl;
    58   int nr_e2=param_map.get_as_sizet(
"nr_e_PT",0);
    59   int nr_h2=param_map.get_as_sizet(
"nr_h_PT",0);
    60   if(nr_e2<hamil->hilbert->get_nr_e()){
    61     std::cerr<<
"nr_e_PT < nr_e !"<<std::endl;
    64   if(nr_h2<hamil->hilbert->get_nr_h()){
    65     std::cerr<<
"nr_h_PT < nr_h !"<<std::endl;
    68   int s_nr_e=param_map.get_as_sizet(
"selected_nr_e");
    69   if(!param_map.is_specified(
"selected_nr_e")){
    70     s_nr_e=hamil->hilbert->get_nr_e();
    72   int s_nr_h=param_map.get_as_sizet(
"selected_nr_h");
    73   if(!param_map.is_specified(
"selected_nr_h")){
    74     s_nr_h=hamil->hilbert->get_nr_h();
    79   param_map2.override_parameter(
"nr_e", Reader::toString(nr_e2));
    80   param_map2.override_parameter(
"nr_h", Reader::toString(nr_h2));
    81   param_map2.override_parameter(
"selected_nr_e", Reader::toString(s_nr_e));
    82   param_map2.override_parameter(
"selected_nr_h", Reader::toString(s_nr_h));
    89     hilbert2.add_singles();
    90     hilbert2.add_singles();
    92     hamil2.replace_hilbert_space(hilbert2);
    97     std::cout<<
"Dimension of original Hilbert space: "<<hamil->get_DIM()<<std::endl;
    98     std::cout<<
"Dimension of new Hilbert space: "<<hamil2.get_DIM()<<std::endl;
   104   std::vector<int> newstates_indices;
   105   double threshold=param_map.get_as_double(
"threshold");
   107   if(param_map.is_specified(
"new_states_file") &&
   108      param_map.is_specified(
"add_new_states_file") ){
   109     std::cerr<<
"Please set either 'new_states_file' or 'add_new_states_file', but not both!"<<std::endl;
   113   int existing_states_in_new_states_file=0;
   114   std::string new_states_file=param_map.get_as_string(
"new_states_file");
   115   if(param_map.is_specified(
"add_new_states_file")){
   116     new_states_file=param_map.get_as_string(
"add_new_states_file");
   117     newstates.add_from_file(new_states_file, \
   118       hamil2.hilbert->get_rank_e(), hamil2.hilbert->get_rank_h(), 
   119       hamil2.hilbert->get_nr_e(), hamil2.hilbert->get_nr_h());
   120     existing_states_in_new_states_file=newstates.size();
   123   bool print_new_states=
false;
   124   if(new_states_file!=
""){
   125     print_new_states=
true;
   132     ofs.open(PT_outfile.c_str());
   133     ofs<<
"#DIM "<<hamil->get_DIM()<<
" -> "<<hamil2.get_DIM()<<std::endl;
   134     std::cout<<std::setprecision(10);
   135     ofs<<std::setprecision(10);
   145   size_t nr_blocks=param_map.get_as_sizet(
"nr_blocks",1);
   146   if(param_map.is_specified(
"EV_per_block")){
   147     size_t EV_per_block=param_map.get_as_sizet(
"EV_per_block");
   148     if(EV_per_block<1){std::cerr<<
"EV_per_block<1!"<<std::endl;exit(1);}
   149     nr_blocks=nr_print/EV_per_block;
   150     if((
int)(nr_blocks*EV_per_block)<(
int)nr_print)nr_blocks++;
   153   std::cout<<
"nr_blocks: "<<nr_blocks<<std::endl;
   157   for(
size_t bl=0; bl<db_EV.get_nr_blocks(); bl++){
   158     size_t this_nr=db_EV.get_blocksize(bl);
   160       std::cout<<
"block: "<<bl<<
"/"<<db_EV.get_nr_blocks()<<std::endl;
   164     std::vector<std::vector<std::complex<double> > > EV2(this_nr,  \
   165       std::vector<std::complex<double> >(hamil2.get_DIM(),0.));
   167     std::vector<double> eigenvalue(this_nr,0);
   168     std::vector<std::vector<std::complex<double> > >EV_local(this_nr, \
   169       std::vector<std::complex<double> >(db->get_local_blocksize(),0.));
   171     for(
size_t i=0; i<this_nr; i++){  
   172       eigenvalue[i]=solver->get_eigenvalue(db_EV.get_start(bl)+i);
   173       solver->get_EV_local_part(db_EV.get_start(bl)+i, &EV_local[i][0]);
   176     for(
size_t j=0; j<db->get_local_blocksize(); j++){
   177       int j2=db->get_local_start()+j;
   178       std::vector< col_val > col_val_vec;
   180       hamil2.get_Matrix_row_block(col_val_vec, fi);
   181       for(
size_t k=0; k<col_val_vec[0].size(); k++){
   182         int Hcol=col_val_vec[0][k].first;
   183         std::complex<double> Hval=std::conj(col_val_vec[0][k].second);
   184         for(
size_t i=0; i<this_nr; i++){  
   185           EV2[i][Hcol]+=Hval*EV_local[i][j];
   192       std::cout<<
"Communicating EV2..."<<std::endl;
   194     for(
size_t i=0; i<this_nr; i++){  
   195       Communicate_Complex_Vector_Template<Tsolver>(solver, EV2[i]);
   201       std::cout<<
"Calculating corrections..."<<std::endl;
   204     std::vector<double> corr(this_nr,0.);
   206     std::vector<double> maxcontrib(this_nr,0.);
   207     std::vector<int> nr_small_denominator(this_nr,0);
   209    for(
size_t j=db2->get_local_start(); j<db2->get_local_start()+db2->get_local_blocksize(); j++){
   212     int k=hamil->hilbert->get_index(fi);
   214       double e=hamil2.get_diagonal(fi);
   216       for(
size_t i=0; i<this_nr; i++){  
   217         double numerator=(std::conj(EV2[i][j])*EV2[i][j]).real();
   218         double denominator=(e-eigenvalue[i]);
   220         if(print_new_states && fabs(denominator)<small_denominator_threshold){
   221           nr_small_denominator[i]++;
   222           newstates_indices.push_back(j);
   226         corr[i]-=numerator/denominator;
   228         if(print_new_states){
   229           double contrib=abs(EV2[i][j]/denominator);
   230           if(contrib>maxcontrib[i])maxcontrib[i]=contrib;
   231           if(!added && contrib>threshold){
   232             newstates_indices.push_back(j);
   242       std::cout<<
"Communicating and printing perturbative corrections..."<<std::endl;
   244     for(
size_t i=0; i<this_nr; i++){  
   246       {std::vector<std::complex<double> > c_corr(1,corr[i]); 
   247       Communicate_Complex_Vector_Template<Tsolver>(solver, c_corr);
   248       corr[i]=c_corr[0].real();}
   258         std::cout<<eigenvalue[i]<<
" ";
   259         ofs<<eigenvalue[i]<<
" ";
   260         if(nr_small_denominator[i]>0){
   261           std::cout<<
"ILL_DEFINED_"<<nr_small_denominator[i]<<
"_";
   262           ofs<<
"ILL_DEFINED_"<<nr_small_denominator[i]<<
"_";
   266         std::cout<<std::endl;
   267         std::cout<<
"Maximum contribution from new state: "<<maxcontrib[i]<<std::endl;
   270         ofs<<
" "<<maxcontrib[i];
   279     std::cout<<
"Communicating and printing new states..."<<std::endl;
   281   Communicate_Append_Int_Vector_Template<Tsolver>(solver, newstates_indices);
   285   if(should_print)
for(
size_t j=0; j<newstates_indices.size(); j++){
   287     newstates.add_if_not_contained(fi);
   293     newstates.print(new_states_file);
   294     std::cout<<
"Threshold: "<<threshold<<std::endl;
   295     std::cout<<
"Adding "<<newstates.size()-existing_states_in_new_states_file;
   296     std::cout<<
" states to new_states_file '"<<new_states_file;
   297     std::cout<<
"' gives a total of "<<newstates.size()<<
" states."<<std::endl;
   298     std::cout<<
"Perturbative corrections done."<<std::endl;
 Definition: Parameter_Map.h:12
 
Definition: Communicator.h:19
 
Definition: SLEPc_Solver.h:12
 
Definition: Fermion_Double_Index.h:14
 
Definition: Distribute_Block.h:7
 
Definition: Distribute_Block_Local.h:15
 
virtual void Reduce_Max_Double(double &d) const 
Maximal value from all thread is communicated to the root. 
Definition: Communicator.h:31
 
Definition: Selected_Manybody_Hilbert_Space.h:7
 
Definition: Eigenvector_Printer.h:8
 
Definition: Selected_Manybody_States_with_Hash_Table.h:8
 
Definition: Manybody_Hamiltonian.h:14