diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cff507abd..0d58038f5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -48,6 +48,7 @@ Version 2022-dev - Fixed exciton options checking (#726) - added basis gpu runner and test to suite (#725) - turned sigma choice into a factory (#731) +- use middleRows/Cols and refactor numerical integration (#732) Version 2021.2 (released XX.07.21) ================================== diff --git a/include/votca/xtp/aoshell.h b/include/votca/xtp/aoshell.h index f69fb31c0..71c2a2e3d 100644 --- a/include/votca/xtp/aoshell.h +++ b/include/votca/xtp/aoshell.h @@ -121,11 +121,17 @@ class AOShell { double getMinDecay() const { return mindecay_; } - void EvalAOspace(Eigen::VectorBlock& AOvalues, - const Eigen::Vector3d& grid_pos) const; - void EvalAOspace(Eigen::VectorBlock& AOvalues, - Eigen::Block& AODervalues, - const Eigen::Vector3d& grid_pos) const; + struct AOValues { + + AOValues(Index size) { + values = Eigen::VectorXd::Zero(size); + derivatives = Eigen::MatrixX3d::Zero(size, 3); + } + Eigen::VectorXd values; + Eigen::MatrixX3d derivatives; + }; + + AOValues EvalAOspace(const Eigen::Vector3d& grid_pos) const; // iterator over pairs (decay constant; contraction coefficient) using GaussianIterator = std::vector::const_iterator; diff --git a/include/votca/xtp/cudamatrix.h b/include/votca/xtp/cudamatrix.h index 19372e5d2..28af0598a 100644 --- a/include/votca/xtp/cudamatrix.h +++ b/include/votca/xtp/cudamatrix.h @@ -125,6 +125,21 @@ class CudaMatrix { return CudaMatrixBlock(*this, rowoffset, coloffset, rows, cols); } + CudaMatrixBlock row(Index row) const { + return CudaMatrixBlock(*this, row, 0, 1, cols()); + } + + CudaMatrixBlock col(Index col) const { + return CudaMatrixBlock(*this, 0, col, rows(), 1); + } + + CudaMatrixBlock middleRows(Index rowoffset, Index rows) const { + return CudaMatrixBlock(*this, rowoffset, 0, rows, cols()); + } + CudaMatrixBlock middleCols(Index coloffset, Index cols) const { + return CudaMatrixBlock(*this, 0, coloffset, rows(), cols); + } + static constexpr bool transposed() { return false; } template diff --git a/include/votca/xtp/gridbox.h b/include/votca/xtp/gridbox.h index 8caad52d3..7f2641231 100644 --- a/include/votca/xtp/gridbox.h +++ b/include/votca/xtp/gridbox.h @@ -36,9 +36,7 @@ class GridBox { public: void FindSignificantShells(const AOBasis& basis); - Eigen::VectorXd CalcAOValue_and_Grad(Eigen::MatrixX3d& ao_grad, - const Eigen::Vector3d& point) const; - Eigen::VectorXd CalcAOValues(const Eigen::Vector3d& pos) const; + AOShell::AOValues CalcAOValues(const Eigen::Vector3d& point) const; const std::vector& getGridPoints() const { return grid_pos; } diff --git a/src/libxtp/aoshell.cc b/src/libxtp/aoshell.cc index eff2e2c75..532f90814 100644 --- a/src/libxtp/aoshell.cc +++ b/src/libxtp/aoshell.cc @@ -88,13 +88,14 @@ void AOShell::normalizeContraction() { return; } -void AOShell::EvalAOspace(Eigen::VectorBlock& AOvalues, - Eigen::Block& gradAOvalues, - const Eigen::Vector3d& grid_pos) const { +AOShell::AOValues AOShell::EvalAOspace(const Eigen::Vector3d& grid_pos) const { // need position of shell const Eigen::Vector3d center = (grid_pos - pos_); const double distsq = center.squaredNorm(); + AOShell::AOValues AO(getNumFunc()); + Eigen::VectorXd& AOvalues = AO.values; + Eigen::MatrixX3d& gradAOvalues = AO.derivatives; // iterate over Gaussians in this shell for (const AOGaussianPrimitive& gaussian : gaussians_) { @@ -299,16 +300,7 @@ void AOShell::EvalAOspace(Eigen::VectorBlock& AOvalues, break; } } // contractions - return; -} // namespace xtp - -void AOShell::EvalAOspace(Eigen::VectorBlock& AOvalues, - const Eigen::Vector3d& grid_pos) const { - - Eigen::MatrixX3d temp = Eigen::MatrixX3d::Zero(AOvalues.size(), 3); - Eigen::Block temp2 = - temp.block(0, 0, temp.rows(), temp.cols()); - EvalAOspace(AOvalues, temp2, grid_pos); + return AO; } std::ostream& operator<<(std::ostream& out, const AOShell& shell) { diff --git a/src/libxtp/bsecoupling.cc b/src/libxtp/bsecoupling.cc index 689bbab9e..24e605547 100644 --- a/src/libxtp/bsecoupling.cc +++ b/src/libxtp/bsecoupling.cc @@ -139,14 +139,13 @@ Eigen::MatrixXd BSECoupling::SetupCTStates(Index bseA_vtotal, Index bseB_vtotal, Index noAB = occA_ * unoccB_; Index noBA = unoccA_ * occB_; - Index bseAB_total = bseAB_vtotal + bseAB_ctotal; Index bseAB_size = bseAB_vtotal * bseAB_ctotal; Eigen::MatrixXd CTstates = Eigen::MatrixXd::Zero(bseAB_size, noAB + noBA); - auto A_occ = A_AB.block(0, bseA_vtotal - occA_, bseAB_total, occA_); - auto A_unocc = A_AB.block(0, bseA_vtotal, bseAB_total, unoccA_); - auto B_occ = B_AB.block(0, bseB_vtotal - occB_, bseAB_total, occB_); - auto B_unocc = B_AB.block(0, bseB_vtotal, bseAB_total, unoccB_); + auto A_occ = A_AB.middleCols(bseA_vtotal - occA_, occA_); + auto A_unocc = A_AB.middleCols(bseA_vtotal, unoccA_); + auto B_occ = B_AB.middleCols(bseB_vtotal - occB_, occB_); + auto B_unocc = B_AB.middleCols(bseB_vtotal, unoccB_); const Eigen::MatrixXd A_occ_occ = A_occ.topRows(bseAB_vtotal); const Eigen::MatrixXd B_unocc_unocc = B_unocc.bottomRows(bseAB_ctotal); @@ -348,7 +347,6 @@ void BSECoupling::CalculateCouplings(const Orbitals& orbitalsA, Index bseAB_cmin = orbitalsAB.getBSEcmin(); Index bseAB_vmax = orbitalsAB.getBSEvmax(); Index bseAB_vmin = orbitalsAB.getBSEvmin(); - Index basisAB = orbitalsAB.getBasisSetSize(); Index bseAB_vtotal = bseAB_vmax - bseAB_vmin + 1; Index bseAB_ctotal = bseAB_cmax - bseAB_cmin + 1; Index bseAB_total = bseAB_vtotal + bseAB_ctotal; @@ -366,11 +364,11 @@ void BSECoupling::CalculateCouplings(const Orbitals& orbitalsA, << " to " << bseAB_cmax << " total: " << bseAB_total << flush; Eigen::MatrixXd MOsA = - orbitalsA.MOs().eigenvectors().block(0, bseA_vmin, basisA, bseA_total); + orbitalsA.MOs().eigenvectors().middleCols(bseA_vmin, bseA_total); Eigen::MatrixXd MOsB = - orbitalsB.MOs().eigenvectors().block(0, bseB_vmin, basisB, bseB_total); - Eigen::MatrixXd MOsAB = orbitalsAB.MOs().eigenvectors().block( - 0, bseAB_vmin, basisAB, bseAB_total); + orbitalsB.MOs().eigenvectors().middleCols(bseB_vmin, bseB_total); + Eigen::MatrixXd MOsAB = + orbitalsAB.MOs().eigenvectors().middleCols(bseAB_vmin, bseAB_total); XTP_LOG(Log::info, *pLog_) << TimeStamp() << " Calculating overlap matrix for basisset: " diff --git a/src/libxtp/davidsonsolver.cc b/src/libxtp/davidsonsolver.cc index d409b3a90..e4a340754 100644 --- a/src/libxtp/davidsonsolver.cc +++ b/src/libxtp/davidsonsolver.cc @@ -455,8 +455,8 @@ void DavidsonSolver::gramschmidt(Eigen::MatrixXd &Q, Index nstart) const { // orthogonalize vectors to each other for (Index j = nstart + 1; j < Q.cols(); ++j) { Index range = j - nstart; - Q.col(j) -= Q.block(0, nstart, Q.rows(), range) * - (Q.block(0, nstart, Q.rows(), range).transpose() * Q.col(j)); + Q.col(j) -= Q.middleCols(nstart, range) * + (Q.middleCols(nstart, range).transpose() * Q.col(j)); Q.col(j).normalize(); } // repeat again two is enough GS @@ -470,8 +470,8 @@ void DavidsonSolver::gramschmidt(Eigen::MatrixXd &Q, Index nstart) const { for (Index j = nstart + 1; j < Q.cols(); ++j) { Index range = j - nstart; - Q.col(j) -= Q.block(0, nstart, Q.rows(), range) * - (Q.block(0, nstart, Q.rows(), range).transpose() * Q.col(j)); + Q.col(j) -= Q.middleCols(nstart, range) * + (Q.middleCols(nstart, range).transpose() * Q.col(j)); if (Q.col(j).norm() <= 1E-12 * norms(range)) { // info_ = Eigen::ComputationInfo::NumericalIssue; throw std::runtime_error("Linear dependencies in Gram-Schmidt."); diff --git a/src/libxtp/dftcoupling.cc b/src/libxtp/dftcoupling.cc index 3c723e121..b46b169fb 100644 --- a/src/libxtp/dftcoupling.cc +++ b/src/libxtp/dftcoupling.cc @@ -173,10 +173,10 @@ void DFTcoupling::CalculateCouplings(const Orbitals& orbitalsA, } // constructing merged orbitals - auto MOsA = orbitalsA.MOs().eigenvectors().block(0, Range_orbA.first, basisA, - Range_orbA.second); - auto MOsB = orbitalsB.MOs().eigenvectors().block(0, Range_orbB.first, basisB, - Range_orbB.second); + auto MOsA = orbitalsA.MOs().eigenvectors().middleCols(Range_orbA.first, + Range_orbA.second); + auto MOsB = orbitalsB.MOs().eigenvectors().middleCols(Range_orbB.first, + Range_orbB.second); XTP_LOG(Log::info, *pLog_) << "Calculating overlap matrix for basisset: " << orbitalsAB.getDFTbasisName() << flush; diff --git a/src/libxtp/dftengine/dftengine.cc b/src/libxtp/dftengine/dftengine.cc index 8783615ee..715839f97 100644 --- a/src/libxtp/dftengine/dftengine.cc +++ b/src/libxtp/dftengine/dftengine.cc @@ -144,8 +144,7 @@ std::array DFTEngine::CalcERIs_EXX( if (conv_accelerator_.getUseMixing() || MOCoeff.rows() == 0) { return ERIs_.CalculateERIs_EXX_3c(Eigen::MatrixXd::Zero(0, 0), Dmat); } else { - Eigen::MatrixXd occblock = - MOCoeff.block(0, 0, MOCoeff.rows(), numofelectrons_ / 2); + Eigen::MatrixXd occblock = MOCoeff.leftCols(numofelectrons_ / 2); return ERIs_.CalculateERIs_EXX_3c(occblock, Dmat); } } else { diff --git a/src/libxtp/grids/gridbox.cc b/src/libxtp/grids/gridbox.cc index d68f8a141..16220ce11 100644 --- a/src/libxtp/grids/gridbox.cc +++ b/src/libxtp/grids/gridbox.cc @@ -41,27 +41,15 @@ void GridBox::FindSignificantShells(const AOBasis& basis) { } } -Eigen::VectorXd GridBox::CalcAOValue_and_Grad( - Eigen::MatrixX3d& ao_grad, const Eigen::Vector3d& point) const { - Eigen::VectorXd ao = Eigen::VectorXd::Zero(Matrixsize()); +AOShell::AOValues GridBox::CalcAOValues(const Eigen::Vector3d& point) const { + AOShell::AOValues result(Matrixsize()); for (Index j = 0; j < Shellsize(); ++j) { - Eigen::Block grad_block = - ao_grad.block(aoranges[j].start, 0, aoranges[j].size, 3); - Eigen::VectorBlock ao_block = - ao.segment(aoranges[j].start, aoranges[j].size); - significant_shells[j]->EvalAOspace(ao_block, grad_block, point); + const AOShell::AOValues val = significant_shells[j]->EvalAOspace(point); + result.derivatives.middleRows(aoranges[j].start, aoranges[j].size) = + val.derivatives; + result.values.segment(aoranges[j].start, aoranges[j].size) = val.values; } - return ao; -} - -Eigen::VectorXd GridBox::CalcAOValues(const Eigen::Vector3d& pos) const { - Eigen::VectorXd ao = Eigen::VectorXd::Zero(Matrixsize()); - for (Index j = 0; j < Shellsize(); ++j) { - Eigen::VectorBlock ao_block = - ao.segment(aoranges[j].start, aoranges[j].size); - significant_shells[j]->EvalAOspace(ao_block, pos); - } - return ao; + return result; } void GridBox::AddtoBigMatrix(Eigen::MatrixXd& bigmatrix, diff --git a/src/libxtp/gwbse/bse_operator.cc b/src/libxtp/gwbse/bse_operator.cc index 1b4da5828..54b3d96c3 100644 --- a/src/libxtp/gwbse/bse_operator.cc +++ b/src/libxtp/gwbse/bse_operator.cc @@ -68,10 +68,10 @@ Eigen::MatrixXd BSE_OPERATOR::matmul( // holds a reference to it Eigen::MatrixXd Temp; if (cd != 0) { - Temp = -cd * (Mmn_[c1 + cmin].block(cmin, 0, bse_ctotal_, auxsize)); + Temp = -cd * (Mmn_[c1 + cmin].middleRows(cmin, bse_ctotal_)); transform.PrepareMatrix1(Temp, threadid); } else if (cd2 != 0) { - Temp = -cd2 * (Mmn_[c1 + cmin].block(vmin, 0, bse_vtotal_, auxsize)); + Temp = -cd2 * (Mmn_[c1 + cmin].middleRows(vmin, bse_vtotal_)); transform.PrepareMatrix1(Temp, threadid); } @@ -79,12 +79,12 @@ Eigen::MatrixXd BSE_OPERATOR::matmul( transform.SetTempZero(threadid); if (cd != 0) { transform.PrepareMatrix2( - Mmn_[v1 + vmin].block(vmin, 0, bse_vtotal_, auxsize), cd2 != 0, + Mmn_[v1 + vmin].middleRows(vmin, bse_vtotal_), cd2 != 0, threadid); } if (cd2 != 0) { transform.PrepareMatrix2( - Mmn_[v1 + vmin].block(cmin, 0, bse_ctotal_, auxsize), cd2 != 0, + Mmn_[v1 + vmin].middleRows(cmin, bse_ctotal_), cd2 != 0, threadid); } if (cqp != 0) { @@ -104,13 +104,12 @@ Eigen::MatrixXd BSE_OPERATOR::matmul( #pragma omp for schedule(dynamic) for (Index v1 = 0; v1 < bse_vtotal_; v1++) { Index va = v1 + vmin; - Eigen::MatrixXd Mmn1 = - cx * Mmn_[va].block(cmin, 0, bse_ctotal_, auxsize); + Eigen::MatrixXd Mmn1 = cx * Mmn_[va].middleRows(cmin, bse_ctotal_); transform.PushMatrix1(Mmn1, threadid); for (Index v2 = v1; v2 < bse_vtotal_; v2++) { Index vb = v2 + vmin; - transform.MultiplyBlocks( - Mmn_[vb].block(cmin, 0, bse_ctotal_, auxsize), v1, v2, threadid); + transform.MultiplyBlocks(Mmn_[vb].middleRows(cmin, bse_ctotal_), v1, + v2, threadid); } } } diff --git a/src/libxtp/gwbse/gwbse.cc b/src/libxtp/gwbse/gwbse.cc index 87e1b8a52..dc952481a 100644 --- a/src/libxtp/gwbse/gwbse.cc +++ b/src/libxtp/gwbse/gwbse.cc @@ -532,9 +532,8 @@ Eigen::MatrixXd GWBSE::CalculateVXC(const AOBasis& dftbasis) { << TimeStamp() << " Set hybrid exchange factor: " << orbitals_.getScaHFX() << flush; Index qptotal = gwopt_.qpmax - gwopt_.qpmin + 1; - Index basissize = Index(orbitals_.MOs().eigenvectors().rows()); Eigen::MatrixXd mos = - orbitals_.MOs().eigenvectors().block(0, gwopt_.qpmin, basissize, qptotal); + orbitals_.MOs().eigenvectors().middleCols(gwopt_.qpmin, qptotal); Eigen::MatrixXd vxc = mos.transpose() * e_vxc_ao.matrix() * mos; XTP_LOG(Log::error, *pLog_) diff --git a/src/libxtp/gwbse/rpa.cc b/src/libxtp/gwbse/rpa.cc index c958f741a..f81bc5b53 100644 --- a/src/libxtp/gwbse/rpa.cc +++ b/src/libxtp/gwbse/rpa.cc @@ -222,19 +222,18 @@ Eigen::MatrixXd RPA::Calculate_H2p_ApB() const { const Index n_occ = lumo - rpamin_; const Index n_unocc = rpamax_ - lumo + 1; const Index rpasize = n_occ * n_unocc; - const Index auxsize = Mmn_.auxsize(); vc2index vc = vc2index(0, 0, n_unocc); Eigen::MatrixXd ApB = Eigen::MatrixXd::Zero(rpasize, rpasize); #pragma omp parallel for schedule(guided) for (Index v2 = 0; v2 < n_occ; v2++) { Index i2 = vc.I(v2, 0); const Eigen::MatrixXd Mmn_v2T = - Mmn_[v2].block(n_occ, 0, n_unocc, auxsize).transpose(); + Mmn_[v2].middleRows(n_occ, n_unocc).transpose(); for (Index v1 = v2; v1 < n_occ; v1++) { Index i1 = vc.I(v1, 0); // Multiply with factor 2 to sum over both (identical) spin states ApB.block(i1, i2, n_unocc, n_unocc) = - 2 * 2 * Mmn_[v1].block(n_occ, 0, n_unocc, auxsize) * Mmn_v2T; + 2 * 2 * Mmn_[v1].middleRows(n_occ, n_unocc) * Mmn_v2T; } } ApB.diagonal() += Calculate_H2p_AmB(); diff --git a/src/libxtp/numerical_integration/amplitude_integration.cc b/src/libxtp/numerical_integration/amplitude_integration.cc index 3b7fb9aa5..87c7ae313 100644 --- a/src/libxtp/numerical_integration/amplitude_integration.cc +++ b/src/libxtp/numerical_integration/amplitude_integration.cc @@ -42,8 +42,8 @@ std::vector > const std::vector& weights = box.getGridWeights(); // iterate over gridpoints for (Index p = 0; p < box.size(); p++) { - Eigen::VectorXd ao = box.CalcAOValues(points[p]); - result[i][p] = weights[p] * amplitude_here.dot(ao); + AOShell::AOValues ao = box.CalcAOValues(points[p]); + result[i][p] = weights[p] * amplitude_here.dot(ao.values); } } return result; diff --git a/src/libxtp/numerical_integration/density_integration.cc b/src/libxtp/numerical_integration/density_integration.cc index ee274835f..4d4168daf 100644 --- a/src/libxtp/numerical_integration/density_integration.cc +++ b/src/libxtp/numerical_integration/density_integration.cc @@ -84,8 +84,8 @@ double DensityIntegration::IntegrateDensity( const std::vector& weights = box.getGridWeights(); // iterate over gridpoints for (Index p = 0; p < box.size(); p++) { - Eigen::VectorXd ao = box.CalcAOValues(points[p]); - double rho = (ao.transpose() * DMAT_here * ao)(0, 0) * weights[p]; + AOShell::AOValues ao = box.CalcAOValues(points[p]); + double rho = ao.values.dot(DMAT_here * ao.values) * weights[p]; densities_[i][p] = rho; N += rho; } @@ -113,8 +113,8 @@ Gyrationtensor DensityIntegration::IntegrateGyrationTensor( const std::vector& weights = box.getGridWeights(); // iterate over gridpoints for (Index p = 0; p < box.size(); p++) { - Eigen::VectorXd ao = box.CalcAOValues(points[p]); - double rho = (ao.transpose() * DMAT_here * ao).value() * weights[p]; + AOShell::AOValues ao = box.CalcAOValues(points[p]); + double rho = ao.values.dot(DMAT_here * ao.values) * weights[p]; densities_[i][p] = rho; N += rho; centroid += rho * points[p]; diff --git a/src/libxtp/numerical_integration/vxc_potential.cc b/src/libxtp/numerical_integration/vxc_potential.cc index ede9045ff..227ba3430 100644 --- a/src/libxtp/numerical_integration/vxc_potential.cc +++ b/src/libxtp/numerical_integration/vxc_potential.cc @@ -182,20 +182,21 @@ Mat_p_Energy Vxc_Potential::IntegrateVXC( // iterate over gridpoints for (Index p = 0; p < box.size(); p++) { - Eigen::MatrixX3d ao_grad = Eigen::MatrixX3d::Zero(box.Matrixsize(), 3); - Eigen::VectorXd ao = box.CalcAOValue_and_Grad(ao_grad, points[p]); - const double rho = 0.5 * (ao.transpose() * DMAT_symm * ao).value(); + AOShell::AOValues ao = box.CalcAOValues(points[p]); + const double rho = 0.5 * ao.values.dot(DMAT_symm * ao.values); const double weight = weights[p]; if (rho * weight < 1.e-20) { continue; // skip the rest, if density is very small } - const Eigen::Vector3d rho_grad = ao.transpose() * DMAT_symm * ao_grad; + const Eigen::Vector3d rho_grad = + ao.values.transpose() * DMAT_symm * ao.derivatives; const double sigma = (rho_grad.transpose() * rho_grad).value(); - const Eigen::VectorXd grad = ao_grad * rho_grad; + const Eigen::VectorXd grad = ao.derivatives * rho_grad; typename Vxc_Potential::XC_entry xc = EvaluateXC(rho, sigma); EXC_box += weight * rho * xc.f_xc; - auto addXC = weight * (0.5 * xc.df_drho * ao + 2.0 * xc.df_dsigma * grad); - Vxc_here.noalias() += addXC * ao.transpose(); + auto addXC = + weight * (0.5 * xc.df_drho * ao.values + 2.0 * xc.df_dsigma * grad); + Vxc_here.noalias() += addXC * ao.values.transpose(); } box.AddtoBigMatrix(vxc.matrix(), Vxc_here); vxc.energy() += EXC_box; diff --git a/src/libxtp/openmp_cuda.cc b/src/libxtp/openmp_cuda.cc index 9d70248c4..5d7193d00 100644 --- a/src/libxtp/openmp_cuda.cc +++ b/src/libxtp/openmp_cuda.cc @@ -396,8 +396,8 @@ void OpenMP_CUDA::MultiplyRow(Index row, Index OpenmpThread) { if (isGPUthread(parentid)) { GPU_data& gpu = gpus_[threadid]; gpu.activateGPU(); - gpu.pipe().gemm(gpu.Mat(4).transpose(), gpu.Mat(1), - gpu.Mat(6).block(row, 0, 1, gpu.Mat(6).cols()), 0.0); + gpu.pipe().gemm(gpu.Mat(4).transpose(), gpu.Mat(1), gpu.Mat(6).row(row), + 0.0); } else { cpucomp(); } @@ -446,14 +446,12 @@ void OpenMP_CUDA::MultiplyBlocks(const Eigen::Block& mat, auto cpucomp = [&]() { CPU_data& cpu = cpus_[threadid]; const Eigen::MatrixXd block = cpu.ref_mat() * mat.transpose(); - cpu.reduce().block(i1 * block.rows(), 0, block.rows(), - cpu.reduce().cols()) += - block * rOP_().block(i2 * block.rows(), 0, block.rows(), rOP_().cols()); + cpu.reduce().middleRows(i1 * block.rows(), block.rows()) += + block * rOP_().middleRows(i2 * block.rows(), block.rows()); if (i1 != i2) { - cpu.reduce().block(i2 * block.rows(), 0, block.rows(), - cpu.reduce().cols()) += + cpu.reduce().middleRows(i2 * block.rows(), block.rows()) += block.transpose() * - rOP_().block(i1 * block.rows(), 0, block.rows(), rOP_().cols()); + rOP_().middleRows(i1 * block.rows(), block.rows()); } }; #ifdef USE_CUDA @@ -463,15 +461,13 @@ void OpenMP_CUDA::MultiplyBlocks(const Eigen::Block& mat, gpu.Mat(3).copy_to_gpu(mat); gpu.pipe().gemm(gpu.Mat(2), gpu.Mat(3).transpose(), gpu.Mat(4)); Index blocksize = gpu.Mat(4).rows(); - Index inputcols = gpu.Mat(1).cols(); - gpu.pipe().gemm( - gpu.Mat(4), gpu.Mat(1).block(i2 * blocksize, 0, blocksize, inputcols), - gpu.Mat(6).block(i1 * blocksize, 0, blocksize, inputcols), 1.0); + gpu.pipe().gemm(gpu.Mat(4), + gpu.Mat(1).middleRows(i2 * blocksize, blocksize), + gpu.Mat(6).middleRows(i1 * blocksize, blocksize), 1.0); if (i1 != i2) { gpu.pipe().gemm(gpu.Mat(4).transpose(), - gpu.Mat(1).block(i1 * blocksize, 0, blocksize, inputcols), - gpu.Mat(6).block(i2 * blocksize, 0, blocksize, inputcols), - 1.0); + gpu.Mat(1).middleRows(i1 * blocksize, blocksize), + gpu.Mat(6).middleRows(i2 * blocksize, blocksize), 1.0); } } else { cpucomp(); diff --git a/src/libxtp/orbitals.cc b/src/libxtp/orbitals.cc index a00d87864..daf8110ac 100644 --- a/src/libxtp/orbitals.cc +++ b/src/libxtp/orbitals.cc @@ -155,8 +155,7 @@ Eigen::MatrixXd Orbitals::CalculateQParticleAORepresentation() const { if (!hasQPdiag()) { throw std::runtime_error("Orbitals file does not contain QP coefficients"); } - return mos_.eigenvectors().block(0, qpmin_, mos_.eigenvectors().rows(), - qpmax_ - qpmin_ + 1) * + return mos_.eigenvectors().middleCols(qpmin_, qpmax_ - qpmin_ + 1) * QPdiag_.eigenvectors(); } @@ -221,10 +220,8 @@ Eigen::MatrixXd Orbitals::TransitionDensityMatrix(const QMState& state) const { coeffs += BSE_singlet_.eigenvectors2().col(state.StateIdx()); } coeffs *= std::sqrt(2.0); - auto occlevels = mos_.eigenvectors().block( - 0, bse_vmin_, mos_.eigenvectors().rows(), bse_vtotal_); - auto virtlevels = mos_.eigenvectors().block( - 0, bse_cmin_, mos_.eigenvectors().rows(), bse_ctotal_); + auto occlevels = mos_.eigenvectors().middleCols(bse_vmin_, bse_vtotal_); + auto virtlevels = mos_.eigenvectors().middleCols(bse_cmin_, bse_ctotal_); Eigen::Map mat(coeffs.data(), bse_ctotal_, bse_vtotal_); @@ -276,13 +273,13 @@ std::array Orbitals::DensityMatrixExcitedState_R( std::array dmatEX; // hole part as matrix products - Eigen::MatrixXd occlevels = mos_.eigenvectors().block( - 0, bse_vmin_, mos_.eigenvectors().rows(), bse_vtotal_); + Eigen::MatrixXd occlevels = + mos_.eigenvectors().middleCols(bse_vmin_, bse_vtotal_); dmatEX[0] = occlevels * CalcAuxMat_vv(coeffs) * occlevels.transpose(); // electron part as matrix products - Eigen::MatrixXd virtlevels = mos_.eigenvectors().block( - 0, bse_cmin_, mos_.eigenvectors().rows(), bse_ctotal_); + Eigen::MatrixXd virtlevels = + mos_.eigenvectors().middleCols(bse_cmin_, bse_ctotal_); dmatEX[1] = virtlevels * CalcAuxMat_cc(coeffs) * virtlevels.transpose(); return dmatEX; @@ -342,12 +339,12 @@ std::array Orbitals::DensityMatrixExcitedState_AR( Eigen::VectorXd coeffs = BSECoefs_AR.col(state.StateIdx()); std::array dmatAR; - Eigen::MatrixXd virtlevels = mos_.eigenvectors().block( - 0, bse_cmin_, mos_.eigenvectors().rows(), bse_ctotal_); + Eigen::MatrixXd virtlevels = + mos_.eigenvectors().middleCols(bse_cmin_, bse_ctotal_); dmatAR[0] = virtlevels * CalcAuxMat_cc(coeffs) * virtlevels.transpose(); // electron part as matrix products - Eigen::MatrixXd occlevels = mos_.eigenvectors().block( - 0, bse_vmin_, mos_.eigenvectors().rows(), bse_vtotal_); + Eigen::MatrixXd occlevels = + mos_.eigenvectors().middleCols(bse_vmin_, bse_vtotal_); dmatAR[1] = occlevels * CalcAuxMat_vv(coeffs) * occlevels.transpose(); return dmatAR; @@ -436,10 +433,8 @@ std::array Orbitals::CalcFreeTransition_Dipoles() const { // now transition dipole elements for free interlevel transitions std::array interlevel_dipoles; - Eigen::MatrixXd empty = - dft_orbitals.block(0, bse_cmin_, basis.AOBasisSize(), bse_ctotal_); - Eigen::MatrixXd occ = - dft_orbitals.block(0, bse_vmin_, basis.AOBasisSize(), bse_vtotal_); + Eigen::MatrixXd empty = dft_orbitals.middleCols(bse_cmin_, bse_ctotal_); + Eigen::MatrixXd occ = dft_orbitals.middleCols(bse_vmin_, bse_vtotal_); for (Index i = 0; i < 3; i++) { interlevel_dipoles[i] = empty.transpose() * dft_dipole.Matrix()[i] * occ; } diff --git a/src/libxtp/self_energy_evaluators/sigma_exact.cc b/src/libxtp/self_energy_evaluators/sigma_exact.cc index b92e8683a..058d11d43 100644 --- a/src/libxtp/self_energy_evaluators/sigma_exact.cc +++ b/src/libxtp/self_energy_evaluators/sigma_exact.cc @@ -27,11 +27,12 @@ namespace votca { namespace xtp { void Sigma_Exact::PrepareScreening() { - rpa_solution_ = rpa_.Diagonalize_H2p(); + RPA::rpa_eigensolution rpa_solution = rpa_.Diagonalize_H2p(); + rpa_omegas_ = rpa_solution.omega; residues_ = std::vector(qptotal_); #pragma omp parallel for schedule(dynamic) for (Index gw_level = 0; gw_level < qptotal_; gw_level++) { - residues_[gw_level] = CalcResidues(gw_level); + residues_[gw_level] = CalcResidues(gw_level, rpa_solution.XpY); } return; } @@ -43,8 +44,8 @@ double Sigma_Exact::CalcCorrelationDiagElement(Index gw_level, const Index n_occ = lumo - opt_.rpamin; const Index n_unocc = opt_.rpamax - opt_.homo; double sigma = 0.0; - for (Index s = 0; s < rpa_solution_.omega.size(); s++) { - const double eigenvalue = rpa_solution_.omega(s); + for (Index s = 0; s < rpa_omegas_.size(); s++) { + const double eigenvalue = rpa_omegas_(s); const Eigen::ArrayXd res_12 = residues_[gw_level].col(s).cwiseAbs2(); Eigen::ArrayXd temp = -rpa_.getRPAInputEnergies().array() + frequency; temp.segment(0, n_occ) += eigenvalue; @@ -62,8 +63,8 @@ double Sigma_Exact::CalcCorrelationDiagElementDerivative( const Index n_occ = lumo - opt_.rpamin; const Index n_unocc = opt_.rpamax - opt_.homo; double dsigma_domega = 0.0; - for (Index s = 0; s < rpa_solution_.omega.size(); s++) { - const double eigenvalue = rpa_solution_.omega(s); + for (Index s = 0; s < rpa_omegas_.size(); s++) { + const double eigenvalue = rpa_omegas_(s); const Eigen::ArrayXd res_12 = residues_[gw_level].col(s).cwiseAbs2(); Eigen::ArrayXd temp = -rpa_.getRPAInputEnergies().array() + frequency; temp.segment(0, n_occ) += eigenvalue; @@ -82,10 +83,10 @@ double Sigma_Exact::CalcCorrelationOffDiagElement(Index gw_level1, const Index lumo = opt_.homo + 1; const Index n_occ = lumo - opt_.rpamin; const Index n_unocc = opt_.rpamax - opt_.homo; - const Index rpasize = rpa_solution_.omega.size(); + const Index rpasize = rpa_omegas_.size(); double sigma_c = 0.0; for (Index s = 0; s < rpasize; s++) { - const double eigenvalue = rpa_solution_.omega(s); + const double eigenvalue = rpa_omegas_(s); const Eigen::VectorXd& res1 = residues_[gw_level1].col(s); const Eigen::VectorXd& res2 = residues_[gw_level2].col(s); const Eigen::VectorXd res_12 = res1.cwiseProduct(res2); @@ -104,20 +105,20 @@ double Sigma_Exact::CalcCorrelationOffDiagElement(Index gw_level1, return 2.0 * sigma_c; } -Eigen::MatrixXd Sigma_Exact::CalcResidues(Index gw_level) const { +Eigen::MatrixXd Sigma_Exact::CalcResidues(Index gw_level, + const Eigen::MatrixXd& XpY) const { const Index lumo = opt_.homo + 1; const Index n_occ = lumo - opt_.rpamin; const Index n_unocc = opt_.rpamax - opt_.homo; const Index rpasize = n_occ * n_unocc; const Index qpoffset = opt_.qpmin - opt_.rpamin; - const Index auxsize = Mmn_.auxsize(); vc2index vc = vc2index(0, 0, n_unocc); const Eigen::MatrixXd& Mmn_i = Mmn_[gw_level + qpoffset]; Eigen::MatrixXd res = Eigen::MatrixXd::Zero(rpatotal_, rpasize); for (Index v = 0; v < n_occ; v++) { // Sum over v - auto Mmn_v = Mmn_[v].block(n_occ, 0, n_unocc, auxsize); - const Eigen::MatrixXd fc = Mmn_v * Mmn_i.transpose(); // Sum over chi - auto XpY_v = rpa_solution_.XpY.block(vc.I(v, 0), 0, n_unocc, rpasize); + auto Mmn_v = Mmn_[v].middleRows(n_occ, n_unocc); + auto fc = Mmn_v * Mmn_i.transpose(); // Sum over chi + auto XpY_v = XpY.middleRows(vc.I(v, 0), n_unocc); res += fc.transpose() * XpY_v; // Sum over c } return res; diff --git a/src/libxtp/self_energy_evaluators/sigma_exact.h b/src/libxtp/self_energy_evaluators/sigma_exact.h index fbfc55f7b..35f5d07e9 100644 --- a/src/libxtp/self_energy_evaluators/sigma_exact.h +++ b/src/libxtp/self_energy_evaluators/sigma_exact.h @@ -49,10 +49,11 @@ class Sigma_Exact : public Sigma_base { double frequency2) const final; private: - RPA::rpa_eigensolution rpa_solution_; // Eigenvalues, eigenvectors from RPA + Eigen::VectorXd rpa_omegas_; // Eigenvalues from RPA std::vector residues_; // Residues - Eigen::MatrixXd CalcResidues(Index gw_level) const; + Eigen::MatrixXd CalcResidues(Index gw_level, + const Eigen::MatrixXd& XpY) const; }; } // namespace xtp } // namespace votca diff --git a/src/libxtp/statefilters/Overlap_filter.cc b/src/libxtp/statefilters/Overlap_filter.cc index cc69478be..7f8b0b404 100644 --- a/src/libxtp/statefilters/Overlap_filter.cc +++ b/src/libxtp/statefilters/Overlap_filter.cc @@ -93,10 +93,8 @@ Eigen::MatrixXd Overlap_filter::CalcExcitonAORepresentation( Index bse_ctotal = bse_cmax - bse_cmin + 1; Index basis = orb.getBasisSetSize(); Index bse_size_ao = basis * basis; - auto occlevels = orb.MOs().eigenvectors().block( - 0, bse_vmin, orb.MOs().eigenvectors().rows(), bse_vtotal); - auto virtlevels = orb.MOs().eigenvectors().block( - 0, bse_cmin, orb.MOs().eigenvectors().rows(), bse_ctotal); + auto occlevels = orb.MOs().eigenvectors().middleCols(bse_vmin, bse_vtotal); + auto virtlevels = orb.MOs().eigenvectors().middleCols(bse_cmin, bse_ctotal); if (orb.getTDAApprox()) { coeffs.resize(bse_size_ao, nostates); diff --git a/src/libxtp/threecenter.cc b/src/libxtp/threecenter.cc index 2c7505ad5..f44d74def 100644 --- a/src/libxtp/threecenter.cc +++ b/src/libxtp/threecenter.cc @@ -240,10 +240,9 @@ std::vector TCMatrix_gwbse::ComputeAO3cBlock( void TCMatrix_gwbse::Fill3cMO(const AOBasis& auxbasis, const AOBasis& dftbasis, const Eigen::MatrixXd& dft_orbitals) { - const Eigen::MatrixXd dftm = - dft_orbitals.block(0, mmin_, dft_orbitals.rows(), mtotal_); + const Eigen::MatrixXd dftm = dft_orbitals.middleCols(mmin_, mtotal_); const Eigen::MatrixXd dftn = - dft_orbitals.block(0, nmin_, dft_orbitals.rows(), ntotal_).transpose(); + dft_orbitals.middleCols(nmin_, ntotal_).transpose(); OpenMP_CUDA transform; transform.setOperators(dftn, dftm); @@ -289,7 +288,7 @@ void TCMatrix_gwbse::Fill3cMO(const AOBasis& auxbasis, const AOBasis& dftbasis, // put into correct position for (Index m_level = 0; m_level < mtotal_; m_level++) { - matrix_[m_level].block(0, auxshell2bf[aux], ntotal_, auxshell.size()) = + matrix_[m_level].middleCols(auxshell2bf[aux], auxshell.size()) = block[m_level]; } // m-th DFT orbital } // shells of GW basis set diff --git a/src/tests/test_aoshell.cc b/src/tests/test_aoshell.cc index 7bc07c452..c3207a166 100644 --- a/src/tests/test_aoshell.cc +++ b/src/tests/test_aoshell.cc @@ -91,23 +91,14 @@ BOOST_AUTO_TEST_CASE(EvalAOspace) { for (const AOShell& shell : aobasis) { Eigen::Vector3d gridpos = Eigen::Vector3d::Ones(); - Eigen::VectorXd aoval = Eigen::VectorXd::Zero(shell.getNumFunc()); - Eigen::MatrixX3d aograd = Eigen::MatrixX3d::Zero(shell.getNumFunc(), 3); - Eigen::Block grad_block = - aograd.block(0, 0, shell.getNumFunc(), 3); - Eigen::VectorBlock ao_block = - aoval.segment(0, shell.getNumFunc()); - shell.EvalAOspace(ao_block, grad_block, gridpos); + AOShell::AOValues ao = shell.EvalAOspace(gridpos); - Eigen::VectorXd aoval_2 = Eigen::VectorXd::Zero(shell.getNumFunc()); - Eigen::VectorBlock ao_block_2 = - aoval_2.segment(0, shell.getNumFunc()); - shell.EvalAOspace(ao_block_2, gridpos); + ao.derivatives.middleRows(0, 1); bool ao_check = aoval_ref.col(0) .segment(shell.getStartIndex(), shell.getNumFunc()) - .isApprox(aoval, 1e-5); + .isApprox(ao.values, 1e-5); if (!ao_check) { std::cout << shell << std::endl; std::cout << "ref" << std::endl; @@ -115,12 +106,12 @@ BOOST_AUTO_TEST_CASE(EvalAOspace) { shell.getNumFunc()) << std::endl; std::cout << "result" << std::endl; - std::cout << aoval << std::endl; + std::cout << ao.values << std::endl; } BOOST_CHECK_EQUAL(ao_check, 1); bool aograd_check = - aograd_ref.block(shell.getStartIndex(), 0, shell.getNumFunc(), 3) - .isApprox(aograd, 1e-5); + aograd_ref.middleRows(shell.getStartIndex(), shell.getNumFunc()) + .isApprox(ao.derivatives, 1e-5); if (!aograd_check) { std::cout << shell << std::endl; std::cout << "ref" << std::endl; @@ -128,18 +119,7 @@ BOOST_AUTO_TEST_CASE(EvalAOspace) { shell.getNumFunc(), 3) << std::endl; std::cout << "result" << std::endl; - std::cout << aograd << std::endl; - } - - BOOST_CHECK_EQUAL(aograd_check, 1); - - bool ao1vsao2_check = aoval_2.isApprox(aoval, 1e-5); - if (!ao1vsao2_check) { - std::cout << shell << std::endl; - std::cout << "ref" << std::endl; - std::cout << aoval << std::endl; - std::cout << "result" << std::endl; - std::cout << aoval_2 << std::endl; + std::cout << ao.derivatives << std::endl; } BOOST_CHECK_EQUAL(aograd_check, 1);