123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /**********************************************************
-
- This software is part of J.-S. Caux's ABACUS library.
-
- Copyright (c) J.-S. Caux.
-
- -----------------------------------------------------------
-
- File: NRG_DFF_Matrix_Block_builder.cc
-
- Purpose: calculate matrix elements of density operator between
- selected states in NRG for a selected block of the whole matrix.
- For collaboration with Robert Konik.
-
- ***********************************************************/
-
- #include "ABACUS.h"
-
- using namespace std;
- using namespace ABACUS;
-
- namespace ABACUS {
-
- void Build_DME_Matrix_Block_for_NRG (DP c_int, DP L, int N, int iKmin, int iKmax,
- int Nstates_required, bool symmetric_states, int iKmod,
- int weighing_option, int nrglabel_left_begin, int nrglabel_left_end,
- int nrglabel_right_begin, int nrglabel_right_end,
- int block_option, DP* DME_block_1, DP* DME_block_2, Vect_DP Kweight)
- {
- // Given a list of states produced by Select_States_for_NRG, this function
- // computes all the density form factors < lstate| \rho | rstate >
- // for all id_left_begin <= id_left <= id_left_end (similarly for right states).
-
- // The block_option flag determines what kind of data is written in the 2 DME blocks.
- // If !symmetric_states, then only block 1 is filled.
- // If symmetric_states, then
- // if block_option == 1, only block 1 is filled with the symmetric states ME.
- // if block_option == 2, both blocks 1 and 2 are filled with ME and ME (after parity) respectively.
-
- // ASSUMPTIONS:
- // We assume the DME_blocks are already reserved in memory.
- // If !symmetric states, DME_block_2 doesn't need to be allocated.
-
- if (nrglabel_left_begin < 0 || nrglabel_right_begin < 0)
- ABACUSerror("beginning nrglabels negative in Build_DME_Matrix_Block_for_NRG");
- if (nrglabel_left_end >= Nstates_required)
- ABACUSerror("nrglabel_left_end too large in Build_DME_Matric_Block_for_NRG");
- if (nrglabel_right_end >= Nstates_required)
- ABACUSerror("nrglabel_right_end too large in Build_DME_Matric_Block_for_NRG");
-
- if (nrglabel_left_begin > nrglabel_left_end)
- ABACUSerror("nrglabels of left states improperly chosen in DME block builder.");
- if (nrglabel_right_begin > nrglabel_right_end)
- ABACUSerror("nrglabels of right states improperly chosen in DME block builder.");
-
- // DME_block is a pointer of size row_l * col_l, where
- int block_row_length = nrglabel_right_end - nrglabel_right_begin + 1;
- int block_col_length = nrglabel_left_end - nrglabel_left_begin + 1;
-
- // iKmod is an integer specifying that we're only interested in momenta multiples of
- // a base unit. In other words, if the perturbation potential repeats itself iKmod times
- // on the periodic cycle on which the theory is defined, then we only need states such
- // that iKl - iKr = (integer) * iKmod. We impose this constraint at the same time as
- // the check on the weight of the state.
-
- // We start by reading off the list of selected states:
-
- stringstream NRG_stringstream;
- string NRG_string;
-
- NRG_stringstream << "States_";
- NRG_stringstream << "c_" << c_int << "_L_" << L << "_N_" << N
- << "_iKmin_" << iKmin << "_iKmax_" << iKmax << "_Nstates_" << Nstates_required
- << "_Sym_" << symmetric_states << "_iKmod_" << iKmod << "_wopt_" << weighing_option << ".nrg";
-
- NRG_string = NRG_stringstream.str();
- const char* NRG_Cstr = NRG_string.c_str();
-
- ifstream infile;
- infile.open(NRG_Cstr);
-
- if (infile.fail()) {
- cout << NRG_Cstr << endl;
- ABACUSerror("The input file was not opened successfully in Build_DME_Matrix_between_Selected_States_for_NRG. ");
- }
-
- // Read the whole data file:
- const int MAXDATA = ABACUS::max(nrglabel_left_end, nrglabel_right_end) + 10; // 10 for safety...
-
- int* nrglabel = new int[MAXDATA];
- DP* omega = new DP[MAXDATA];
- int* iK = new int[MAXDATA];
- string* label = new string[MAXDATA];
- bool* sym = new bool[MAXDATA];
- DP* weight = new DP[MAXDATA];
-
- int Ndata = 0;
- while (((infile.peek()) != EOF) && (Ndata < MAXDATA)) {
-
- infile >> nrglabel[Ndata];
- if (nrglabel[Ndata] != Ndata) ABACUSerror("reading states nrglabels wrong in NRG_DME_Matrix_Block_builder");
- infile >> omega[Ndata];
- infile >> iK[Ndata];
- infile >> label[Ndata];
- infile >> sym[Ndata];
- infile >> weight[Ndata];
-
- Ndata++;
- }
- infile.close();
-
- // We first reconstruct all the needed eigenstates:
-
- // Vector containing all the kept states:
- Vect<LiebLin_Bethe_State> Kept_States_left(block_col_length);
- Vect<LiebLin_Bethe_State> Kept_States_right(block_row_length);
-
- // Dummy state for calculations
- LiebLin_Bethe_State Scanstate (c_int, L, N);
-
- // State list containing all the types of states
- Scan_State_List<LiebLin_Bethe_State> List_of_Basic_States ('Z', Scanstate);
-
- for (int nrglabel_left = nrglabel_left_begin; nrglabel_left <= nrglabel_left_end; ++nrglabel_left) {
-
- Scanstate = List_of_Basic_States.Return_State (Extract_Base_Label(label[nrglabel_left]));
- Scanstate.Set_to_Label (label[nrglabel_left]);
-
- Scanstate.Compute_All(true);
-
- Kept_States_left[nrglabel_left - nrglabel_left_begin] = Scanstate;
-
- if (!Scanstate.conv)
- cout << "State of label " << label[nrglabel_left] << " did not converge after " << Scanstate.iter_Newton
- << " Newton step; diffsq = " << Scanstate.diffsq << endl;
- } // for nrglabel_left
-
- for (int nrglabel_right = nrglabel_right_begin; nrglabel_right <= nrglabel_right_end; ++nrglabel_right) {
-
- Scanstate = List_of_Basic_States.Return_State (Extract_Base_Label(label[nrglabel_right]));
- Scanstate.Set_to_Label (label[nrglabel_right]);
-
- Scanstate.Compute_All(true);
-
- Kept_States_right[nrglabel_right - nrglabel_right_begin] = Scanstate;
-
- if (!Scanstate.conv)
- cout << "State of label " << label[nrglabel_right] << " did not converge after " << Scanstate.iter_Newton
- << " Newton step; diffsq = " << Scanstate.diffsq << endl;
- } // for nrglabel_left
-
-
- // Now that we have all the states, we can do the full calculation of all cross form factors:
-
- for (int ll = 0; ll < block_col_length; ++ll) {
- for (int lr = 0; lr < block_row_length; ++lr) {
-
- if (Kept_States_left[ll].conv && Kept_States_right[lr].conv
- && abs(Kept_States_left[ll].iK) % iKmod == 0
- && abs(Kept_States_right[lr].iK) % iKmod == 0) {
-
- if (!symmetric_states) {
- DME_block_1[ll* block_row_length + lr] = // By convention, put the lowest energy state to the left
- Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * (Kept_States_left[ll].E <= Kept_States_right[lr].E
- ? real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
- : real(exp(ln_Density_ME (Kept_States_right[lr], Kept_States_left[ll]))));
- // We don't do anything with block 2, we don't even assume it's been allocated.
- }
-
- else if (symmetric_states) {
- // Check parity of both states:
- bool Lstate_parity_inv = Kept_States_left[ll].Check_Symmetry();
- bool Rstate_parity_inv = Kept_States_right[lr].Check_Symmetry();
-
- if (Lstate_parity_inv && Rstate_parity_inv) {
- DME_block_1[ll* block_row_length + lr] = Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
- if (block_option == 2) DME_block_2[ll* block_row_length + lr] = 0.0;
- }
- else if (!Lstate_parity_inv && !Rstate_parity_inv) {
- LiebLin_Bethe_State PRstate = Kept_States_right[lr];
- PRstate.Parity_Flip();
-
- if (block_option == 1) {
- DME_block_1[ll* block_row_length + lr] =
- (Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
- + Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate))));
- // We don't do anything with block 2, we don't even assume it's been allocated.
- }
- else if (block_option == 2) {
- DME_block_1[ll* block_row_length + lr] =
- Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
- DME_block_2[ll* block_row_length + lr] =
- Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate)));
- }
- }
-
- else if (Lstate_parity_inv) {
- LiebLin_Bethe_State PRstate = Kept_States_right[lr];
- PRstate.Parity_Flip();
-
- if (block_option == 1) {
- DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
- (Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
- + Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate))));
- // We don't do anything with block 2, we don't even assume it's been allocated.
- }
- else if (block_option == 2) {
- DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
- Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
- DME_block_2[ll* block_row_length + lr] = sqrt(0.5) *
- Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate)));
- }
- }
-
- else { // only R state is parity invariant, flip left:
- LiebLin_Bethe_State PLstate = Kept_States_left[ll];
- PLstate.Parity_Flip();
-
- if (block_option == 1) {
- DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
- (Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
- + Kweight[abs(PLstate.iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (PLstate, Kept_States_right[lr]))));
- // We don't do anything with block 2, we don't even assume it's been allocated.
- }
- else if (block_option == 2) {
- DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
- Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
- DME_block_2[ll* block_row_length + lr] = sqrt(0.5) *
- Kweight[abs(PLstate.iK - Kept_States_right[lr].iK)]
- * real(exp(ln_Density_ME (PLstate, Kept_States_right[lr])));
- }
- }
-
- } // if (symmetric_states)
- } // if conv & iKmod condition fulfilled
-
- else {
- DME_block_1[ll* block_row_length + lr] = 0.0;
- // condition, to prevent segfault if DME_block_2 not allocated.
- if (symmetric_states && block_option == 2) DME_block_2[ll* block_row_length + lr] = 0.0;
- }
- } // for lr
- } // for ll
-
- return;
- }
-
- } // namespace ABACUS
|