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