/***************************************************************************
 *  PSIMRCC : Copyright (C) 2007 by Francesco Evangelista and Andrew Simmonett
 *  frank@ccc.uga.edu   andysim@ccc.uga.edu
 *  A multireference coupled cluster code
 ***************************************************************************/
#include <libmoinfo/libmoinfo.h>
#include "mrcc.h"
#include "matrix.h"
#include "blas.h"
#include "debugging.h"
#include <libutil/libutil.h>

extern FILE* outfile;

namespace psi{ namespace psimrcc{

using namespace std;

void CCMRCC::synchronize_amps()
{
  blas->solve("t1[ov]{u}     = #12# t1[o][v]{u}");
  blas->solve("t1[OV]{u}     = #12# t1[O][V]{u}");
  blas->solve("t2[ov][OV]{u} = #1324# t2[oO][vV]{u}");
  blas->solve("t2[ov][ov]{u} = #1324# t2[oo][vv]{u}");
  blas->solve("t2[OV][OV]{u} = #1324# t2[OO][VV]{u}");
  blas->solve("t2[oV][Ov]{u} = #1342# t2[oO][vV]{u}");

  blas->solve("t2[o][ovv]{u} = #1234# t2[oo][vv]{u}");
  blas->solve("t2[o][OvV]{u} = #1234# t2[oO][vV]{u}");
  blas->solve("t2[O][oVv]{u} = #2143# t2[oO][vV]{u}");
  blas->solve("t2[O][OVV]{u} = #1234# t2[OO][VV]{u}");

  blas->solve("t2[v][voo]{u} = #3412# t2[oo][vv]{u}");
  blas->solve("t2[v][VoO]{u} = #3412# t2[oO][vV]{u}");
  blas->solve("t2[V][vOo]{u} = #4321# t2[oO][vV]{u}");
  blas->solve("t2[V][VOO]{u} = #3412# t2[OO][VV]{u}");

  if(triples_type>=ccsd_t){
    blas->solve("t2[ovv][o]{u} = #1423# t2[oo][vv]{u}"); // T2_iab_j
    blas->solve("t2[oVv][O]{u} = #1432# t2[oO][vV]{u}"); // T2_iBa_J
    blas->solve("t2[OvV][o]{u} = #4123# t2[oO][vV]{u}"); // T2_JaB_i
    blas->solve("t2[OVV][O]{u} = #1423# t2[OO][VV]{u}"); // T2_IAB_J

    blas->solve("t2[oov][v]{u} = #1234# t2[oo][vv]{u}"); // T2_ija_b
    blas->solve("t2[oOv][V]{u} = #1234# t2[oO][vV]{u}"); // T2_iJa_B
    blas->solve("t2[OoV][v]{u} = #2143# t2[oO][vV]{u}"); // T2_JiB_a
    blas->solve("t2[OOV][V]{u} = #1234# t2[OO][VV]{u}"); // T2_IJA_B
  }
}

void CCMRCC::update_amps_ccsd_wrapper()
{
  ptr->update_amps();
}

void CCMRCC::update_amps()
{
  update_t1_amps();
  update_t2_amps();
  if(triples_type>ccsd_t)
    update_t3_amps();
  synchronize_amps();

  // Compute the T-AMPS difference
  delta_t1_amps=0.0;
  delta_t2_amps=0.0;
  for(int n=0;n<moinfo->get_nunique();n++){
    int m = moinfo->get_ref_number("u",n);
    delta_t1_amps+=blas->get_scalar("||Delta_t1||",m);
    delta_t2_amps+=blas->get_scalar("||Delta_t2||",m);
  }
  delta_t1_amps=pow(delta_t1_amps,0.5)/((double)moinfo->get_nunique());
  delta_t2_amps=pow(delta_t2_amps,0.5)/((double)moinfo->get_nunique());
}

void CCMRCC::update_t1_amps()
{
  blas->solve("t1_delta[o][v]{u}  =   t1_eqns[o][v]{u} / d1[o][v]{u} - t1[o][v]{u}");
  blas->solve("t1_delta[O][V]{u}  =   t1_eqns[O][V]{u} / d1[O][V]{u} - t1[O][V]{u}");

  blas->solve("t1[o][v]{u} = t1_eqns[o][v]{u} / d1[o][v]{u}");
  blas->solve("t1[O][V]{u} = t1_eqns[O][V]{u} / d1[O][V]{u}");

  blas->solve("t1_norm{u}  = t1[o][v]{u} . t1[o][v]{u}");
  blas->solve("t1_norm{u} += t1[O][V]{u} . t1[O][V]{u}");

  blas->solve("||Delta_t1||{u}  = t1_delta[o][v]{u} . t1_delta[o][v]{u}");
  blas->solve("||Delta_t1||{u} += t1_delta[O][V]{u} . t1_delta[O][V]{u}");

  DEBUGGING(3,
    blas->print("t1[o][v]{u}");
    blas->print("t1[O][V]{u}");
  )
}

void CCMRCC::update_t2_amps()
{
  blas->solve("t2_delta[oo][vv]{u} = t2_eqns[oo][vv]{u} / d2[oo][vv]{u} - t2[oo][vv]{u}");
  blas->solve("t2_delta[oO][vV]{u} = t2_eqns[oO][vV]{u} / d2[oO][vV]{u} - t2[oO][vV]{u}");
  blas->solve("t2_delta[OO][VV]{u} = t2_eqns[OO][VV]{u} / d2[OO][VV]{u} - t2[OO][VV]{u}");

  blas->solve("t2[oo][vv]{u} = t2_eqns[oo][vv]{u} / d2[oo][vv]{u}");
  blas->solve("t2[oO][vV]{u} = t2_eqns[oO][vV]{u} / d2[oO][vV]{u}");
  blas->solve("t2[OO][VV]{u} = t2_eqns[OO][VV]{u} / d2[OO][VV]{u}");

  blas->solve("||Delta_t2||{u}  = t2_delta[oo][vv]{u} . t2_delta[oo][vv]{u}");
  blas->solve("||Delta_t2||{u} += t2_delta[oO][vV]{u} . t2_delta[oO][vV]{u}");
  blas->solve("||Delta_t2||{u} += t2_delta[OO][VV]{u} . t2_delta[OO][VV]{u}");

  DEBUGGING(3,
    blas->print("t2[oo][vv]{u}");
    blas->print("t2[oO][vV]{u}");
    blas->print("t2[OO][VV]{u}");
  );
}

void CCMRCC::update_t3_amps()
{
  update_t3_ijkabc_amps();
  update_t3_ijKabC_amps();
  update_t3_iJKaBC_amps();
  update_t3_IJKABC_amps();
}

void CCMRCC::update_t3_ijkabc_amps()
{
  // Loop over references
  for(int ref=0;ref<moinfo->get_nunique();ref++){
    int unique_ref  = moinfo->get_ref_number("u",ref);

    // Grab the temporary matrices
    CCMatTmp  TijkabcMatTmp = blas->get_MatTmp("t3[ooo][vvv]",unique_ref,none);
    CCMatTmp  HijkabcMatTmp = blas->get_MatTmp("t3_eqns[ooo][vvv]",unique_ref,none);

    // Grab the indexing for t3[ijk][abc]
    short**   left_tuples  = TijkabcMatTmp->get_left()->get_tuples();
    short**   right_tuples = TijkabcMatTmp->get_right()->get_tuples();

    double*** Tijkabc_matrix = TijkabcMatTmp->get_matrix();
    double*** Hijkabc_matrix = HijkabcMatTmp->get_matrix();

    for(int h =0; h < moinfo->get_nirreps();h++){
      for(int abc = 0;abc<TijkabcMatTmp->get_right_pairpi(h);abc++){
        double delta_abc = d3_vvv[ref][h][abc];
        for(int ijk = 0;ijk<TijkabcMatTmp->get_left_pairpi(h);ijk++){
          double delta_ijk = d3_ooo[ref][h][ijk];
          Tijkabc_matrix[h][ijk][abc]+=Hijkabc_matrix[h][ijk][abc]/(delta_ijk-delta_abc);
        }
      }
    }
  }
//   blas->print("t3[ooo][vvv]{u}");
//   blas->solve("ERROR{u} = 1000000.0 t3[ooo][vvv]{u} . t3[ooo][vvv]{u}");
//   blas->print("ERROR{u}");
}

void CCMRCC::update_t3_ijKabC_amps()
{
  // Loop over references
  for(int ref=0;ref<moinfo->get_nunique();ref++){
    int unique_ref  = moinfo->get_ref_number("u",ref);

    // Grab the temporary matrices
    CCMatTmp  TijKabCMatTmp = blas->get_MatTmp("t3[ooO][vvV]",unique_ref,none);
    CCMatTmp  HijKabCMatTmp = blas->get_MatTmp("t3_eqns[ooO][vvV]",unique_ref,none);

    // Grab the indexing for t3[ijk][abc]
    short**   left_tuples  = TijKabCMatTmp->get_left()->get_tuples();
    short**   right_tuples = TijKabCMatTmp->get_right()->get_tuples();

    double*** TijKabC_matrix = TijKabCMatTmp->get_matrix();
    double*** HijKabC_matrix = HijKabCMatTmp->get_matrix();

    for(int h =0; h < moinfo->get_nirreps();h++){
      for(int abc = 0;abc<TijKabCMatTmp->get_right_pairpi(h);abc++){
        double delta_abc = d3_vvV[ref][h][abc];
        for(int ijk = 0;ijk<TijKabCMatTmp->get_left_pairpi(h);ijk++){
          double delta_ijk = d3_ooO[ref][h][ijk];
          TijKabC_matrix[h][ijk][abc]+=HijKabC_matrix[h][ijk][abc]/(delta_ijk-delta_abc);
        }
      }
    }
  }
//   blas->print("t3[ooO][vvV]{u}");
//   blas->solve("ERROR{u} = 1000000.0 t3[ooO][vvV]{u} . t3[ooO][vvV]{u}");
//   blas->print("ERROR{u}");
}


void CCMRCC::update_t3_iJKaBC_amps()
{
  // Loop over references
  for(int ref=0;ref<moinfo->get_nunique();ref++){
    int unique_ref  = moinfo->get_ref_number("u",ref);

    // Grab the temporary matrices
    CCMatTmp  TiJKaBCMatTmp = blas->get_MatTmp("t3[oOO][vVV]",unique_ref,none);
    CCMatTmp  HiJKaBCMatTmp = blas->get_MatTmp("t3_eqns[oOO][vVV]",unique_ref,none);

    // Grab the indexing for t3[ijk][abc]
    short**   left_tuples  = TiJKaBCMatTmp->get_left()->get_tuples();
    short**   right_tuples = TiJKaBCMatTmp->get_right()->get_tuples();

    double*** TiJKaBC_matrix = TiJKaBCMatTmp->get_matrix();
    double*** HiJKaBC_matrix = HiJKaBCMatTmp->get_matrix();

    for(int h =0; h < moinfo->get_nirreps();h++){
      for(int abc = 0;abc<TiJKaBCMatTmp->get_right_pairpi(h);abc++){
        double delta_abc = d3_vVV[ref][h][abc];
        for(int ijk = 0;ijk<TiJKaBCMatTmp->get_left_pairpi(h);ijk++){
          double delta_ijk = d3_oOO[ref][h][ijk];
          TiJKaBC_matrix[h][ijk][abc]+=HiJKaBC_matrix[h][ijk][abc]/(delta_ijk-delta_abc);
        }
      }
    }
  }
//   blas->print("t3[oOO][vVV]{u}");
//   blas->solve("ERROR{u} = 1000000.0 t3[oOO][vVV]{u} . t3[oOO][vVV]{u}");
//   blas->print("ERROR{u}");
}

void CCMRCC::update_t3_IJKABC_amps()
{
  // Loop over references
  for(int ref=0;ref<moinfo->get_nunique();ref++){
    int unique_ref  = moinfo->get_ref_number("u",ref);

    // Grab the temporary matrices
    CCMatTmp  TIJKABCMatTmp = blas->get_MatTmp("t3[OOO][VVV]",unique_ref,none);
    CCMatTmp  HIJKABCMatTmp = blas->get_MatTmp("t3_eqns[OOO][VVV]",unique_ref,none);

    // Grab the indexing for t3[ijk][abc]
    short**   left_tuples  = TIJKABCMatTmp->get_left()->get_tuples();
    short**   right_tuples = TIJKABCMatTmp->get_right()->get_tuples();

    double*** TIJKABC_matrix = TIJKABCMatTmp->get_matrix();
    double*** HIJKABC_matrix = HIJKABCMatTmp->get_matrix();

    for(int h =0; h < moinfo->get_nirreps();h++){
      for(int abc = 0;abc<TIJKABCMatTmp->get_right_pairpi(h);abc++){
        double delta_abc = d3_VVV[ref][h][abc];
        for(int ijk = 0;ijk<TIJKABCMatTmp->get_left_pairpi(h);ijk++){
          double delta_ijk = d3_OOO[ref][h][ijk];
          TIJKABC_matrix[h][ijk][abc]+=HIJKABC_matrix[h][ijk][abc]/(delta_ijk-delta_abc);
        }
      }
    }
  }
//   blas->print("t3[OOO][VVV]{u}");
//   blas->solve("ERROR{u} = 1000000.0 t3[OOO][VVV]{u} . t3[OOO][VVV]{u}");
//   blas->print("ERROR{u}");
}


// void CCMRCC::update_t3_ijkabc_amps()
// {
//   // Loop over references
//   for(int ref=0;ref<moinfo->get_nunique();ref++){
//     int unique_ref  = moinfo->get_ref_number("u",ref);
// 
//     // Grab the temporary matrices
//     CCMatTmp  TijkabcMatTmp = blas->get_MatTmp("t3[ooo][vvv]",unique_ref,none);
//     CCMatTmp  HijkabcMatTmp = blas->get_MatTmp("t3_eqns[ooo][vvv]",unique_ref,none);
//     CCMatTmp  FockmnMatTmp  = blas->get_MatTmp("fock[oo]",unique_ref,none);
//     CCMatTmp  FockefMatTmp  = blas->get_MatTmp("fock[vv]",unique_ref,none);
// 
//     // Grab the indexing for t3[ijk][abc]
//     short**   left_tuples  = TijkabcMatTmp->get_left()->get_tuples();
//     short**   right_tuples = TijkabcMatTmp->get_right()->get_tuples();
// 
//     double*** Tijkabc_matrix = TijkabcMatTmp->get_matrix();
//     double*** Hijkabc_matrix = HijkabcMatTmp->get_matrix();
//     double*** Fockmn_matrix  = FockmnMatTmp->get_matrix();
//     double*** Fockef_matrix  = FockefMatTmp->get_matrix();
// 
//     for(int h =0; h < moinfo->get_nirreps();h++){
//       size_t left_offset  = TijkabcMatTmp->get_left()->get_first(h);
//       size_t right_offset = TijkabcMatTmp->get_right()->get_first(h);     
//       for(int abc = 0;abc<TijkabcMatTmp->get_right_pairpi(h);abc++){
//         int a = right_tuples[right_offset + abc][0];
//         int b = right_tuples[right_offset + abc][1];
//         int c = right_tuples[right_offset + abc][2];
//         double delta_abc = FockefMatTmp->get_two_address_element(a,a) +
//                            FockefMatTmp->get_two_address_element(b,b) +
//                            FockefMatTmp->get_two_address_element(c,c);
//         double delta_abc_new = d3_vvv[ref][h][abc];
//         if(delta_abc_new!=delta_abc)
//           fprintf(outfile,"\nDenominators disagree %d",abc);
//         for(int ijk = 0;ijk<TijkabcMatTmp->get_left_pairpi(h);ijk++){
//           int i = left_tuples[left_offset + ijk][0];
//           int j = left_tuples[left_offset + ijk][1];
//           int k = left_tuples[left_offset + ijk][2];
//           double delta_ijk = FockmnMatTmp->get_two_address_element(i,i) +
//                              FockmnMatTmp->get_two_address_element(j,j) +
//                              FockmnMatTmp->get_two_address_element(k,k);
//           Tijkabc_matrix[h][ijk][abc]+=Hijkabc_matrix[h][ijk][abc]/(delta_ijk-delta_abc);
//         }
//       }
//     }
//   }
// //   blas->print("t3[ooo][vvv]{u}");
// //   blas->solve("ERROR{u} = 1000000.0 t3[ooo][vvv]{u} . t3[ooo][vvv]{u}");
// //   blas->print("ERROR{u}");
// }

// void CCMRCC::update_t3_ijKabC_amps()
// {
//   // Loop over references
//   for(int ref=0;ref<moinfo->get_nunique();ref++){
//     int unique_ref  = moinfo->get_ref_number("u",ref);
// 
//     // Grab the temporary matrices
//     CCMatTmp  TijKabCMatTmp = blas->get_MatTmp("t3[ooO][vvV]",unique_ref,none);
//     CCMatTmp  HijKabCMatTmp = blas->get_MatTmp("t3_eqns[ooO][vvV]",unique_ref,none);
//     CCMatTmp  FockmnMatTmp  = blas->get_MatTmp("fock[oo]",unique_ref,none);
//     CCMatTmp  FockMNMatTmp  = blas->get_MatTmp("fock[OO]",unique_ref,none);
//     CCMatTmp  FockefMatTmp  = blas->get_MatTmp("fock[vv]",unique_ref,none);
//     CCMatTmp  FockEFMatTmp  = blas->get_MatTmp("fock[VV]",unique_ref,none);
// 
//     // Grab the indexing for t3[ijk][abc]
//     short**   left_tuples  = TijKabCMatTmp->get_left()->get_tuples();
//     short**   right_tuples = TijKabCMatTmp->get_right()->get_tuples();
// 
//     double*** TijKabC_matrix = TijKabCMatTmp->get_matrix();
//     double*** HijKabC_matrix = HijKabCMatTmp->get_matrix();
//     double*** Fockmn_matrix  = FockmnMatTmp->get_matrix();
//     double*** FockMN_matrix  = FockMNMatTmp->get_matrix();
//     double*** Fockef_matrix  = FockefMatTmp->get_matrix();
//     double*** FockEF_matrix  = FockEFMatTmp->get_matrix();
// 
//     for(int h =0; h < moinfo->get_nirreps();h++){
//       size_t left_offset  = TijKabCMatTmp->get_left()->get_first(h);
//       size_t right_offset = TijKabCMatTmp->get_right()->get_first(h);     
//       for(int abc = 0;abc<TijKabCMatTmp->get_right_pairpi(h);abc++){
//         int a = right_tuples[right_offset + abc][0];
//         int b = right_tuples[right_offset + abc][1];
//         int c = right_tuples[right_offset + abc][2];
//         double delta_abc = FockefMatTmp->get_two_address_element(a,a) +
//                            FockefMatTmp->get_two_address_element(b,b) +
//                            FockEFMatTmp->get_two_address_element(c,c);
//         for(int ijk = 0;ijk<TijKabCMatTmp->get_left_pairpi(h);ijk++){
//           int i = left_tuples[left_offset + ijk][0];
//           int j = left_tuples[left_offset + ijk][1];
//           int k = left_tuples[left_offset + ijk][2];
//           double delta_ijk = FockmnMatTmp->get_two_address_element(i,i) +
//                              FockmnMatTmp->get_two_address_element(j,j) +
//                              FockMNMatTmp->get_two_address_element(k,k);
//           TijKabC_matrix[h][ijk][abc]+=HijKabC_matrix[h][ijk][abc]/(delta_ijk-delta_abc);
//         }
//       }
//     }
//   }
// //   blas->print("t3[ooO][vvV]{u}");
// //   blas->solve("ERROR{u} = 1000000.0 t3[ooO][vvV]{u} . t3[ooO][vvV]{u}");
// //   blas->print("ERROR{u}");
// }
// 
// 
// void CCMRCC::update_t3_iJKaBC_amps()
// {
//   // Loop over references
//   for(int ref=0;ref<moinfo->get_nunique();ref++){
//     int unique_ref  = moinfo->get_ref_number("u",ref);
// 
//     // Grab the temporary matrices
//     CCMatTmp  TiJKaBCMatTmp = blas->get_MatTmp("t3[oOO][vVV]",unique_ref,none);
//     CCMatTmp  HiJKaBCMatTmp = blas->get_MatTmp("t3_eqns[oOO][vVV]",unique_ref,none);
//     CCMatTmp  FockmnMatTmp  = blas->get_MatTmp("fock[oo]",unique_ref,none);
//     CCMatTmp  FockMNMatTmp  = blas->get_MatTmp("fock[OO]",unique_ref,none);
//     CCMatTmp  FockefMatTmp  = blas->get_MatTmp("fock[vv]",unique_ref,none);
//     CCMatTmp  FockEFMatTmp  = blas->get_MatTmp("fock[VV]",unique_ref,none);
// 
//     // Grab the indexing for t3[ijk][abc]
//     short**   left_tuples  = TiJKaBCMatTmp->get_left()->get_tuples();
//     short**   right_tuples = TiJKaBCMatTmp->get_right()->get_tuples();
// 
//     double*** TiJKaBC_matrix = TiJKaBCMatTmp->get_matrix();
//     double*** HiJKaBC_matrix = HiJKaBCMatTmp->get_matrix();
//     double*** Fockmn_matrix  = FockmnMatTmp->get_matrix();
//     double*** FockMN_matrix  = FockMNMatTmp->get_matrix();
//     double*** Fockef_matrix  = FockefMatTmp->get_matrix();
//     double*** FockEF_matrix  = FockEFMatTmp->get_matrix();
// 
//     for(int h =0; h < moinfo->get_nirreps();h++){
//       size_t left_offset  = TiJKaBCMatTmp->get_left()->get_first(h);
//       size_t right_offset = TiJKaBCMatTmp->get_right()->get_first(h);     
//       for(int abc = 0;abc<TiJKaBCMatTmp->get_right_pairpi(h);abc++){
//         int a = right_tuples[right_offset + abc][0];
//         int b = right_tuples[right_offset + abc][1];
//         int c = right_tuples[right_offset + abc][2];
//         double delta_abc = FockefMatTmp->get_two_address_element(a,a) +
//                            FockEFMatTmp->get_two_address_element(b,b) +
//                            FockEFMatTmp->get_two_address_element(c,c);
//         for(int ijk = 0;ijk<TiJKaBCMatTmp->get_left_pairpi(h);ijk++){
//           int i = left_tuples[left_offset + ijk][0];
//           int j = left_tuples[left_offset + ijk][1];
//           int k = left_tuples[left_offset + ijk][2];
//           double delta_ijk = FockmnMatTmp->get_two_address_element(i,i) +
//                              FockMNMatTmp->get_two_address_element(j,j) +
//                              FockMNMatTmp->get_two_address_element(k,k);
//           TiJKaBC_matrix[h][ijk][abc]+=HiJKaBC_matrix[h][ijk][abc]/(delta_ijk-delta_abc); // TODO, check this when doing MR-CCSD
//         }
//       }
//     }
//   }
// //   blas->print("t3[oOO][vVV]{u}");
// //   blas->solve("ERROR{u} = 1000000.0 t3[oOO][vVV]{u} . t3[oOO][vVV]{u}");
// //   blas->print("ERROR{u}");
// }
// 
// void CCMRCC::update_t3_IJKABC_amps()
// {
//   // Loop over references
//   for(int ref=0;ref<moinfo->get_nunique();ref++){
//     int unique_ref  = moinfo->get_ref_number("u",ref);
// 
//     // Grab the temporary matrices
//     CCMatTmp  TIJKABCMatTmp = blas->get_MatTmp("t3[OOO][VVV]",unique_ref,none);
//     CCMatTmp  HIJKABCMatTmp = blas->get_MatTmp("t3_eqns[OOO][VVV]",unique_ref,none);
//     CCMatTmp  FockMNMatTmp  = blas->get_MatTmp("fock[OO]",unique_ref,none);
//     CCMatTmp  FockEFMatTmp  = blas->get_MatTmp("fock[VV]",unique_ref,none);
// 
//     // Grab the indexing for t3[ijk][abc]
//     short**   left_tuples  = TIJKABCMatTmp->get_left()->get_tuples();
//     short**   right_tuples = TIJKABCMatTmp->get_right()->get_tuples();
// 
//     double*** TIJKABC_matrix = TIJKABCMatTmp->get_matrix();
//     double*** HIJKABC_matrix = HIJKABCMatTmp->get_matrix();
//     double*** FockMN_matrix  = FockMNMatTmp->get_matrix();
//     double*** FockEF_matrix  = FockEFMatTmp->get_matrix();
// 
//     for(int h =0; h < moinfo->get_nirreps();h++){
//       size_t left_offset  = TIJKABCMatTmp->get_left()->get_first(h);
//       size_t right_offset = TIJKABCMatTmp->get_right()->get_first(h);     
//       for(int abc = 0;abc<TIJKABCMatTmp->get_right_pairpi(h);abc++){
//         int a = right_tuples[right_offset + abc][0];
//         int b = right_tuples[right_offset + abc][1];
//         int c = right_tuples[right_offset + abc][2];
//         double delta_abc = FockEFMatTmp->get_two_address_element(a,a) +
//                            FockEFMatTmp->get_two_address_element(b,b) +
//                            FockEFMatTmp->get_two_address_element(c,c);
//         for(int ijk = 0;ijk<TIJKABCMatTmp->get_left_pairpi(h);ijk++){
//           int i = left_tuples[left_offset + ijk][0];
//           int j = left_tuples[left_offset + ijk][1];
//           int k = left_tuples[left_offset + ijk][2];
//           double delta_ijk = FockMNMatTmp->get_two_address_element(i,i) +
//                              FockMNMatTmp->get_two_address_element(j,j) +
//                              FockMNMatTmp->get_two_address_element(k,k);
//           TIJKABC_matrix[h][ijk][abc]+=HIJKABC_matrix[h][ijk][abc]/(delta_ijk-delta_abc);
//         }
//       }
//     }
//   }
// //   blas->print("t3[OOO][VVV]{u}");
// //   blas->solve("ERROR{u} = 1000000.0 t3[OOO][VVV]{u} . t3[OOO][VVV]{u}");
// //   blas->print("ERROR{u}");
// }



}} /* End Namespaces */
