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; }
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; }
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; }
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; }