5 #include <unordered_map> 8 #include "DMRGKron.hpp" 9 #include <../src/mat/impls/aij/seq/aij.h> 10 #include <../src/mat/impls/aij/mpi/mpiaij.h> 14 #if defined(DMRG_KRON_DEBUG) 15 #ifndef PRINT_RANK_BEGIN 16 #define PRINT_RANK_BEGIN() \ 17 for(PetscMPIInt irank = 0; irank < mpi_size; ++irank){\ 18 if(irank==mpi_rank){std::cout << "[" << mpi_rank << "]<<" << std::endl; 21 #ifndef PRINT_RANK_END 22 #define PRINT_RANK_END() \ 23 std::cout << ">>[" << mpi_rank << "]" << std::endl;}\ 24 ierr = MPI_Barrier(mpi_comm); CHKERRQ(ierr);} 27 #ifndef PRINT_RANK_BEGIN 28 #define PRINT_RANK_BEGIN() 31 #ifndef PRINT_RANK_END 32 #define PRINT_RANK_END() 37 PETSC_EXTERN PetscErrorCode MatEnsureAssembled(
const Mat& matin);
38 PETSC_EXTERN PetscErrorCode MatSetOption_MultipleMats(
39 const std::vector<Mat>& matrices,
40 const std::vector<MatOption>& options,
41 const std::vector<PetscBool>& flgs);
42 PETSC_EXTERN PetscErrorCode MatSetOption_MultipleMatGroups(
43 const std::vector<std::vector<Mat>>& matgroups,
44 const std::vector<MatOption>& options,
45 const std::vector<PetscBool>& flgs);
46 PETSC_EXTERN PetscErrorCode MatEnsureAssembled_MultipleMatGroups(
const std::vector<std::vector<Mat>>& matgroups);
47 PETSC_EXTERN PetscErrorCode InitSingleSiteOperator(
const MPI_Comm& comm,
const PetscInt dim, Mat* mat);
49 static const PetscScalar one = 1.0;
52 PetscErrorCode MatKronEyeConstruct(
59 PetscErrorCode ierr = 0;
61 MPI_Comm mpi_comm = LeftBlock.
MPIComm();
62 PetscMPIInt mpi_rank, mpi_size;
63 ierr = MPI_Comm_rank(mpi_comm, &mpi_rank); CHKERRQ(ierr);
64 ierr = MPI_Comm_size(mpi_comm, &mpi_size); CHKERRQ(ierr);
67 if(!BlockOut.
NumSites()) SETERRQ(PETSC_COMM_SELF,1,
"BlockOut must have at least one site.");
68 Mat matin = BlockOut.
Sz(0);
70 const PetscInt rstart = matin->rmap->rstart;
71 const PetscInt lrows = matin->rmap->n;
72 const PetscInt cstart = matin->cmap->rstart;
73 const PetscInt cend = matin->cmap->rend;
77 PetscInt M,N, locrows, loccols, Istart, Cstart, lcols=cend-cstart;
78 ierr = MatGetSize(matin, &M, &N); CHKERRQ(ierr);
79 ierr = PreSplitOwnership(mpi_comm, M, locrows, Istart); CHKERRQ(ierr);
80 if(locrows!=lrows) SETERRQ4(PETSC_COMM_SELF, 1,
81 "Incorrect guess for locrows. Expected %d. Got %d. Size: %d x %d.", locrows, lrows, M, N);
82 if(Istart!=rstart) SETERRQ4(PETSC_COMM_SELF, 1,
83 "Incorrect guess for Istart. Expected %d. Got %d. Size: %d x %d.", Istart, rstart, M, N);
84 ierr = PreSplitOwnership(mpi_comm, N, loccols, Cstart); CHKERRQ(ierr);
85 if(loccols!=lcols) SETERRQ4(PETSC_COMM_SELF, 1,
86 "Incorrect guess for loccols. Expected %d. Got %d. Size: %d x %d.", loccols, lcols, M, N);
87 if(Cstart!=cstart) SETERRQ4(PETSC_COMM_SELF, 1,
88 "Incorrect guess for Cstart. Expected %d. Got %d. Size: %d x %d.", Cstart, cstart, M, N);
91 const PetscInt TotSites = BlockOut.
NumSites();
92 const std::vector<PetscInt> NumSites_LR = {LeftBlock.
NumSites(), RightBlock.
NumSites()};
95 std::unordered_map<PetscInt,PetscInt> MapRowsL, MapRowsR;
98 std::vector<PetscInt> ReqRowsL, ReqRowsR;
99 PetscInt NReqRowsL, NReqRowsR;
108 std::set<PetscInt> SetRowsL, SetRowsR;
110 for( ; KIter.Loop(); ++KIter)
112 SetRowsL.insert(KIter.GlobalIdxLeft());
113 SetRowsR.insert(KIter.GlobalIdxRight());
118 NReqRowsL = SetRowsL.size();
119 NReqRowsR = SetRowsR.size();
122 ReqRowsL.resize(NReqRowsL);
123 ReqRowsR.resize(NReqRowsR);
127 for(PetscInt row: SetRowsL){
129 MapRowsL[row] = idx++;
132 for(PetscInt row: SetRowsR){
134 MapRowsR[row] = idx++;
141 ierr = PetscCalloc1(2*TotSites, &SubMatArray); CHKERRQ(ierr);
142 const std::vector<PetscInt> SiteShifts_LR = {0, LeftBlock.
NumSites()};
143 #define p_SubMat(OPTYPE, SIDETYPE, ISITE) (SubMatArray[ (ISITE + (SiteShifts_LR [SIDETYPE]) )*2+(OPTYPE) ]) 144 #define SubMat(OPTYPE, SIDETYPE, ISITE) (*p_SubMat((OPTYPE), (SIDETYPE), (ISITE))) 147 IS isrow_L, isrow_R, iscol_L, iscol_R;
149 ierr = ISCreateGeneral(mpi_comm, NReqRowsL, ReqRowsL.data(), PETSC_USE_POINTER, &isrow_L); CHKERRQ(ierr);
150 ierr = ISCreateGeneral(mpi_comm, NReqRowsR, ReqRowsR.data(), PETSC_USE_POINTER, &isrow_R); CHKERRQ(ierr);
152 ierr = ISCreateStride(mpi_comm, LeftBlock.
NumStates(), 0, 1, &iscol_L); CHKERRQ(ierr);
153 ierr = ISCreateStride(mpi_comm, RightBlock.
NumStates(), 0, 1, &iscol_R); CHKERRQ(ierr);
156 for(PetscInt isite=0; isite<LeftBlock.
NumSites(); ++isite){
157 ierr = MatCreateSubMatrices(LeftBlock.
Sz(isite), 1, &isrow_L, &iscol_L,
158 MAT_INITIAL_MATRIX, &p_SubMat(
OpSz,
SideLeft, isite)); CHKERRQ(ierr);
159 ierr = MatCreateSubMatrices(LeftBlock.
Sp(isite), 1, &isrow_L, &iscol_L,
160 MAT_INITIAL_MATRIX, &p_SubMat(
OpSp,
SideLeft, isite)); CHKERRQ(ierr);
162 for(PetscInt isite=0; isite<RightBlock.
NumSites(); ++isite){
163 ierr = MatCreateSubMatrices(RightBlock.
Sz(isite), 1, &isrow_R, &iscol_R,
164 MAT_INITIAL_MATRIX, &p_SubMat(
OpSz,
SideRight, isite)); CHKERRQ(ierr);
165 ierr = MatCreateSubMatrices(RightBlock.
Sp(isite), 1, &isrow_R, &iscol_R,
166 MAT_INITIAL_MATRIX, &p_SubMat(
OpSp,
SideRight, isite)); CHKERRQ(ierr);
174 std::vector<PetscInt> D_NNZ_all(2*TotSites*lrows), O_NNZ_all(2*TotSites*lrows);
175 #define Dnnz(OPTYPE,SIDETYPE,ISITE,LROW) (D_NNZ_all[ ((ISITE + (SiteShifts_LR [SIDETYPE]) )*2+(OPTYPE))*lrows + LROW ]) 176 #define Onnz(OPTYPE,SIDETYPE,ISITE,LROW) (O_NNZ_all[ ((ISITE + (SiteShifts_LR [SIDETYPE]) )*2+(OPTYPE))*lrows + LROW ]) 179 ierr = MatSetOption_MultipleMatGroups({ BlockOut.
Sz(), BlockOut.
Sp() },
180 { MAT_NO_OFF_PROC_ENTRIES, MAT_NEW_NONZERO_LOCATION_ERR }, { PETSC_TRUE, PETSC_TRUE }); CHKERRQ(ierr);
182 const std::vector<std::vector<Mat>>& MatOut_ZP = {BlockOut.
Sz(), BlockOut.
Sp()};
183 PetscInt MaxElementsPerRow = 0;
185 std::vector<PetscInt> fws_O_Sp_LR, col_NStatesR_LR;
188 for( ; KIter.Loop(); ++KIter)
190 const PetscInt lrow = KIter.Steps();
191 const PetscInt Row_BlockIdx_L = KIter.BlockIdxLeft();
192 const PetscInt Row_BlockIdx_R = KIter.BlockIdxRight();
193 const PetscInt Row_NumStates_R = KIter.NumStatesRight();
194 const PetscInt Row_LocIdx_L = KIter.LocIdxLeft();
195 const PetscInt Row_LocIdx_R = KIter.LocIdxRight();
196 const PetscInt Row_L = KIter.GlobalIdxLeft();
197 const PetscInt Row_R = KIter.GlobalIdxRight();
198 const PetscInt LocRow_L = MapRowsL[Row_L];
199 const PetscInt LocRow_R = MapRowsR[Row_R];
202 PetscInt nz_L, nz_R, col_NStatesR;
203 const PetscInt *idx_L, *idx_R;
204 const PetscScalar *v_L, *v_R;
208 const PetscInt fws_O_Sz = KIter.BlockStartIdx(
OpSz);
211 if(KIter.UpdatedBlock()){
213 KronBlocks.
Offsets(Row_BlockIdx_L + 1, Row_BlockIdx_R),
214 KronBlocks.
Offsets(Row_BlockIdx_L, Row_BlockIdx_R + 1)
223 for(
Op_t OpType: BasicOpTypes)
226 const std::vector<PetscInt> shift_L = {
228 const std::vector<PetscInt> shift_R = {
231 for (
Side_t SideType: SideTypes)
238 col_NStatesR = Row_NumStates_R;
240 if(fws_O == -1)
continue;
242 else if(OpType ==
OpSp)
245 col_NStatesR = col_NStatesR_LR[SideType];
246 fws_O = fws_O_Sp_LR[SideType];
247 if(fws_O == -1)
continue;
251 SETERRQ(mpi_comm, 1,
"Invalid operator type.");
255 for(PetscInt isite=0; isite < NumSites_LR[SideType]; ++isite)
257 if(!flg[SideType])
continue;
260 const PetscInt bks_L = shift_L[SideType];
261 const PetscInt bks_R = shift_R[SideType];
262 const Mat mat = SubMat(OpType, SideType, isite);
268 idx_L = &Row_LocIdx_L;
270 ierr = (*mat->ops->getrow)(mat, LocRow_R, &nz_R, (PetscInt**)&idx_R, (PetscScalar**)&v_R); CHKERRQ(ierr);
275 ierr = (*mat->ops->getrow)(mat, LocRow_L, &nz_L, (PetscInt**)&idx_L, (PetscScalar**)&v_L); CHKERRQ(ierr);
277 idx_R = &Row_LocIdx_R;
284 PetscInt& diag = Dnnz(OpType, SideType, isite,lrow);
285 PetscInt& odiag = Onnz(OpType, SideType, isite,lrow);
286 for(PetscInt l=0; l<nz_L; ++l){
287 for(PetscInt r=0; r<nz_R; ++r)
289 idx = (idx_L[l] - bks_L) * col_NStatesR + (idx_R[r] - bks_R) + fws_O;
290 if ( cstart <= idx && idx < cend ) ++diag;
294 PetscInt nelts = nz_L * nz_R;
295 if (nelts > MaxElementsPerRow) MaxElementsPerRow = nelts;
303 for(
Side_t SideType: SideTypes){
304 for(
Op_t OpType: BasicOpTypes){
305 for(PetscInt isite = 0; isite < NumSites_LR[SideType]; ++isite){
306 ierr = MatMPIAIJSetPreallocation(
307 MatOut_ZP[OpType][isite+SiteShifts_LR[SideType]],
308 0, &Dnnz(OpType,SideType,isite,0),
309 0, &Onnz(OpType,SideType,isite,0)); CHKERRQ(ierr);
321 ierr = PetscCalloc1(MaxElementsPerRow+1, &idx); CHKERRQ(ierr);
325 std::vector<PetscInt> fws_O_Sp_LR, col_NStatesR_LR;
327 for( ; KIter.Loop(); ++KIter)
329 const PetscInt lrow = KIter.Steps();
330 const PetscInt Irow = lrow + rstart;
332 const PetscInt Row_BlockIdx_L = KIter.BlockIdxLeft();
333 const PetscInt Row_BlockIdx_R = KIter.BlockIdxRight();
334 const PetscInt Row_NumStates_R = KIter.NumStatesRight();
336 const PetscInt Row_LocIdx_L = KIter.LocIdxLeft();
337 const PetscInt Row_LocIdx_R = KIter.LocIdxRight();
339 const PetscInt LocRow_L = MapRowsL[KIter.GlobalIdxLeft()];
340 const PetscInt LocRow_R = MapRowsR[KIter.GlobalIdxRight()];
343 PetscInt nz_L, nz_R, col_NStatesR;
344 const PetscInt *idx_L, *idx_R;
345 const PetscScalar *v_L, *v_R, *v_O;
348 const PetscInt fws_O_Sz = KIter.BlockStartIdx(
OpSz);
351 if(KIter.UpdatedBlock()){
353 KronBlocks.
Offsets(Row_BlockIdx_L + 1, Row_BlockIdx_R),
354 KronBlocks.
Offsets(Row_BlockIdx_L, Row_BlockIdx_R + 1)
363 const std::vector<std::vector<Mat>>& MatOut = {BlockOut.
Sz(), BlockOut.
Sp()};
364 for(
Op_t OpType: BasicOpTypes)
367 const std::vector<PetscInt> shift_L = {
369 const std::vector<PetscInt> shift_R = {
372 for (
Side_t SideType: SideTypes)
379 col_NStatesR = Row_NumStates_R;
381 if(fws_O == -1)
continue;
383 else if(OpType ==
OpSp)
386 col_NStatesR = col_NStatesR_LR[SideType];
387 fws_O = fws_O_Sp_LR[SideType];
388 if(fws_O == -1)
continue;
392 SETERRQ(mpi_comm, 1,
"Invalid operator type.");
396 const PetscInt ishift = SiteShifts_LR[SideType];
399 for(PetscInt isite=0; isite < NumSites_LR[SideType]; ++isite)
401 if(!flg[SideType])
continue;
404 const PetscInt bks_L = shift_L[SideType];
405 const PetscInt bks_R = shift_R[SideType];
406 const Mat mat = SubMat(OpType, SideType, isite);
412 idx_L = &Row_LocIdx_L;
414 ierr = (*mat->ops->getrow)(mat, LocRow_R, &nz_R, (PetscInt**)&idx_R, (PetscScalar**)&v_R); CHKERRQ(ierr);
419 ierr = (*mat->ops->getrow)(mat, LocRow_L, &nz_L, (PetscInt**)&idx_L, (PetscScalar**)&v_L); CHKERRQ(ierr);
421 idx_R = &Row_LocIdx_R;
427 for(PetscInt l=0; l<nz_L; ++l)
428 for(PetscInt r=0; r<nz_R; ++r)
429 idx[l*nz_R+r] = (idx_L[l] - bks_L) * col_NStatesR + (idx_R[r] - bks_R) + fws_O;
432 ierr = MatSetValues(MatOut[OpType][isite+ishift], 1, &Irow, nz_L*nz_R, &idx[0], v_O, INSERT_VALUES); CHKERRQ(ierr);
440 ierr = MatEnsureAssembled_MultipleMatGroups({BlockOut.
Sz(), BlockOut.
Sp()}); CHKERRQ(ierr);
442 for(PetscInt i=0; i<2*TotSites; ++i){
443 ierr = MatDestroySubMatrices(1, &SubMatArray[i]); CHKERRQ(ierr);
445 ierr = PetscFree(idx); CHKERRQ(ierr);
446 ierr = PetscFree(SubMatArray); CHKERRQ(ierr);
447 ierr = ISDestroy(&isrow_L); CHKERRQ(ierr);
448 ierr = ISDestroy(&isrow_R); CHKERRQ(ierr);
449 ierr = ISDestroy(&iscol_L); CHKERRQ(ierr);
450 ierr = ISDestroy(&iscol_R); CHKERRQ(ierr);
462 const std::vector< Hamiltonians::Term >& Terms,
466 PetscErrorCode ierr = 0;
469 if(!LeftBlock.
Initialized()) SETERRQ(PETSC_COMM_SELF,1,
"Left input block not initialized.");
470 if(!RightBlock.
Initialized()) SETERRQ(PETSC_COMM_SELF,1,
"Right input block not initialized.");
472 MPI_Comm mpi_comm = LeftBlock.
MPIComm();
473 if(mpi_comm != RightBlock.
MPIComm()) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"Input blocks must have the same communicator.");
474 PetscMPIInt mpi_rank, mpi_size;
475 ierr = MPI_Comm_rank(mpi_comm, &mpi_rank); CHKERRQ(ierr);
476 ierr = MPI_Comm_size(mpi_comm, &mpi_size); CHKERRQ(ierr);
479 #if defined(DMRG_KRON_DEBUG) 481 std::cout <<
"***** Kron_Explicit *****" << std::endl;
482 std::cout <<
"LeftBlock qn_list: ";
484 std::cout << std::endl;
486 std::cout <<
"LeftBlock qn_size: ";
488 std::cout << std::endl;
490 std::cout <<
"LeftBlock qn_offset: ";
492 std::cout << std::endl;
494 std::cout << std::endl;
496 std::cout <<
"RightBlock qn_list: ";
498 std::cout << std::endl;
500 std::cout <<
"RightBlock qn_size: ";
502 std::cout << std::endl;
504 std::cout <<
"RightBlock qn_offset: ";
506 std::cout << std::endl;
519 KronBlocks_t KronBlocks(LeftBlock, RightBlock, {}, NULL, -1);
521 #if defined(DMRG_KRON_DEBUG) 525 std::cout <<
"KronBlocks: \n";
529 << std::get<0>(kb) <<
", " 530 << std::get<1>(kb) <<
", " 531 << std::get<2>(kb) <<
", " 532 << std::get<3>(kb) <<
", " 533 << KronBlocks.
Offsets()[i++] <<
" )\n";
535 std::cout <<
"*************************" << std::endl;
541 PetscInt nsites_left = LeftBlock.
NumSites();
542 PetscInt nsites_right = RightBlock.
NumSites();
543 PetscInt nsites_out = nsites_left + nsites_right;
548 PetscInt nsectors_out = nsectors_left * nsectors_right;
549 if(PetscUnlikely(KronBlocks.
size() != nsectors_out ))
550 SETERRQ2(mpi_comm, 1,
"Mismatch in number of sectors. Expected %lu. Got %d.", KronBlocks.
size(), nsectors_out);
555 PetscInt nstates_out = nstates_left * nstates_right;
556 PetscInt KronBlocks_nstates = KronBlocks.
NumStates();
557 if(PetscUnlikely(KronBlocks_nstates != nstates_out))
558 SETERRQ2(mpi_comm, 1,
"Mismatch in number of states. Expected %lu. Got %d.", KronBlocks_nstates, nstates_out);
561 std::vector<PetscReal> QN_List;
562 std::vector<PetscInt> QN_Size;
563 PetscReal QN_last = 0;
564 for (
auto tup: KronBlocks.
data()){
565 const PetscReal& qn = std::get<0>(tup);
566 const PetscInt& size = std::get<3>(tup);
567 if(qn < QN_last || QN_List.size()==0){
568 QN_List.push_back(qn);
569 QN_Size.push_back(size);
571 QN_Size.back() += size;
576 PetscInt QN_Size_total = 0;
577 for(PetscInt size: QN_Size) QN_Size_total += size;
578 if(PetscUnlikely(nstates_out != QN_Size_total))
579 SETERRQ2(mpi_comm, 1,
"Mismatch in number of states. Expected %d. Got %d.", nstates_out, QN_Size_total);
581 #if defined(DMRG_KRON_DEBUG) 583 std::cout <<
"QN_List: ";
for(
auto q: QN_List) std::cout << q <<
" "; std::cout << std::endl;
584 std::cout <<
"Total Sites: " << nsites_out << std::endl;
585 std::cout <<
"Total Sectors: " << nsectors_out << std::endl;
586 std::cout <<
"Total States: " << nstates_out << std::endl;
591 ierr = BlockOut.
Initialize(mpi_comm, nsites_out, QN_List, QN_Size); CHKERRQ(ierr);
593 #if defined(DMRG_KRON_DEBUG) 595 std::cout <<
"Mag: QN_List: ";
for(
auto q: BlockOut.
Magnetization.
List()) std::cout << q <<
" "; std::cout << std::endl;
596 std::cout <<
"Mag: QN_Size: ";
for(
auto q: BlockOut.
Magnetization.
Sizes()) std::cout << q <<
" "; std::cout << std::endl;
603 ierr = MatKronEyeConstruct(LeftBlock, RightBlock, KronBlocks, BlockOut); CHKERRQ(ierr);
608 if(term.Iop >= nsites_out || term.Jop >= nsites_out)
609 SETERRQ3(mpi_comm,1,
"Term indices must be less than %d. Got %d and %d.",nsites_out,term.Iop,term.Jop);
619 const std::vector< Mat >& Matrices,
623 PetscErrorCode ierr = 0;
624 for(
const Mat& mat: Matrices){
637 const Op_t& OpType_L,
639 const Op_t& OpType_R,
644 FUNCTION_TIMINGS_BEGIN()
653 ierr = PetscNew(&shellctx); CHKERRQ(ierr);
668 ierr = PreSplitOwnership(mpi_comm, ctx.
Nrows, ctx.
lrows, ctx.
rstart); CHKERRQ(ierr);
674 ierr = KronGetSubmatrices(Mat_L, OpType_L, Mat_R, OpType_R, ctx); CHKERRQ(ierr);
675 ierr = KronSumSetUpShellTerms(shellctx); CHKERRQ(ierr);
678 ierr = VecCreateMPI(mpi_comm, ctx.
lrows, PETSC_DETERMINE, &x_mpi); CHKERRQ(ierr);
679 ierr = VecScatterCreateToAll(x_mpi, &shellctx->vsctx, &shellctx->x_seq); CHKERRQ(ierr);
680 ierr = VecDestroy(&x_mpi); CHKERRQ(ierr);
683 ierr = MatCreateShell(mpi_comm, ctx.
lrows, ctx.
lcols, ctx.
Nrows, ctx.
Ncols, (
void*)shellctx, &MatOut); CHKERRQ(ierr);
684 ierr = MatShellSetOperation(MatOut, MATOP_MULT, (
void(*)())MatMult_KronSumShell); CHKERRQ(ierr);
688 SETERRQ(mpi_comm,1,
"Not implemented for non-shell matrices"); CHKERRQ(ierr);
691 FUNCTION_TIMINGS_END()
696 PetscErrorCode KronBlocks_t::KronGetSubmatrices(
698 const Op_t& OpType_L,
700 const Op_t& OpType_R,
705 FUNCTION_TIMINGS_BEGIN()
710 std::set<PetscInt> SetRowsL, SetRowsR;
711 for( ; KIter.
Loop(); ++KIter)
713 SetRowsL.insert(KIter.GlobalIdxLeft());
714 SetRowsR.insert(KIter.GlobalIdxRight());
717 ctx.NReqRowsR = SetRowsR.size();
719 ctx.ReqRowsR.resize(ctx.NReqRowsR);
721 for(PetscInt row: SetRowsL){
726 for(PetscInt row: SetRowsR){
727 ctx.ReqRowsR[idx] = row;
728 ctx.MapRowsR[row] = idx++;
732 IS isrow_L, isrow_R, iscol_L, iscol_R;
734 ierr = ISCreateGeneral(mpi_comm, ctx.
NReqRowsL, ctx.
ReqRowsL.data(), PETSC_USE_POINTER, &isrow_L); CHKERRQ(ierr);
735 ierr = ISCreateGeneral(mpi_comm, ctx.NReqRowsR, ctx.ReqRowsR.data(), PETSC_USE_POINTER, &isrow_R); CHKERRQ(ierr);
737 ierr = ISCreateStride(mpi_comm, LeftBlock.
NumStates(), 0, 1, &iscol_L); CHKERRQ(ierr);
738 ierr = ISCreateStride(mpi_comm, RightBlock.
NumStates(), 0, 1, &iscol_R); CHKERRQ(ierr);
741 Mat *submat_L, *submat_R;
742 ierr = MatCreateSubMatrices(Mat_L, 1, &isrow_L, &iscol_L, MAT_INITIAL_MATRIX, &submat_L); CHKERRQ(ierr);
743 ierr = MatCreateSubMatrices(Mat_R, 1, &isrow_R, &iscol_R, MAT_INITIAL_MATRIX, &submat_R); CHKERRQ(ierr);
744 ctx.
Terms.push_back({1.0, OpType_L, submat_L[0], OpType_R, submat_R[0]});
749 ierr = ISDestroy(&isrow_L); CHKERRQ(ierr);
750 ierr = ISDestroy(&isrow_R); CHKERRQ(ierr);
751 ierr = ISDestroy(&iscol_L); CHKERRQ(ierr);
752 ierr = ISDestroy(&iscol_R); CHKERRQ(ierr);
754 FUNCTION_TIMINGS_END()
760 const std::vector< Hamiltonians::Term >& Terms,
764 PetscErrorCode ierr = 0;
767 PetscInt nsites_left = LeftBlock.
NumSites();
768 PetscInt nsites_right = RightBlock.
NumSites();
769 PetscInt nsites_out = nsites_left + nsites_right;
772 PetscInt Max_Isite = 0;
774 Max_Isite = ( term.Isite > Max_Isite ) ? term.Isite : Max_Isite;
775 Max_Isite = ( term.Jsite > Max_Isite ) ? term.Jsite : Max_Isite;
777 if(Max_Isite >= nsites_out) SETERRQ2(mpi_comm, 1,
"Maximum site index from Terms (%d) has to be " 778 "less than the total number of sites in the blocks (%d).", Max_Isite, nsites_out);
789 std::vector< Hamiltonians::Term > TermsLR;
791 if ((0 <= term.Isite && term.Isite < nsites_left) && (nsites_left <= term.Jsite && term.Jsite < nsites_out)){
792 if(term.a == PetscScalar(0.0))
continue;
793 TermsLR.push_back(term);
795 else if ((0 <= term.Isite && term.Isite < nsites_left) && (0 <= term.Jsite && term.Jsite < nsites_left)){}
796 else if ((nsites_left <= term.Isite && term.Isite < nsites_out) && (nsites_left <= term.Jsite && term.Jsite < nsites_out)){}
798 SETERRQ4(mpi_comm, 1,
"Invalid term: Isite=%d Jsite=%d for nsites_left=%d and nsites_right=%d.",
799 term.Isite, term.Jsite, nsites_left, nsites_right);
806 term.Jsite = nsites_out - 1 - term.Jsite;
811 PetscBool CreateSmL = PETSC_FALSE, CreateSmR = PETSC_FALSE;
813 if(term.Iop ==
OpSm){
814 CreateSmL = PETSC_TRUE;
815 ierr = LeftBlock.
CreateSm(); CHKERRQ(ierr);
820 if(term.Jop ==
OpSm){
821 CreateSmR = PETSC_TRUE;
822 ierr = RightBlock.
CreateSm(); CHKERRQ(ierr);
828 ierr = KronSumConstructShell(TermsLR, MatOut); CHKERRQ(ierr);
830 ierr = KronSumConstructExplicit(TermsLR, MatOut); CHKERRQ(ierr);
835 ierr = LeftBlock.
DestroySm(); CHKERRQ(ierr);
838 ierr = RightBlock.
DestroySm(); CHKERRQ(ierr);
844 PetscErrorCode KronBlocks_t::KronSumConstructExplicit(
845 const std::vector< Hamiltonians::Term >& TermsLR,
849 PetscErrorCode ierr = 0;
854 ierr = PreSplitOwnership(mpi_comm, ctx.
Nrows, ctx.
lrows, ctx.
rstart); CHKERRQ(ierr);
860 ierr = KronSumGetSubmatrices(LeftBlock.
H, RightBlock.
H, TermsLR, ctx); CHKERRQ(ierr);
861 ierr = KronSumCalcPreallocation(ctx); CHKERRQ(ierr);
864 ierr = KronSumRedistribute(ctx,flg); CHKERRQ(ierr);
866 ierr = KronSumGetSubmatrices(LeftBlock.
H, RightBlock.
H, TermsLR, ctx); CHKERRQ(ierr);
867 ierr = KronSumCalcPreallocation(ctx); CHKERRQ(ierr);
870 ierr = SavePreallocData(ctx); CHKERRQ(ierr);
873 ierr = KronSumPreallocate(ctx, MatOut); CHKERRQ(ierr);
874 ierr = KronSumFillMatrix(ctx, MatOut); CHKERRQ(ierr);
878 ierr = MatDestroySubMatrices(1,&mat); CHKERRQ(ierr);
884 #define GetBlockMat(BLOCK,OP,ISITE)\ 885 ((OP)==OpSp ? (BLOCK).Sp(ISITE) : ((OP)==OpSm ? (BLOCK).Sm(ISITE) : ((OP)==OpSz ? (BLOCK).Sz(ISITE) : NULL))) 887 #define GetBlockMatFromTuple(BLOCK,TUPLE)\ 888 GetBlockMat((BLOCK), std::get<0>(TUPLE), std::get<1>(TUPLE)) 891 PetscErrorCode KronBlocks_t::KronSumGetSubmatrices(
892 const Mat& OpProdSumLL,
893 const Mat& OpProdSumRR,
894 const std::vector< Hamiltonians::Term >& TermsLR,
898 PetscErrorCode ierr = 0;
899 FUNCTION_TIMINGS_BEGIN()
904 std::set<PetscInt> SetRowsL, SetRowsR;
905 for( ; KIter.
Loop(); ++KIter)
907 SetRowsL.insert(KIter.GlobalIdxLeft());
908 SetRowsR.insert(KIter.GlobalIdxRight());
911 ctx.NReqRowsR = SetRowsR.size();
913 ctx.ReqRowsR.resize(ctx.NReqRowsR);
915 for(PetscInt row: SetRowsL){
920 for(PetscInt row: SetRowsR){
921 ctx.ReqRowsR[idx] = row;
922 ctx.MapRowsR[row] = idx++;
926 IS isrow_L, isrow_R, iscol_L, iscol_R;
928 ierr = ISCreateGeneral(mpi_comm, ctx.
NReqRowsL, ctx.
ReqRowsL.data(), PETSC_USE_POINTER, &isrow_L); CHKERRQ(ierr);
929 ierr = ISCreateGeneral(mpi_comm, ctx.NReqRowsR, ctx.ReqRowsR.data(), PETSC_USE_POINTER, &isrow_R); CHKERRQ(ierr);
931 ierr = ISCreateStride(mpi_comm, LeftBlock.
NumStates(), 0, 1, &iscol_L); CHKERRQ(ierr);
932 ierr = ISCreateStride(mpi_comm, RightBlock.
NumStates(), 0, 1, &iscol_R); CHKERRQ(ierr);
936 const PetscInt NumTerms = 2 + TermsLR.size();
937 ctx.
Terms.reserve(NumTerms);
941 ierr = MatCreateSubMatrices(OpProdSumLL, 1, &isrow_L, &iscol_L, MAT_INITIAL_MATRIX, &A); CHKERRQ(ierr);
948 ierr = MatCreateSubMatrices(OpProdSumRR, 1, &isrow_R, &iscol_R, MAT_INITIAL_MATRIX, &B); CHKERRQ(ierr);
955 std::map< std::tuple< PetscInt, PetscInt >, Mat> OpLeft;
956 std::map< std::tuple< PetscInt, PetscInt >, Mat> OpRight;
958 OpLeft[ std::make_tuple(term.Iop, term.Isite) ] =
nullptr;
959 OpRight[ std::make_tuple(term.Jop, term.Jsite) ] =
nullptr;
962 for (
auto&
Op: OpLeft){
963 const Mat mat = GetBlockMatFromTuple(LeftBlock,
Op.first);
965 ierr = MatCreateSubMatrices(mat, 1, &isrow_L, &iscol_L, MAT_INITIAL_MATRIX, &submat); CHKERRQ(ierr);
966 Op.second = submat[0];
969 for (
auto&
Op: OpRight){
970 const Mat mat = GetBlockMatFromTuple(RightBlock,
Op.first);
972 ierr = MatCreateSubMatrices(mat, 1, &isrow_R, &iscol_R, MAT_INITIAL_MATRIX, &submat); CHKERRQ(ierr);
973 Op.second = submat[0];
978 const Mat A = OpLeft.at(std::make_tuple(term.Iop, term.Isite));
979 const Mat B = OpRight.at(std::make_tuple(term.Jop, term.Jsite));
980 ctx.
Terms.push_back({term.a, term.Iop, A, term.Jop, B});
982 ierr = ISDestroy(&isrow_L); CHKERRQ(ierr);
983 ierr = ISDestroy(&isrow_R); CHKERRQ(ierr);
984 ierr = ISDestroy(&iscol_L); CHKERRQ(ierr);
985 ierr = ISDestroy(&iscol_R); CHKERRQ(ierr);
987 FUNCTION_TIMINGS_END()
992 #undef GetBlockMatFromTuple 994 PetscErrorCode KronBlocks_t::KronSumCalcPreallocation(
998 PetscErrorCode ierr = 0;
999 FUNCTION_TIMINGS_BEGIN()
1002 PetscInt Nvals = ctx.
lrows > 0 ? ctx.
Ncols : 1;
1003 PetscScalar *val_arr;
1005 ierr = PetscCalloc1(Nvals, &val_arr); CHKERRQ(ierr);
1018 std::map< Op_t, PetscInt > fws_LOP = {};
1019 std::map< Op_t, PetscInt > Row_NumStates_ROP = {};
1023 for( ; KIter.
Loop(); ++KIter)
1025 const PetscInt lrow = KIter.
Steps();
1028 const PetscInt Row_L = KIter.GlobalIdxLeft();
1029 const PetscInt Row_R = KIter.GlobalIdxRight();
1030 const PetscInt LocRow_L = ctx.
MapRowsL[Row_L];
1031 const PetscInt LocRow_R = ctx.MapRowsR[Row_R];
1034 PetscInt nz_L, nz_R, bks_L, bks_R, col_NStatesR, fws_O, MinIdx, MaxIdx;
1035 const PetscInt *idx_L, *idx_R;
1036 const PetscScalar *v_L, *v_R;
1044 {
OpSp ,
Offsets(Row_BlockIdx_L + 1, Row_BlockIdx_R - 1),},
1045 {
OpSm ,
Offsets(Row_BlockIdx_L - 1, Row_BlockIdx_R + 1)}
1048 Row_NumStates_ROP = {
1057 ierr = PetscMemzero(val_arr, Nvals*
sizeof(val_arr[0])); CHKERRQ(ierr);
1060 if(term.a == PetscScalar(0.0))
continue;
1062 if(term.OpTypeA !=
OpEye){
1063 ierr = (*term.A->ops->getrow)(term.A, LocRow_L, &nz_L, (PetscInt**)&idx_L, (PetscScalar**)&v_L); CHKERRQ(ierr);
1072 if(term.OpTypeB !=
OpEye){
1073 ierr = (*term.B->ops->getrow)(term.B, LocRow_R, &nz_R, (PetscInt**)&idx_R, (PetscScalar**)&v_R); CHKERRQ(ierr);
1083 if(nz_L*nz_R == 0)
continue;
1085 fws_O = fws_LOP.at(term.OpTypeA);
1086 col_NStatesR = Row_NumStates_ROP.at(term.OpTypeB);
1087 if(col_NStatesR==-1) SETERRQ(PETSC_COMM_SELF,1,
"Accessed incorrect value.");
1089 for(PetscInt l=0; l<nz_L; ++l)
1091 for(PetscInt r=0; r<nz_R; ++r)
1093 val_arr[( (idx_L[l] - bks_L) * col_NStatesR + (idx_R[r] - bks_R) + fws_O )] += term.a * v_L[l] * v_R[r];
1099 MinIdx = ( (idx_L[0] - bks_L) * col_NStatesR + (idx_R[0] - bks_R) + fws_O );
1100 MaxIdx = ( (idx_L[nz_L-1] - bks_L) * col_NStatesR + (idx_R[nz_R-1] - bks_R) + fws_O );
1104 ctx.Nelts += nz_L*nz_R;
1108 PetscInt dnnz = 0, onnz=0, i;
1109 for (i=0; i<ctx.
cstart; i++) onnz += !(PetscAbsScalar(val_arr[i]) < ks_tol);
1110 for (i=ctx.
cstart; i<ctx.
cend; i++) dnnz += !(PetscAbsScalar(val_arr[i]) < ks_tol);
1111 for (i=ctx.
cend; i<ctx.
Ncols; i++) onnz += !(PetscAbsScalar(val_arr[i]) < ks_tol);
1112 ctx.
Dnnz[lrow] = dnnz + (PetscAbsScalar(val_arr[lrow+ctx.
rstart]) < ks_tol ? 1 : 0);
1113 ctx.
Onnz[lrow] = onnz;
1114 ctx.Nnz += ctx.
Dnnz[lrow] + ctx.
Onnz[lrow];
1117 ierr = PetscFree(val_arr); CHKERRQ(ierr);
1119 FUNCTION_TIMINGS_END()
1123 PetscErrorCode KronBlocks_t::KronSumRedistribute(
1128 PetscErrorCode ierr = 0;
1129 FUNCTION_TIMINGS_BEGIN()
1132 PetscInt *lrows_arr, *rstart_arr;
1133 const PetscInt arr_size = mpi_rank ? 0 : mpi_size;
1134 ierr = PetscCalloc2(arr_size, &lrows_arr, arr_size, &rstart_arr); CHKERRQ(ierr);
1135 ierr = MPI_Gather(&ctx.
lrows, 1, MPIU_INT, lrows_arr, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1136 ierr = MPI_Gather(&ctx.
rstart, 1, MPIU_INT, rstart_arr, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1138 PetscMPIInt *lrows_arr_mpi, *rstart_arr_mpi;
1139 #if defined(PETSC_USE_64BIT_INDICES) 1142 ierr = PetscCalloc2(arr_size, &lrows_arr_mpi, arr_size, &rstart_arr_mpi); CHKERRQ(ierr);
1143 for(PetscInt p=0; p<arr_size; ++p){
1144 ierr = PetscMPIIntCast(lrows_arr[p],&lrows_arr_mpi[p]); CHKERRQ(ierr);
1146 for(PetscInt p=0; p<arr_size; ++p){
1147 ierr = PetscMPIIntCast(rstart_arr[p],&rstart_arr_mpi[p]); CHKERRQ(ierr);
1152 lrows_arr_mpi = lrows_arr;
1153 rstart_arr_mpi = rstart_arr;
1158 PetscInt *Tnnz_arr, *Onnz_arr;
1159 const PetscInt tot_size = mpi_rank ? 0 : ctx.
Nrows;
1160 ierr = PetscCalloc2(tot_size, &Tnnz_arr, tot_size, &Onnz_arr); CHKERRQ(ierr);
1161 ierr = MPI_Gatherv(ctx.
Dnnz, ctx.
lrows, MPIU_INT, Tnnz_arr, lrows_arr_mpi, rstart_arr_mpi, MPIU_INT, 0, mpi_comm); CHKERRQ(ierr);
1162 ierr = MPI_Gatherv(ctx.
Onnz, ctx.
lrows, MPIU_INT, Onnz_arr, lrows_arr_mpi, rstart_arr_mpi, MPIU_INT, 0, mpi_comm); CHKERRQ(ierr);
1163 for(PetscInt irow = 0; irow < tot_size; ++irow) Tnnz_arr[irow] += Onnz_arr[irow];
1166 #if defined(DEBUG_REDIST) 1168 printf(
"-------\n");
1169 for(PetscInt p=0; p<mpi_size; ++p){
1170 PetscInt tot_nnz = 0;
1171 for(PetscInt irow=rstart_arr[p]; irow<rstart_arr[p]+lrows_arr[p]; ++irow) tot_nnz += Tnnz_arr[irow];
1172 printf(
"[%d] lrows: %3d rstart: %3d nnz: %d\n", p, lrows_arr[p], rstart_arr[p], tot_nnz);
1174 printf(
"excess: %d\n", ctx.
Nrows % mpi_size);
1175 printf(
"-------\n");
1179 PetscInt tot_nnz = 0;
1180 for(PetscInt irow = 0; irow < tot_size; ++irow) tot_nnz += Tnnz_arr[irow];
1181 const PetscInt avg_nnz_proc = tot_nnz / mpi_size;
1183 ierr = PetscMemzero(lrows_arr,
sizeof(PetscInt) * arr_size); CHKERRQ(ierr);
1184 ierr = PetscMemzero(rstart_arr,
sizeof(PetscInt) * arr_size); CHKERRQ(ierr);
1190 #if defined(DEBUG_REDIST) 1191 printf(
"tot_nnz: %d\n", tot_nnz);
1192 printf(
"avg_nnz_proc: %d\n", avg_nnz_proc);
1193 printf(
"-------\n");
1196 std::vector< PetscInt > nnz_proc(mpi_size);
1197 for(PetscInt irow=0, iproc=0; irow<ctx.
Nrows; ++irow){
1198 if(iproc>=mpi_size)
break;
1200 nnz_proc[iproc] += Tnnz_arr[irow];
1203 #if defined(DEBUG_REDIST) && 0 1204 printf(
"irow: %-5d iproc: %-5d nrows_proc: %-5d Tnnz: %-5d nnz_proc: %-5d\n", irow, iproc, lrows_arr[iproc], Tnnz_arr[irow], nnz_proc[iproc]);
1207 if( nnz_proc[iproc] >= avg_nnz_proc ){
1209 #if defined(DEBUG_REDIST) && 0 1210 printf(
"\ntriggered\n");
1211 printf(
"irow: %-5d iproc: %-5d nrows_proc: %-5d Tnnz: %-5d nnz_proc: %-5d\n", irow, iproc, lrows_arr[iproc], Tnnz_arr[irow], nnz_proc[iproc]);
1212 printf(
"lrows_arr[%d] = %d\n", iproc, lrows_arr[iproc]);
1220 PetscInt tot_lrows = 0;
1221 for(PetscInt p=0; p<mpi_size; ++p){
1222 rstart_arr[p] = tot_lrows;
1223 tot_lrows += lrows_arr[p];
1225 if(ctx.
Nrows!=tot_lrows){
1227 printf(
"--------------------------------------------------\n");
1228 printf(
"[0] Redistribution failed at GlobIdx: %lld\n", LLD(GlobIdx));
1229 printf(
"[0] >>> tot_lrows: %lld\n", LLD(tot_lrows));
1230 printf(
"[0] >>> ctx.Nrows: %lld\n", LLD(ctx.
Nrows));
1231 printf(
"[0] >>> tot_nnz: %lld\n", LLD(tot_nnz));
1232 printf(
"[0] >>> avg_nnz_proc: %lld\n", LLD(avg_nnz_proc));
1233 printf(
"[0] >>> nnz_proc: [ %lld", LLD(nnz_proc[0]));
1234 for(PetscInt p=1; p<mpi_size; ++p) printf(
", %lld", LLD(nnz_proc[p]));
1236 #if 0 && defined(DEBUG_REDIST) 1237 printf(
"[0] >>> Tnnz_arr: [ %d", Tnnz_arr[0]);
1238 for(PetscInt i=1; i<ctx.
Nrows; ++i) printf(
", %d", Tnnz_arr[i]);
1240 printf(
"--------------------------------------------------\n");
1246 SETERRQ2(PETSC_COMM_SELF,1,
"Incorrect total number of rows. " 1247 "Expected %d. Got %d.", ctx.
Nrows, tot_lrows);
1251 #if defined(DEBUG_REDIST) 1252 for(PetscInt p=0; p<mpi_size; ++p){
1253 printf(
"[%d] lrows: %3d rstart: %3d nnz: %d\n", p, lrows_arr[p], rstart_arr[p], nnz_proc[p]);
1258 ierr = MPI_Bcast(&flg, 1, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1261 ierr = MPI_Scatter(lrows_arr, 1, MPIU_INT, &ctx.
lrows, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1262 ierr = MPI_Scatter(rstart_arr, 1, MPIU_INT, &ctx.
rstart, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1268 ierr = PetscFree2(ctx.
Dnnz, ctx.
Onnz); CHKERRQ(ierr);
1270 ctx.ReqRowsR.clear();
1272 ctx.MapRowsR.clear();
1276 ierr = MatDestroySubMatrices(1,&mat); CHKERRQ(ierr);
1280 ierr = PetscFree2(Tnnz_arr, Onnz_arr); CHKERRQ(ierr);
1281 ierr = PetscFree2(lrows_arr, rstart_arr); CHKERRQ(ierr);
1282 #if defined(PETSC_USE_64BIT_INDICES) 1284 ierr = PetscFree2(lrows_arr_mpi, rstart_arr_mpi); CHKERRQ(ierr);
1288 FUNCTION_TIMINGS_END()
1292 PetscErrorCode KronBlocks_t::KronSumPreallocate(
1297 PetscErrorCode ierr = 0;
1298 FUNCTION_TIMINGS_BEGIN()
1300 ierr = MatCreate(mpi_comm, &MatOut); CHKERRQ(ierr);
1302 ierr = MatSetType(MatOut,MATMPIAIJ); CHKERRQ(ierr);
1303 ierr = MatSetOptionsPrefix(MatOut,
"H_"); CHKERRQ(ierr);
1304 ierr = MatSetFromOptions(MatOut); CHKERRQ(ierr);
1305 ierr = MatMPIAIJSetPreallocation(MatOut, 0, ctx.
Dnnz, 0, ctx.
Onnz); CHKERRQ(ierr);
1306 ierr = PetscFree2(ctx.
Dnnz, ctx.
Onnz); CHKERRQ(ierr);
1309 ierr = MatSetOption(MatOut, MAT_HERMITIAN, PETSC_TRUE); CHKERRQ(ierr);
1310 ierr = MatSetOption(MatOut, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE); CHKERRQ(ierr);
1311 ierr = MatSetOption(MatOut, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE); CHKERRQ(ierr);
1312 ierr = MatSetOption(MatOut, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE); CHKERRQ(ierr);
1313 ierr = MatSetOption(MatOut, MAT_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE); CHKERRQ(ierr);
1314 ierr = MatSetOption(MatOut, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE); CHKERRQ(ierr);
1315 ierr = MatSetOption(MatOut, MAT_NO_OFF_PROC_ZERO_ROWS, PETSC_TRUE); CHKERRQ(ierr);
1316 ierr = MatSetOption(MatOut, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE); CHKERRQ(ierr);
1320 const PetscInt M = MatOut->rmap->N;
1321 const PetscInt N = MatOut->cmap->N;
1322 const PetscInt Istart = MatOut->rmap->rstart;
1323 const PetscInt locrows = MatOut->rmap->rend - Istart;
1324 if(locrows!=ctx.
lrows) SETERRQ4(PETSC_COMM_SELF, 1,
1325 "Incorrect guess for locrows. Expected %d. Got %d. Size: %d x %d.", locrows, ctx.
lrows, M, N);
1326 if(Istart!=ctx.
rstart) SETERRQ4(PETSC_COMM_SELF, 1,
1327 "Incorrect guess for Istart. Expected %d. Got %d. Size: %d x %d.", Istart, ctx.
rstart, M, N);
1328 const PetscInt Cstart = MatOut->cmap->rstart;
1329 const PetscInt loccols = MatOut->cmap->rend - Cstart;
1330 if(loccols!=ctx.
lcols) SETERRQ4(PETSC_COMM_SELF, 1,
1331 "Incorrect guess for loccols. Expected %d. Got %d. Size: %d x %d.", loccols, ctx.
lcols, M, N);
1332 if(Cstart!=ctx.
cstart) SETERRQ4(PETSC_COMM_SELF, 1,
1333 "Incorrect guess for Cstart. Expected %d. Got %d. Size: %d x %d.", Cstart, ctx.
cstart, M, N);
1336 FUNCTION_TIMINGS_END()
1340 PetscErrorCode KronBlocks_t::KronSumFillMatrix(
1345 PetscErrorCode ierr = 0;
1346 INTERVAL_TIMINGS_SETUP()
1347 FUNCTION_TIMINGS_BEGIN()
1351 PetscScalar *val_arr;
1353 if(Nvals <= 0) SETERRQ1(PETSC_COMM_SELF,1,
"Incorrect value of Nvals. Must be positive. Got %lld.", LLD(Nvals));
1354 ierr = PetscCalloc1(Nvals, &idx_arr); CHKERRQ(ierr);
1355 ierr = PetscCalloc1(Nvals, &val_arr); CHKERRQ(ierr);
1358 for(PetscInt i=0; i < Nvals; ++i) idx_arr[i] = ctx.
MinIdx + i;
1364 std::map< Op_t, PetscInt > fws_LOP = {};
1365 std::map< Op_t, PetscInt > Row_NumStates_ROP = {};
1367 ACCUM_TIMINGS_SETUP(KronIterSetup)
1368 ACCUM_TIMINGS_SETUP(MatSetValues)
1369 ACCUM_TIMINGS_SETUP(MatLoop)
1370 INTERVAL_TIMINGS_BEGIN()
1374 for( ; KIter.
Loop(); ++KIter)
1376 ACCUM_TIMINGS_BEGIN(KronIterSetup)
1380 const PetscInt Row_L = KIter.GlobalIdxLeft();
1381 const PetscInt Row_R = KIter.GlobalIdxRight();
1382 const PetscInt LocRow_L = ctx.
MapRowsL.at(Row_L);
1383 const PetscInt LocRow_R = ctx.MapRowsR.at(Row_R);
1386 PetscInt nz_L, nz_R, bks_L, bks_R, col_NStatesR, fws_O;
1387 const PetscInt *idx_L, *idx_R;
1388 const PetscScalar *v_L, *v_R;
1396 {
OpSp ,
Offsets(Row_BlockIdx_L + 1, Row_BlockIdx_R - 1),},
1397 {
OpSm ,
Offsets(Row_BlockIdx_L - 1, Row_BlockIdx_R + 1)}
1400 Row_NumStates_ROP = {
1409 ierr = PetscMemzero(val_arr, Nvals*
sizeof(val_arr[0])); CHKERRQ(ierr);
1410 ACCUM_TIMINGS_END(KronIterSetup)
1411 ACCUM_TIMINGS_BEGIN(MatLoop)
1414 if(term.OpTypeA !=
OpEye){
1415 ierr = (*term.A->ops->getrow)(term.A, LocRow_L, &nz_L, (PetscInt**)&idx_L, (PetscScalar**)&v_L); CHKERRQ(ierr);
1424 if(term.OpTypeB !=
OpEye){
1425 ierr = (*term.B->ops->getrow)(term.B, LocRow_R, &nz_R, (PetscInt**)&idx_R, (PetscScalar**)&v_R); CHKERRQ(ierr);
1435 if(nz_L*nz_R == 0)
continue;
1437 fws_O = fws_LOP.at(term.OpTypeA) - ctx.
MinIdx;
1438 col_NStatesR = Row_NumStates_ROP.at(term.OpTypeB);
1439 if(col_NStatesR==-1) SETERRQ(PETSC_COMM_SELF,1,
"Accessed incorrect value.");
1440 for(PetscInt l=0; l<nz_L; ++l)
1442 for(PetscInt r=0; r<nz_R; ++r)
1444 val_arr[( (idx_L[l] - bks_L) * col_NStatesR + (idx_R[r] - bks_R) + fws_O )] += term.a * v_L[l] * v_R[r];
1449 for(PetscInt i=0; i<Nvals; i++){
1450 if(PetscAbsScalar(val_arr[i]) < ks_tol){
1456 ACCUM_TIMINGS_END(MatLoop)
1457 ACCUM_TIMINGS_BEGIN(MatSetValues)
1458 ierr = MatSetValues(MatOut, 1, &Irow, Nvals, idx_arr, val_arr, INSERT_VALUES); CHKERRQ(ierr);
1459 ACCUM_TIMINGS_END(MatSetValues)
1462 ierr = PetscFree(val_arr); CHKERRQ(ierr);
1463 ierr = PetscFree(idx_arr); CHKERRQ(ierr);
1465 ACCUM_TIMINGS_PRINT(KronIterSetup,
" KronIterSetup")
1466 ACCUM_TIMINGS_PRINT(MatLoop,
" MatLoop")
1467 ACCUM_TIMINGS_PRINT(MatSetValues,
" MatSetValues")
1468 INTERVAL_TIMINGS_END(
"KronSumFillMatrixLoop")
1470 INTERVAL_TIMINGS_BEGIN()
1471 ierr = MatEnsureAssembled(MatOut); CHKERRQ(ierr);
1472 INTERVAL_TIMINGS_END(
"MatEnsureAssembled")
1474 FUNCTION_TIMINGS_END()
1475 FUNCTION_TIMINGS_PRINT_SPACE()
1479 PetscErrorCode KronBlocks_t::SavePreallocData(
const KronSumCtx& ctx)
1484 PetscInt Dnnz=0, Onnz=0;
1485 for(PetscInt irow=0; irow<ctx.
lrows; ++irow) Dnnz += ctx.
Dnnz[irow];
1486 for(PetscInt irow=0; irow<ctx.
lrows; ++irow) Onnz += ctx.
Onnz[irow];
1488 PetscErrorCode ierr = 0;
1489 PetscInt *Dnnz_arr, *Onnz_arr;
1490 PetscInt arr_size = mpi_rank ? 0 : mpi_size;
1491 ierr = PetscCalloc2(arr_size, &Dnnz_arr, arr_size, &Onnz_arr); CHKERRQ(ierr);
1492 ierr = MPI_Gather(&Dnnz, 1, MPIU_INT, Dnnz_arr, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1493 ierr = MPI_Gather(&Onnz, 1, MPIU_INT, Onnz_arr, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1495 if(mpi_rank)
return(0);
1499 " \"GlobIdx\" : %lld,\n" 1500 " \"Dnnz\" : [", LLD(GlobIdx));
1502 for(PetscInt iproc=1; iproc<mpi_size; ++iproc){
1503 fprintf(
fp_prealloc,
", %lld", LLD(Dnnz_arr[iproc]));
1508 for(PetscInt iproc=1; iproc<mpi_size; ++iproc){
1509 fprintf(
fp_prealloc,
", %lld", LLD(Onnz_arr[iproc]));
1513 ierr = PetscFree2(Dnnz_arr, Onnz_arr); CHKERRQ(ierr);
1519 PetscErrorCode KronBlocks_t::KronSumShellSplitOwnership(
1520 const Mat& OpProdSumLL,
1521 const Mat& OpProdSumRR,
1522 const std::vector< Hamiltonians::Term >& TermsLR,
1523 const PetscInt Nrows,
1528 FUNCTION_TIMINGS_BEGIN();
1529 PetscErrorCode ierr;
1530 if(Nrows!=
num_states) SETERRQ2(mpi_comm,1,
"Invalid input Nrows. Expected %lld. Got %lld.", LLD(
num_states), LLD(Nrows));
1534 std::map< std::tuple< Side_t, Op_t, PetscInt >, std::vector<PetscInt> > nnzs_loc, nnzs;
1535 std::tuple< Side_t, Op_t, PetscInt > key;
1536 PetscMPIInt lrows_L, lrows_R;
1542 key = std::make_tuple(
SideLeft, term.Iop, term.Isite);
1543 if(nnzs_loc.find(key)==nnzs_loc.end())
1545 ierr = LeftBlock.
MatOpGetNNZs(term.Iop, term.Isite, nnzs_loc[key]); CHKERRQ(ierr);
1549 key = std::make_tuple(
SideRight, term.Jop, term.Jsite);
1550 if(nnzs_loc.find(key)==nnzs_loc.end())
1552 ierr = RightBlock.
MatOpGetNNZs(term.Jop, term.Jsite, nnzs_loc[key]); CHKERRQ(ierr);
1558 if(nnzs_loc.find(key)==nnzs_loc.end())
1560 ierr = LeftBlock.
MatGetNNZs(OpProdSumLL, nnzs_loc[key]); CHKERRQ(ierr);
1561 ierr = PetscMPIIntCast(PetscInt(nnzs_loc[key].
size()), &lrows_L);
1563 else SETERRQ(mpi_comm,1,
"Key error: (SideLeft, OpSz, -1).");
1567 if(nnzs_loc.find(key)==nnzs_loc.end())
1569 ierr = LeftBlock.
MatGetNNZs(OpProdSumRR, nnzs_loc[key]); CHKERRQ(ierr);
1570 ierr = PetscMPIIntCast(PetscInt(nnzs_loc[key].
size()), &lrows_R);
1572 else SETERRQ(mpi_comm,1,
"Key error: (SideRight, OpSz, -1).");
1575 std::vector< std::vector< PetscMPIInt > > side_lrows(2);
1576 side_lrows[
SideLeft ].resize(mpi_rank ? 1 : mpi_size);
1577 side_lrows[
SideRight].resize(mpi_rank ? 1 : mpi_size);
1579 ierr = MPI_Gather(&lrows_L, 1, MPI_INT, &side_lrows[
SideLeft ].at(0), 1, MPI_INT, 0, mpi_comm); CHKERRQ(ierr);
1580 ierr = MPI_Gather(&lrows_R, 1, MPI_INT, &side_lrows[
SideRight].at(0), 1, MPI_INT, 0, mpi_comm); CHKERRQ(ierr);
1583 std::vector< std::vector< PetscMPIInt > > side_offset(2);
1584 std::vector< PetscMPIInt > side_nrows(2);
1585 side_offset[
SideLeft ].resize(mpi_rank ? 1 : mpi_size);
1586 side_offset[
SideRight].resize(mpi_rank ? 1 : mpi_size);
1588 for(
const auto& side_key: SideTypes)
1591 const std::vector< PetscMPIInt >& lrows = side_lrows.at(side_key);
1592 std::vector< PetscMPIInt >& offset = side_offset.at(side_key);
1593 PetscInt sum_lrows = 0;
1594 for(
size_t i=0; i<lrows.size(); ++i)
1596 offset[i] = sum_lrows;
1597 sum_lrows += lrows.at(i);
1599 ierr = PetscMPIIntCast(PetscInt(mpi_rank ? 1 : sum_lrows), &side_nrows.at(side_key)); CHKERRQ(ierr);
1604 for(
const auto& pair_loc: nnzs_loc)
1606 const std::tuple< Side_t, Op_t, PetscInt >& key = pair_loc.first;
1607 const std::vector< PetscInt >& nnz_loc = pair_loc.second;
1608 const Side_t side = std::get<0>(key);
1609 PetscMPIInt nnz_loc_size;
1610 ierr = PetscMPIIntCast(PetscInt(nnz_loc.size()),&nnz_loc_size); CHKERRQ(ierr);
1611 nnzs[key].resize(side_nrows.at(side));
1613 const PetscInt *nnz_loc_val = nnz_loc.empty() ? NULL : &nnz_loc.at(0);
1614 ierr = MPI_Gatherv(nnz_loc_val, nnz_loc_size, MPIU_INT,
1615 &nnzs.at(key).at(0), &side_lrows.at(side).at(0), &side_offset.at(side).at(0),
1616 MPIU_INT, 0, mpi_comm); CHKERRQ(ierr);
1619 PetscBool flg = PETSC_TRUE;
1620 std::vector< PetscInt > lrows_arr(mpi_rank ? 1: mpi_size), rstart_arr(mpi_rank ? 1: mpi_size);
1625 std::tuple< Side_t, Op_t, PetscInt > key_L, key_R;
1627 for( ; KIter.
Loop(); ++KIter)
1629 const PetscInt lrow = KIter.
Steps();
1630 const PetscInt Row_L = KIter.GlobalIdxLeft();
1631 const PetscInt Row_R = KIter.GlobalIdxRight();
1635 key_L = std::make_tuple(
SideLeft, term.Iop, term.Isite);
1636 key_R = std::make_tuple(
SideRight, term.Jop, term.Jsite);
1637 ks_nnz.at(lrow) += nnzs.at(key_L).at(Row_L) * nnzs.at(key_R).at(Row_R);
1640 ks_nnz.at(lrow) += nnzs.at(key_L).at(Row_L);
1642 ks_nnz.at(lrow) += nnzs.at(key_R).at(Row_R);
1646 for(
const PetscInt& nnz: ks_nnz) tot_nnz+=nnz;
1649 PetscInt avg_nnz_proc = tot_nnz / mpi_size;
1650 std::vector< PetscInt > nnz_proc(mpi_size);
1651 for(PetscInt irow=0, iproc=0; irow<Nrows; ++irow)
1653 if(iproc>=mpi_size)
break;
1654 nnz_proc.at(iproc) += ks_nnz.at(irow);
1655 ++lrows_arr.at(iproc);
1656 if( nnz_proc.at(iproc) >= avg_nnz_proc ) ++iproc;
1659 PetscInt tot_lrows = 0;
1660 for(PetscInt p=0; p<mpi_size; ++p)
1662 rstart_arr[p] = tot_lrows;
1663 tot_lrows += lrows_arr[p];
1665 if(Nrows!=tot_lrows)
1667 printf(
"--------------------------------------------------\n");
1668 printf(
"[0] Redistribution failed at GlobIdx: %lld\n", LLD(GlobIdx));
1669 printf(
"[0] >>> tot_lrows: %lld\n", LLD(tot_lrows));
1670 printf(
"[0] >>> ctx.Nrows: %lld\n", LLD(Nrows));
1671 printf(
"[0] >>> tot_nnz: %lld\n", LLD(tot_nnz));
1672 printf(
"[0] >>> avg_nnz_proc: %lld\n", LLD(avg_nnz_proc));
1673 printf(
"[0] >>> nnz_proc: [ %lld", LLD(nnz_proc[0]));
1674 for(PetscInt p=1; p<mpi_size; ++p) printf(
", %lld", LLD(nnz_proc[p]));
1678 SETERRQ2(PETSC_COMM_SELF,1,
"Incorrect total number of rows. " 1679 "Expected %d. Got %d.", Nrows, tot_lrows);
1686 ierr = MPI_Bcast(&flg, 1, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1690 ierr = MPI_Scatter(&lrows_arr.at(0), 1, MPIU_INT, &lrows, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1691 ierr = MPI_Scatter(&rstart_arr.at(0), 1, MPIU_INT, &rstart, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1695 ierr = PreSplitOwnership(mpi_comm, Nrows, lrows, rstart); CHKERRQ(ierr);
1702 FUNCTION_TIMINGS_END();
1706 PetscErrorCode KronBlocks_t::KronSumSetUpShellTerms(
KronSumShellCtx *shellctx)
1708 PetscErrorCode ierr;
1709 FUNCTION_TIMINGS_BEGIN()
1714 shellctx->one = 1.00;
1715 shellctx->Nterms = ctx.
Terms.size();
1716 shellctx->Nrowterms = (shellctx->Nterms) * (ctx.
lrows);
1717 ierr = PetscCalloc1(ctx.
lrows, &(shellctx->Rows_L)); CHKERRQ(ierr);
1718 ierr = PetscCalloc1(ctx.
lrows, &(shellctx->Rows_R)); CHKERRQ(ierr);
1719 ierr = PetscCalloc1(shellctx->Nrowterms, &(shellctx->
kstr)); CHKERRQ(ierr);
1722 ierr = PetscCalloc1(shellctx->Nterms, &(shellctx->term_a)); CHKERRQ(ierr);
1723 for(PetscInt it = 0; it < shellctx->Nterms; ++it){
1724 (shellctx->term_a)[it] = ctx.
Terms[it].a;
1730 std::map< Op_t, PetscInt > fws_LOP = {};
1731 std::map< Op_t, PetscInt > Row_NumStates_ROP = {};
1733 ACCUM_TIMINGS_SETUP(KronIterSetup)
1734 ACCUM_TIMINGS_SETUP(MatLoop)
1738 for( ; KIter.
Loop(); ++KIter)
1740 ACCUM_TIMINGS_BEGIN(KronIterSetup)
1741 const PetscInt lrow = KIter.
Steps();
1744 const PetscInt Row_L = shellctx->Rows_L[lrow] = KIter.GlobalIdxLeft();
1745 const PetscInt Row_R = shellctx->Rows_R[lrow] = KIter.GlobalIdxRight();
1746 const PetscInt LocRow_L = ctx.
MapRowsL.at(Row_L);
1747 const PetscInt LocRow_R = ctx.MapRowsR.at(Row_R);
1757 {
OpSp ,
Offsets(Row_BlockIdx_L + 1, Row_BlockIdx_R - 1),},
1758 {
OpSm ,
Offsets(Row_BlockIdx_L - 1, Row_BlockIdx_R + 1)}
1761 Row_NumStates_ROP = {
1768 ACCUM_TIMINGS_END(KronIterSetup)
1771 ACCUM_TIMINGS_BEGIN(MatLoop)
1777 if(term.OpTypeA !=
OpEye){
1778 ierr = (*term.A->ops->getrow)(term.A, LocRow_L,
1779 &(kstr.nz_L), (PetscInt**)&(kstr.idx_L), (PetscScalar**)&(kstr.v_L)); CHKERRQ(ierr);
1783 kstr.idx_L = &(shellctx->Rows_L[lrow]);
1784 kstr.v_L = &(shellctx->one);
1788 if(term.OpTypeB !=
OpEye){
1789 ierr = (*term.B->ops->getrow)(term.B, LocRow_R,
1790 &(kstr.nz_R), (PetscInt**)&(kstr.idx_R), (PetscScalar**)&(kstr.v_R)); CHKERRQ(ierr);
1794 kstr.idx_R = &(shellctx->Rows_R[lrow]);
1795 kstr.v_R = &(shellctx->one);
1803 kstr.fws_O = fws_LOP.at(term.OpTypeA) - bks_R;
1804 kstr.col_NStatesR = Row_NumStates_ROP.at(term.OpTypeB);
1805 if(kstr.col_NStatesR==-1) SETERRQ(PETSC_COMM_SELF,1,
"Accessed incorrect value.");
1810 ACCUM_TIMINGS_END(MatLoop)
1813 if(irt!=(shellctx->Nrowterms)) SETERRQ2(PETSC_COMM_SELF,1,
1814 "Wrong index irt. Expected %lld. Got %lld.", LLD(shellctx->Nrowterms), LLD(irt));
1818 ACCUM_TIMINGS_PRINT(KronIterSetup,
" KronIterSetup")
1819 ACCUM_TIMINGS_PRINT(MatLoop,
" MatLoop")
1821 FUNCTION_TIMINGS_END()
1822 FUNCTION_TIMINGS_PRINT_SPACE()
1827 PETSC_EXTERN PetscErrorCode MatMult_KronSumShell(Mat A, Vec x, Vec y)
1829 PetscErrorCode ierr;
1831 ierr = MatShellGetContext(A,(
void**)&shellctx); CHKERRQ(ierr);
1833 ierr = VecScatterBegin(shellctx->vsctx, x, shellctx->x_seq, INSERT_VALUES, SCATTER_FORWARD); CHKERRQ(ierr);
1834 ierr = VecScatterEnd(shellctx->vsctx, x, shellctx->x_seq, INSERT_VALUES, SCATTER_FORWARD); CHKERRQ(ierr);
1836 const PetscScalar *xvals;
1838 ierr = VecGetArrayRead(shellctx->x_seq, &xvals); CHKERRQ(ierr);
1839 ierr = VecGetArray(y, &yvals); CHKERRQ(ierr);
1840 ierr = PetscMemzero(yvals, (ctx.
lrows)*
sizeof(PetscScalar)); CHKERRQ(ierr);
1842 PetscInt irt=-1,idx;
1843 PetscScalar yval, temp;
1844 for(PetscInt ir = 0; ir < ctx.
lrows; ++ir)
1847 for(PetscInt it = 0; it < shellctx->Nterms; ++it)
1852 for(PetscInt l=0; l<kstr.nz_L; ++l)
1855 idx = (kstr.idx_L[l] - kstr.bks_L) * kstr.col_NStatesR + kstr.fws_O;
1856 temp = shellctx->term_a[it] * kstr.v_L[l];
1857 for(PetscInt r=0; r<kstr.nz_R; ++r)
1859 yval += temp * kstr.v_R[r] * xvals[idx + kstr.idx_R[r]];
1866 ierr = VecRestoreArrayRead(shellctx->x_seq, &xvals);
1867 ierr = VecRestoreArray(y, &yvals);
1871 PetscErrorCode KronBlocks_t::KronSumConstructShell(
1872 const std::vector< Hamiltonians::Term >& TermsLR,
1876 PetscErrorCode ierr = 0;
1879 ierr = PetscNew(&shellctx); CHKERRQ(ierr);
1889 ierr = KronSumShellSplitOwnership(LeftBlock.
H, RightBlock.
H, TermsLR, ctx.
Nrows, ctx.
lrows, ctx.
rstart); CHKERRQ(ierr);
1894 ierr = PreSplitOwnership(mpi_comm, ctx.
Nrows, ctx.
lrows, ctx.
rstart); CHKERRQ(ierr);
1901 ierr = KronSumGetSubmatrices(LeftBlock.
H, RightBlock.
H, TermsLR, ctx); CHKERRQ(ierr);
1904 ierr = KronSumSetUpShellTerms(shellctx); CHKERRQ(ierr);
1907 ierr = VecCreateMPI(mpi_comm, ctx.
lrows, PETSC_DETERMINE, &x_mpi); CHKERRQ(ierr);
1908 ierr = VecScatterCreateToAll(x_mpi, &shellctx->vsctx, &shellctx->x_seq); CHKERRQ(ierr);
1909 ierr = VecDestroy(&x_mpi); CHKERRQ(ierr);
1912 ierr = MatCreateShell(mpi_comm, ctx.
lrows, ctx.
lcols, ctx.
Nrows, ctx.
Ncols, (
void*)shellctx, &MatOut); CHKERRQ(ierr);
1914 ierr = MatShellSetOperation(MatOut, MATOP_MULT, (
void(*)())MatMult_KronSumShell); CHKERRQ(ierr);
1919 PetscErrorCode MatDestroy_KronSumShell(Mat *p_mat)
1921 PetscErrorCode ierr;
1923 ierr = MatShellGetContext(*p_mat,(
void**)&shellctx); CHKERRQ(ierr);
1926 ierr = PetscFree(shellctx->term_a); CHKERRQ(ierr);
1927 ierr = PetscFree(shellctx->
kstr); CHKERRQ(ierr);
1928 ierr = PetscFree(shellctx->Rows_L); CHKERRQ(ierr);
1929 ierr = PetscFree(shellctx->Rows_R); CHKERRQ(ierr);
1930 ierr = VecDestroy(&(shellctx->x_seq)); CHKERRQ(ierr);
1931 ierr = VecScatterDestroy(&(shellctx->vsctx)); CHKERRQ(ierr);
1934 ierr = MatDestroySubMatrices(1,&mat); CHKERRQ(ierr);
1937 delete shellctx->
p_ctx;
1938 shellctx->
p_ctx = NULL;
1939 ierr = PetscFree(shellctx); CHKERRQ(ierr);
PetscInt Steps() const
Gets the number of steps incremented from the starting index.
Base class for the implementation of a block of spin sites.
Calculates the sum of the Kronecker product of operators on two blocks following the terms of a Hamil...
PetscBool do_shell
Whether to create an implicit MATSHELL matrix.
PetscInt rstart
Starting index of local rows.
PetscInt size() const
Returns the total number blocks.
PetscInt OpBlockToGlobalRangeStart(const PetscInt &BlockIdx, const PetscInt &BlockShift, PetscBool &flg) const
Maps the shifted quantum number block index to the global index start in the range [start...
A single term of the KronSum.
Context structure defining a single row of KronSumShell.
std::vector< KronSumTerm > Terms
Lists down all the terms of the KronSum with Mat entries filled with local submatrices.
PetscErrorCode EnsureSaved()
Ensures that the block matrices have been saved if the block is initialized, otherwise does nothing...
PetscErrorCode KronEye_Explicit(Block::SpinBase &LeftBlock, Block::SpinBase &RightBlock, const std::vector< Hamiltonians::Term > &Terms, Block::SpinBase &BlockOut)
Calculates a new block combining two spin-1/2 blocks.
FILE * fp_prealloc
File to store preallocation data for each processor.
Op_t
Identifies the three possible spin operators and also represents the shift associated to its action o...
PetscErrorCode CheckOperatorBlocks() const
Checks whether all matrix blocks follow the correct sector indices using MatCheckOperatorBlocks() ...
PetscErrorCode VerifySzAssumption(const std::vector< Mat > &Matrices, const Side_t &SideType)
Verifies that the assumtpion of intra-block terms to follow Sz form is valid.
PetscBool UpdatedBlock() const
Gets the update state of the block index from the previous increment.
PetscBool do_saveprealloc
Whether to store preallocation data for each processor.
PetscInt * Onnz
Preallocation data of the output matrix for local off-diagonal diagonal rows.
std::unordered_map< PetscInt, PetscInt > MapRowsL
Maps the global indices of the rows of L and R to their local indices in the corresponding submatrice...
Mat H
Matrix representation of the Hamiltonian operator.
PetscErrorCode KronConstruct(const Mat &Mat_L, const Op_t &OpType_L, const Mat &Mat_R, const Op_t &OpType_R, Mat &MatOut)
Constructs the explicit sum of Kronecker products of two matrices provided that they follow a fixed K...
PetscInt cstart
Starting index of local columns.
std::vector< PetscReal > List() const
Returns the list of quantum numbers.
PetscInt rend
Index after last of local rows, exclusive.
std::vector< PetscInt > Maxnnz
Predicted maximum number of elements on each local row.
PetscInt cend
Index after last of local columns, exclusive.
std::vector< Mat * > LocalSubMats
List of unique submatrices to be destroyed later.
PetscErrorCode MatOpGetNNZs(const Op_t &OpType, const PetscInt &isite, std::vector< PetscInt > &nnzs) const
Returns the number of non-zeros in each row for an operator acting on a given site.
PetscErrorCode DestroySm()
Destroys the Sm matrices on the fly.
A single interaction term on a one-dimensional lattice.
PetscInt BlockIdxLeft() const
Gets the block index for the left side.
PetscInt Nrows
Total number of rows.
PetscErrorCode CheckOperators() const
Checks whether all operators have been initialized and have correct dimensions.
PetscErrorCode CheckSectors() const
Checks whether sector indexing was done properly.
std::vector< PetscInt > ReqRowsL
List of required rows of the left and right blocks.
std::vector< PetscInt > Sizes() const
Returns the number of basis states in each quantum number block.
std::vector< PetscInt > Offsets() const
Returns the offsets for each quantum number block.
PetscInt * Dnnz
Preallocation data of the output matrix for local diagonal rows.
PetscInt MaxIdx
Largest non-zero index in the current set of local rows.
PetscInt prev_rstart
Stores the resulting rstart of a previous call to KronSumShellSplitOwnership.
PetscBool do_redistribute
Whether to redistribute the resulting KronSum.
PetscInt lrows
Number of local rows.
PetscInt BlockStartIdx(const PetscInt &BlockShift) const
Gets the column index of the starting block with a shift.
PetscErrorCode KronSumConstruct(const std::vector< Hamiltonians::Term > &Terms, Mat &MatOut)
Constructs the explicit sum of Kronecker products of matrices from the blocks.
KronSumTermRow * kstr
Contains the KronSumTermRow's needed for calculating the terms of the full matrix.
Mat Sz(const PetscInt &Isite) const
Returns the matrix pointer to the operator at site Isite.
PetscBool Initialized() const
Indicates whether block has been initialized before using it.
const std::vector< KronBlock_t > & data() const
Returns a const reference to the KronBlocks object.
PetscInt NReqRowsL
Number of required rows of the left and right blocks.
PetscErrorCode CreateSm()
Creates the Sm matrices on the fly.
PetscInt Ncols
Total number of columns.
PetscInt MinIdx
Smallest non-zero index in the current set of local rows.
PetscInt NumSectors() const
Returns the number of quantum number sectors.
std::vector< PetscInt > Offsets() const
Returns the offsets for each quantum number block.
std::tuple< PetscReal, PetscInt, PetscInt, PetscInt > KronBlock_t
Storage for information on resulting blocks of quantum numbers stored as a tuple for quick sorting...
PetscInt num_states
The total number of states stored.
PetscInt lcols
Number of local columns.
KronSumCtx * p_ctx
Contains the usual ctx object for explicit matrices.
PetscErrorCode Initialize(const MPI_Comm &comm_in)
Initializes block object's MPI attributes.
Context for the shell matrix object.
A container of ordered KronBlock_t objects representing a Kronecker product structure.
QuantumNumbers Magnetization
Stores the information on the magnetization Sectors.
PetscErrorCode MatGetNNZs(const Mat &matin, std::vector< PetscInt > &nnzs) const
Returns the number of non-zeros in each row for a given matrix.
PetscBool called_KronSumShellSplitOwnership
Whether KronSumShellSplitOwnership has been called before.
PetscInt NumSites() const
Gets the number of sites that are currently initialized.
PetscErrorCode MatCheckOperatorBlocks(const Op_t &op_t, const Mat &matin) const
Checks the block indexing in the matrix operator op_t on specified matrix matin.
Mat Sp(const PetscInt &Isite) const
Returns the matrix pointer to the operator at site Isite.
MPI_Comm MPIComm() const
Gets the communicator associated to the block.
PetscInt NumStates() const
Returns the total number of states.
bool Loop() const
Determines whether the end of the range has not yet been reached.
Defines a single operator to be used for performing measurements.
PetscInt BlockIdxRight() const
Gets the block index for the right side.
PetscInt prev_lrows
Stores the resulting lrows of a previous call to KronSumShellSplitOwnership.
PetscInt NumStates() const
Gets the number of states that are currently used.
PetscInt NumStates() const
Returns the total number of states.
Context struct for the KronSumShell matrix.
PetscInt NumStatesRight() const
Gets the number of states for the right block.
Side_t
Identifies the sides of the DMRG block.