std::shared_ptr<Matrix> MultiExcitonHamiltonian<VecType>::compute_diagonal_1e(const DSubSpace& AB, const double* hAA, const double* hBB, const double diag) const {
  std::shared_ptr<const VecType> ccvecA = AB.template ci<0>();
  std::shared_ptr<const VecType> ccvecB = AB.template ci<1>();
  std::shared_ptr<const VecType> sigmavecA = form_sigma_1e(ccvecA, hAA);
  std::shared_ptr<const VecType> sigmavecB = form_sigma_1e(ccvecB, hBB);

  const int nstatesA = AB.template nstates<0>();
  const int nstatesB = AB.template nstates<1>();
  const int dimerstates = AB.dimerstates();

  auto out = std::make_shared<Matrix>(dimerstates, dimerstates);

  // first H^{AA}_{AA}
  for(int stateA = 0; stateA < nstatesA; ++stateA) {
    std::shared_ptr<const CiType> isigma = sigmavecA->data(stateA);
    for(int stateAp = 0; stateAp < stateA; ++stateAp) {
      std::shared_ptr<const CiType> icc = ccvecA->data(stateAp);
      const double dotproduct = isigma->dot_product(*icc);
      for(int stateB = 0; stateB < nstatesB; ++stateB) {
        const int stateApB = AB.dimerindex(stateAp, stateB);
        const int stateAB = AB.dimerindex(stateA, stateB);
        out->element(stateAB, stateApB) += dotproduct;
        out->element(stateApB, stateAB) += dotproduct;
      }
    }
    const double dotproduct = isigma->dot_product(*ccvecA->data(stateA));
    for(int stateB = 0; stateB < nstatesB; ++stateB) {
      const int stateAB = AB.dimerindex(stateA, stateB);
      out->element(stateAB,stateAB) += dotproduct;
    }
  }

  // H^{BB}_{BB}
  for(int stateB = 0; stateB < nstatesB; ++stateB) {
    std::shared_ptr<const CiType> isigma = sigmavecB->data(stateB);
    for(int stateBp = 0; stateBp < stateB; ++stateBp) {
      std::shared_ptr<const CiType> icc = ccvecB->data(stateBp);
      const double dotproduct = isigma->dot_product(*icc);
      for(int stateA = 0; stateA < nstatesA; ++stateA) {
        const int stateAB = AB.dimerindex(stateA, stateB);
        const int stateABp = AB.dimerindex(stateA, stateBp);
        out->element(stateAB, stateABp) += dotproduct;
        out->element(stateABp, stateAB) += dotproduct;
      }
    }
    const double dotproduct = ccvecB->data(stateB)->dot_product(*isigma);
    for(int stateA = 0; stateA < nstatesA; ++stateA) {
      const int stateAB = AB.dimerindex(stateA, stateB);
      out->element(stateAB,stateAB) += dotproduct;
    }
  }

  out->add_diag(diag);

  return out;
}
std::shared_ptr<Matrix> MultiExcitonHamiltonian<VecType>::compute_intra(const DSubSpace& AB, std::shared_ptr<const DimerJop> jop, const double diag) {
  const int nstatesA = AB.template nstates<0>();
  const int nstatesB = AB.template nstates<1>();
  const int dimerstates = AB.dimerstates();

  auto out = std::make_shared<Matrix>(dimerstates, dimerstates);

  // first H^{AA}_{AA}
  for(int stateA = 0; stateA < nstatesA; ++stateA) {
    for(int stateAp = 0; stateAp < stateA; ++stateAp) {
      const double value = AB.template sigma<0>()->element(stateAp, stateA);
      for(int stateB = 0; stateB < nstatesB; ++stateB) {
        const int stateApB = AB.dimerindex(stateAp, stateB);
        const int stateAB = AB.dimerindex(stateA, stateB);
        out->element(stateAB, stateApB) += value;
        out->element(stateApB, stateAB) += value;
      }
    }
    const double value = AB.template sigma<0>()->element(stateA, stateA);
    for(int stateB = 0; stateB < nstatesB; ++stateB) {
      const int stateAB = AB.dimerindex(stateA, stateB);
      out->element(stateAB,stateAB) += value;
    }
  }

  // H^{BB}_{BB}
  for(int stateB = 0; stateB < nstatesB; ++stateB) {
    for(int stateBp = 0; stateBp < stateB; ++stateBp) {
      const double value = AB.template sigma<1>()->element(stateBp, stateB);
      for(int stateA = 0; stateA < nstatesA; ++stateA) {
        const int stateAB = AB.dimerindex(stateA, stateB);
        const int stateABp = AB.dimerindex(stateA, stateBp);
        out->element(stateAB, stateABp) += value;
        out->element(stateABp, stateAB) += value;
      }
    }
    const double value = AB.template sigma<1>()->element(stateB, stateB);
    for(int stateA = 0; stateA < nstatesA; ++stateA) {
      const int stateAB = AB.dimerindex(stateA, stateB);
      out->element(stateAB,stateAB) += value;
    }
  }

  out->add_diag(diag);

  return out;
}
Example #3
0
int hFcn(double *obj, const Mesh *m)
{
  const int e = m->ne;

  double *v = m->v;
  double *g_obj = m->g;
  double *h_obj = m->dat;
  double *w;

  int    *t = m->e;
  int    *p = m->p;
  int    *inst  = m->inst;

  double  x[12];
  double  d[12];
  double  h[78];
  double  A[9];
  double  o, f;

  int     v1, v2, v3, v4;
  int     i;

  *obj = 0.0;
  memset(g_obj, 0, 3*sizeof(double)*m->nn);
  memset(h_obj, 0, 1*sizeof(double)*m->nz);

  o = 0.0;
  for (i = 0; i < e; ++i) {
    v1 = t[0];
    v2 = t[1];
    v3 = t[2];
    v4 = t[3];
    t += 4;

    w = v + 3*v1;
    x[0] = w[0];
    x[4] = w[1];
    x[8] = w[2];

    w = v + 3*v2;
    x[1] = w[0];
    x[5] = w[1];
    x[9] = w[2];

    w = v + 3*v3;
    x[2] = w[0];
    x[6] = w[1];
    x[10]= w[2];

    w = v + 3*v4;
    x[3] = w[0];
    x[7] = w[1];
    x[11]= w[2];

    if (h_fcn(&f, d, h, x)) return 1;

    v1 = p[v1];
    v2 = p[v2];
    v3 = p[v3];
    v4 = p[v4];

    if (v1 >= 0) {
      /* Add the gradient information */
      w = g_obj + v1;
      w[0] += d[0];
      w[1] += d[4];
      w[2] += d[8];

      /* Add diagonal block */

      A[0] = h[0];
      A[1] = h[10];
      A[2] = h[26];
      A[3] = h[42];
      A[4] = h[52];
      A[5] = h[68];

      add_diag(h_obj + *inst++, A);

      if (v2 >= 0) {

	A[0] = h[1];
	A[1] = h[11];
  	A[2] = h[27];
	A[3] = h[14];
	A[4] = h[43];
	A[5] = h[53];
	A[6] = h[30];
	A[7] = h[56];
	A[8] = h[69];

	/* Add first off diagonal block */
	if (v1 < v2) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }

      if (v3 >= 0) {

	A[0] = h[2];
	A[1] = h[12];
  	A[2] = h[28];
	A[3] = h[18];
	A[4] = h[44];
	A[5] = h[54];
	A[6] = h[34];
	A[7] = h[60];
	A[8] = h[70];

	/* Add second off diagonal block */
	if (v1 < v3) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }

      if (v4 >= 0) {

	A[0] = h[3];
	A[1] = h[13];
  	A[2] = h[29];
	A[3] = h[22];
	A[4] = h[45];
	A[5] = h[55];
	A[6] = h[38];
	A[7] = h[64];
	A[8] = h[71];

	/* Add third off diagonal block */
	if (v1 < v4) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }
    }

    if (v2 >= 0) {
      /* Add the gradient information */
      w = g_obj + v2;
      w[0] += d[1];
      w[1] += d[5];
      w[2] += d[9];

      /* Add diagonal block */

      A[0] = h[4];
      A[1] = h[15];
      A[2] = h[31];
      A[3] = h[46];
      A[4] = h[57];
      A[5] = h[72];

      add_diag(h_obj + *inst++, A);

      if (v3 >= 0) {

	A[0] = h[5];
	A[1] = h[16];
  	A[2] = h[32];
	A[3] = h[19];
	A[4] = h[47];
	A[5] = h[58];
	A[6] = h[35];
	A[7] = h[61];
	A[8] = h[73];

	/* Add first off diagonal block */
	if (v2 < v3) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }

      if (v4 >= 0) {

	A[0] = h[6];
	A[1] = h[17];
  	A[2] = h[33];
	A[3] = h[23];
	A[4] = h[48];
	A[5] = h[59];
	A[6] = h[39];
	A[7] = h[65];
	A[8] = h[74];

	/* Add second off diagonal block */
	if (v2 < v4) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }
    }

    if (v3 >= 0) {
      /* Add the gradient information */
      w = g_obj + v3;
      w[0] += d[2];
      w[1] += d[6];
      w[2] += d[10];

      /* Add diagonal block */

      A[0] = h[7];
      A[1] = h[20];
      A[2] = h[36];
      A[3] = h[49];
      A[4] = h[62];
      A[5] = h[75];

      add_diag(h_obj + *inst++, A);

      if (v4 >= 0) {

	A[0] = h[8];
	A[1] = h[21];
  	A[2] = h[37];
	A[3] = h[24];
	A[4] = h[50];
	A[5] = h[63];
	A[6] = h[40];
	A[7] = h[66];
	A[8] = h[76];

	/* Add first off diagonal block */
	if (v3 < v4) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }
    }

    if (v4 >= 0) {
      /* Add the gradient information */
      w = g_obj + v4;
      w[0] += d[3];
      w[1] += d[7];
      w[2] += d[11];

      /* Add diagonal block */

      A[0] = h[9];
      A[1] = h[25];
      A[2] = h[41];
      A[3] = h[51];
      A[4] = h[67];
      A[5] = h[77];

      add_diag(h_obj + *inst++, A);
    }

    o += f;
  }

  *obj = o;
  return 0;
}
Example #4
0
void hOnly(const Mesh *m)
{
  const int e = m->ne;

  double *v = m->v;
  double *h_obj = m->dat;
  double *w;

  int    *t = m->e;
  int    *p = m->p;
  int    *inst  = m->inst;

  double  x[12];
  double  h[78];
  double  A[9];

  int     v1, v2, v3, v4;
  int     i;

  memset(h_obj, 0, 1*sizeof(double)*m->nz);

  for (i = 0; i < e; ++i) {
    v1 = t[0];
    v2 = t[1];
    v3 = t[2];
    v4 = t[3];
    t += 4;

    w = v + 3*v1;
    x[0] = w[0];
    x[4] = w[1];
    x[8] = w[2];

    w = v + 3*v2;
    x[1] = w[0];
    x[5] = w[1];
    x[9] = w[2];

    w = v + 3*v3;
    x[2] = w[0];
    x[6] = w[1];
    x[10]= w[2];

    w = v + 3*v4;
    x[3] = w[0];
    x[7] = w[1];
    x[11]= w[2];

    h_only(h, x);

    v1 = p[v1];
    v2 = p[v2];
    v3 = p[v3];
    v4 = p[v4];

    if (v1 >= 0) {
      /* Add diagonal block */
      A[0] = h[0];
      A[1] = h[10];
      A[2] = h[26];
      A[3] = h[42];
      A[4] = h[52];
      A[5] = h[68];

      add_diag(h_obj + *inst++, A);

      if (v2 >= 0) {

	A[0] = h[1];
	A[1] = h[11];
  	A[2] = h[27];
	A[3] = h[14];
	A[4] = h[43];
	A[5] = h[53];
	A[6] = h[30];
	A[7] = h[56];
	A[8] = h[69];

	/* Add first off diagonal block */
	if (v1 < v2) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }

      if (v3 >= 0) {

	A[0] = h[2];
	A[1] = h[12];
  	A[2] = h[28];
	A[3] = h[18];
	A[4] = h[44];
	A[5] = h[54];
	A[6] = h[34];
	A[7] = h[60];
	A[8] = h[70];

	/* Add second off diagonal block */
	if (v1 < v3) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }

      if (v4 >= 0) {

	A[0] = h[3];
	A[1] = h[13];
  	A[2] = h[29];
	A[3] = h[22];
	A[4] = h[45];
	A[5] = h[55];
	A[6] = h[38];
	A[7] = h[64];
	A[8] = h[71];

	/* Add third off diagonal block */
	if (v1 < v4) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }
    }

    if (v2 >= 0) {
      /* Add diagonal block */
      A[0] = h[4];
      A[1] = h[15];
      A[2] = h[31];
      A[3] = h[46];
      A[4] = h[57];
      A[5] = h[72];

      add_diag(h_obj + *inst++, A);

      if (v3 >= 0) {

	A[0] = h[5];
	A[1] = h[16];
  	A[2] = h[32];
	A[3] = h[19];
	A[4] = h[47];
	A[5] = h[58];
	A[6] = h[35];
	A[7] = h[61];
	A[8] = h[73];

	/* Add first off diagonal block */
	if (v2 < v3) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }

      if (v4 >= 0) {

	A[0] = h[6];
	A[1] = h[17];
  	A[2] = h[33];
	A[3] = h[23];
	A[4] = h[48];
	A[5] = h[59];
	A[6] = h[39];
	A[7] = h[65];
	A[8] = h[74];

	/* Add second off diagonal block */
	if (v2 < v4) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }
    }

    if (v3 >= 0) {
      /* Add diagonal block */
      A[0] = h[7];
      A[1] = h[20];
      A[2] = h[36];
      A[3] = h[49];
      A[4] = h[62];
      A[5] = h[75];

      add_diag(h_obj + *inst++, A);

      if (v4 >= 0) {

	A[0] = h[8];
	A[1] = h[21];
  	A[2] = h[37];
	A[3] = h[24];
	A[4] = h[50];
	A[5] = h[63];
	A[6] = h[40];
	A[7] = h[66];
	A[8] = h[76];

	/* Add first off diagonal block */
	if (v3 < v4) {
	  add_block(h_obj + *inst++, A);
        }
        else {
	  add_blockT(h_obj + *inst++, A);
        }
      }
    }

    if (v4 >= 0) {
      /* Add diagonal block */
      A[0] = h[9];
      A[1] = h[25];
      A[2] = h[41];
      A[3] = h[51];
      A[4] = h[67];
      A[5] = h[77];

      add_diag(h_obj + *inst++, A);
    }
  }
  return;
}
Example #5
0
int hFcn_d(double *obj, const Mesh *m)
{
  const int e = m->ne;

  double *v = m->v;
  double *g_obj = m->g;
  double *h_obj = m->dat;
  double *w;

  int    *t = m->e;
  int    *p = m->p;

  double  x[12];
  double  d[12];
  double  h[78];
  double  A[9];
  double  o, f;

  int     v1, v2, v3, v4;
  int     i;

  *obj = 0.0;
  memset(g_obj, 0, 3*sizeof(double)*m->nn);
  memset(h_obj, 0, 6*sizeof(double)*m->nn);

  o = 0.0;
  for (i = 0; i < e; ++i) {
    v1 = t[0];
    v2 = t[1];
    v3 = t[2];
    v4 = t[3];
    t += 4;

    w = v + 3*v1;
    x[0] = w[0];
    x[4] = w[1];
    x[8] = w[2];

    w = v + 3*v2;
    x[1] = w[0];
    x[5] = w[1];
    x[9] = w[2];

    w = v + 3*v3;
    x[2] = w[0];
    x[6] = w[1];
    x[10]= w[2];

    w = v + 3*v4;
    x[3] = w[0];
    x[7] = w[1];
    x[11]= w[2];

    if (h_fcn(&f, d, h, x)) return 1;

    v1 = p[v1];
    v2 = p[v2];
    v3 = p[v3];
    v4 = p[v4];

    if (v1 >= 0) {
      /* Add the gradient information */
      w = g_obj + v1;
      w[0] += d[0];
      w[1] += d[4];
      w[2] += d[8];

      /* Add diagonal block */

      A[0] = h[0];
      A[1] = h[10];
      A[2] = h[26];
      A[3] = h[42];
      A[4] = h[52];
      A[5] = h[68];

      add_diag(h_obj + 2*v1, A);
    }

    if (v2 >= 0) {
      /* Add the gradient information */
      w = g_obj + v2;
      w[0] += d[1];
      w[1] += d[5];
      w[2] += d[9];

      /* Add diagonal block */

      A[0] = h[4];
      A[1] = h[15];
      A[2] = h[31];
      A[3] = h[46];
      A[4] = h[57];
      A[5] = h[72];

      add_diag(h_obj + 2*v2, A);
    }

    if (v3 >= 0) {
      /* Add the gradient information */
      w = g_obj + v3;
      w[0] += d[2];
      w[1] += d[6];
      w[2] += d[10];

      /* Add diagonal block */

      A[0] = h[7];
      A[1] = h[20];
      A[2] = h[36];
      A[3] = h[49];
      A[4] = h[62];
      A[5] = h[75];

      add_diag(h_obj + 2*v3, A);
    }

    if (v4 >= 0) {
      /* Add the gradient information */
      w = g_obj + v4;
      w[0] += d[3];
      w[1] += d[7];
      w[2] += d[11];

      /* Add diagonal block */

      A[0] = h[9];
      A[1] = h[25];
      A[2] = h[41];
      A[3] = h[51];
      A[4] = h[67];
      A[5] = h[77];

      add_diag(h_obj + 2*v4, A);
    }

    o += f;
  }

  *obj = o;
  return 0;
}