46 #ifndef _PEXSI_UTILITY_IMPL_HPP_
47 #define _PEXSI_UTILITY_IMPL_HPP_
65 inline void ReadSparseMatrix (
const char* filename, SparseMatrix<Real>& spmat )
68 PushCallStack(
"ReadSparseMatrix");
74 std::istringstream iss;
75 SharedRead( filename, iss );
76 deserialize( spmat.size, iss, NO_MASK );
77 deserialize( spmat.nnz, iss, NO_MASK );
78 deserialize( spmat.colptr, iss, NO_MASK );
79 deserialize( spmat.rowind, iss, NO_MASK );
80 deserialize( spmat.nzval, iss, NO_MASK );
85 ifstream fin(filename);
86 fin >> spmat.size >> spmat.nnz;
88 spmat.colptr.Resize( spmat.size+1 );
89 spmat.rowind.Resize( spmat.nnz );
90 spmat.nzval.Resize ( spmat.nnz );
92 for( Int i = 0; i < spmat.size + 1; i++ ){
93 fin >> spmat.colptr(i);
96 for( Int i = 0; i < spmat.nnz; i++ ){
97 fin >> spmat.rowind(i);
100 for( Int i = 0; i < spmat.nnz; i++ ){
101 fin >> spmat.nzval(i);
114 inline void ReadDistSparseMatrix (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
117 PushCallStack(
"ReadDistSparseMatrix");
121 Int mpirank; MPI_Comm_rank(comm, &mpirank);
122 Int mpisize; MPI_Comm_size(comm, &mpisize);
136 throw std::logic_error(
"File cannot be opened!" );
138 fin.read((
char*)&pspmat.size,
sizeof(Int));
139 fin.read((
char*)&pspmat.nnz,
sizeof(Int));
144 MPI_Bcast(&pspmat.size, 1, MPI_INT, 0, comm);
145 MPI_Bcast(&pspmat.nnz, 1, MPI_INT, 0, comm);
148 IntNumVec colptr(pspmat.size+1);
151 fin.read((
char*)&tmp,
sizeof(Int));
153 if( tmp != pspmat.size+1 ){
157 throw std::logic_error(
"colptr is not of the right size." );
160 fin.read((
char*)colptr.Data(),
sizeof(Int)*tmp);
164 MPI_Bcast(colptr.Data(), pspmat.size+1, MPI_INT, 0, comm);
167 IntNumVec numColLocalVec(mpisize);
168 Int numColLocal, numColFirst;
169 numColFirst = pspmat.size / mpisize;
170 SetValue( numColLocalVec, numColFirst );
171 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
172 numColLocal = numColLocalVec[mpirank];
174 pspmat.colptrLocal.Resize( numColLocal + 1 );
175 for( Int i = 0; i < numColLocal + 1; i++ ){
176 pspmat.colptrLocal[i] = colptr[mpirank * numColFirst+i] - colptr[mpirank * numColFirst] + 1;
180 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
182 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
183 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
188 fin.read((
char*)&tmp,
sizeof(Int));
190 if( tmp != pspmat.nnz ){
191 std::ostringstream msg;
193 <<
"The number of nonzeros in row indices do not match." << std::endl
194 <<
"nnz = " << pspmat.nnz << std::endl
195 <<
"size of row indices = " << tmp << std::endl;
199 throw std::logic_error( msg.str().c_str() );
203 for( Int ip = 0; ip < mpisize; ip++ ){
204 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
205 colptr[ip*numColFirst];
207 fin.read( (
char*)buf.Data(), numRead*
sizeof(Int) );
210 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
211 MPI_Send(buf.Data(), numRead, MPI_INT, ip, 1, comm);
214 pspmat.rowindLocal = buf;
220 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
221 if( numRead != pspmat.nnzLocal ){
222 std::ostringstream msg;
223 msg <<
"The number of columns in row indices do not match." << std::endl
224 <<
"numRead = " << numRead << std::endl
225 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
229 throw std::logic_error( msg.str().c_str() );
232 pspmat.rowindLocal.Resize( numRead );
233 MPI_Recv( pspmat.rowindLocal.Data(), numRead, MPI_INT, 0, 1, comm, &mpistat );
239 fin.read((
char*)&tmp,
sizeof(Int));
241 if( tmp != pspmat.nnz ){
242 std::ostringstream msg;
244 <<
"The number of nonzeros in values do not match." << std::endl
245 <<
"nnz = " << pspmat.nnz << std::endl
246 <<
"size of values = " << tmp << std::endl;
250 throw std::logic_error( msg.str().c_str() );
254 for( Int ip = 0; ip < mpisize; ip++ ){
255 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
256 colptr[ip*numColFirst];
258 fin.read( (
char*)buf.Data(), numRead*
sizeof(Real) );
261 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
262 MPI_Send(buf.Data(), numRead, MPI_DOUBLE, ip, 1, comm);
265 pspmat.nzvalLocal = buf;
271 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
272 if( numRead != pspmat.nnzLocal ){
273 std::ostringstream msg;
274 msg <<
"The number of columns in values do not match." << std::endl
275 <<
"numRead = " << numRead << std::endl
276 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
280 throw std::logic_error( msg.str().c_str() );
283 pspmat.nzvalLocal.Resize( numRead );
284 MPI_Recv( pspmat.nzvalLocal.Data(), numRead, MPI_DOUBLE, 0, 1, comm, &mpistat );
303 inline void ParaWriteDistSparseMatrix (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
306 PushCallStack(
"ParaWriteDistSparseMatrix");
310 Int mpirank; MPI_Comm_rank(comm, &mpirank);
311 Int mpisize; MPI_Comm_size(comm, &mpisize);
317 int filemode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_UNIQUE_OPEN;
324 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fout);
326 if (err != MPI_SUCCESS) {
330 throw std::logic_error(
"File cannot be opened!" );
336 err = MPI_File_write_at(fout, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
337 err = MPI_File_write_at(fout,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
342 Int numColLocal = pspmat.colptrLocal.m()-1;
343 Int numColFirst = pspmat.size / mpisize;
344 IntNumVec colptrChunk(numColLocal+1);
347 MPI_Exscan(&pspmat.nnzLocal, &prev_nz, 1, MPI_INT, MPI_SUM, comm);
349 for( Int i = 0; i < numColLocal + 1; i++ ){
350 colptrChunk[i] = pspmat.colptrLocal[i] + prev_nz;
354 MPI_Datatype memtype, filetype;
357 MPI_Datatype types[6] = {MPI_INT,MPI_INT, MPI_INT,MPI_INT, MPI_INT,MPI_DOUBLE};
360 blklens[0] = (mpirank==0)?1:0;
361 blklens[1] = numColLocal+1;
362 blklens[2] = (mpirank==0)?1:0;
363 blklens[3] = pspmat.nnzLocal;
364 blklens[4] = (mpirank==0)?1:0;
365 blklens[5] = pspmat.nnzLocal;
371 MPI_Offset myColPtrOffset, myRowIdxOffset, myNzValOffset;
372 myColPtrOffset = 3*
sizeof(int) + (mpirank*numColFirst)*
sizeof(Int);
373 myRowIdxOffset = 3*
sizeof(int) + (pspmat.size +1 + prev_nz)*
sizeof(Int);
374 myNzValOffset = 4*
sizeof(int) + (pspmat.size +1 + pspmat.nnz)*
sizeof(Int)+ prev_nz*
sizeof(Real);
375 disps[0] = 2*
sizeof(int);
376 disps[1] = myColPtrOffset;
377 disps[2] = myRowIdxOffset;
378 disps[3] =
sizeof(int)+myRowIdxOffset;
379 disps[4] = myNzValOffset;
380 disps[5] =
sizeof(int)+myNzValOffset;
384 #if ( _DEBUGlevel_ >= 1 )
387 tmp += sprintf(tmp,
"P%d ",mpirank);
388 for(
int i = 0; i<6; ++i){
390 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(
double));
392 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(
int));
394 tmp += sprintf(tmp,
"\n");
401 MPI_Type_create_struct(6, blklens, disps, types, &filetype);
402 MPI_Type_commit(&filetype);
405 Int np1 = pspmat.size+1;
406 MPI_Address( (
void *)&np1, &disps[0]);
407 MPI_Address(colptrChunk.Data(), &disps[1]);
408 MPI_Address( (
void *)&pspmat.nnz, &disps[2]);
409 MPI_Address((
void *)pspmat.rowindLocal.Data(), &disps[3]);
410 MPI_Address( (
void *)&pspmat.nnz, &disps[4]);
411 MPI_Address((
void *)pspmat.nzvalLocal.Data(), &disps[5]);
413 MPI_Type_create_struct(6, blklens, disps, types, &memtype);
414 MPI_Type_commit(&memtype);
419 err = MPI_File_set_view(fout, 0, MPI_BYTE, filetype,
"native",MPI_INFO_NULL);
425 err = MPI_File_write_all(fout, MPI_BOTTOM, 1, memtype, &status);
427 MPI_Type_free(&filetype);
428 MPI_Type_free(&memtype);
436 MPI_File_close(&fout);
444 inline void ParaReadDistSparseMatrix (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
447 PushCallStack(
"ParaReadDistSparseMatrix");
451 Int mpirank; MPI_Comm_rank(comm, &mpirank);
452 Int mpisize; MPI_Comm_size(comm, &mpisize);
457 MPI_Datatype types[3];
460 int filemode = MPI_MODE_RDONLY | MPI_MODE_UNIQUE_OPEN;
468 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fin);
470 if (err != MPI_SUCCESS) {
474 throw std::logic_error(
"File cannot be opened!" );
480 err = MPI_File_read_at(fin, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
481 err = MPI_File_read_at(fin,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
488 MPI_Address(&pspmat.size, &disps[0]);
489 MPI_Address(&pspmat.nnz, &disps[1]);
492 MPI_Type_struct(2, lens, disps, types, &type);
493 MPI_Type_commit(&type);
497 MPI_Bcast(MPI_BOTTOM, 1, type, 0, comm);
499 MPI_Type_free(&type);
502 IntNumVec numColLocalVec(mpisize);
503 Int numColLocal, numColFirst;
504 numColFirst = pspmat.size / mpisize;
505 SetValue( numColLocalVec, numColFirst );
506 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
507 numColLocal = numColLocalVec[mpirank];
508 pspmat.colptrLocal.Resize( numColLocal + 1 );
512 MPI_Offset myColPtrOffset = (2 + ((mpirank==0)?0:1) )*
sizeof(
int) + (mpirank*numColFirst)*
sizeof(Int);
515 lens[0] = (mpirank==0)?1:0;
516 lens[1] = numColLocal + 1;
518 MPI_Address(&np1, &disps[0]);
519 MPI_Address(pspmat.colptrLocal.Data(), &disps[1]);
521 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
522 MPI_Type_commit(&type);
524 err= MPI_File_read_at_all(fin, myColPtrOffset, MPI_BOTTOM, 1, type, &status);
526 if (err != MPI_SUCCESS) {
530 throw std::logic_error(
"error reading colptr" );
532 MPI_Type_free(&type);
535 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
538 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
539 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
542 MPI_Offset myRowIdxOffset = (3 + ((mpirank==0)?0:1) )*
sizeof(
int) + (pspmat.size+1 + (pspmat.colptrLocal[0]-1))*
sizeof(int);
544 lens[0] = (mpirank==0)?1:0;
545 lens[1] = pspmat.nnzLocal;
547 MPI_Address(&np1, &disps[0]);
548 MPI_Address(pspmat.rowindLocal.Data(), &disps[1]);
550 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
551 MPI_Type_commit(&type);
553 err= MPI_File_read_at_all(fin, myRowIdxOffset, MPI_BOTTOM, 1, type,&status);
555 if (err != MPI_SUCCESS) {
559 throw std::logic_error(
"error reading rowind" );
561 MPI_Type_free(&type);
565 MPI_Offset myNzValOffset = (4 + ((mpirank==0)?0:1) )*
sizeof(
int) + (pspmat.size+1 + pspmat.nnz)*
sizeof(Int) + (pspmat.colptrLocal[0]-1)*
sizeof(
double);
567 lens[0] = (mpirank==0)?1:0;
568 lens[1] = pspmat.nnzLocal;
570 MPI_Address(&np1, &disps[0]);
571 MPI_Address(pspmat.nzvalLocal.Data(), &disps[1]);
574 types[1] = MPI_DOUBLE;
576 MPI_Type_create_struct(2, lens, disps, types, &type);
577 MPI_Type_commit(&type);
579 err = MPI_File_read_at_all(fin, myNzValOffset, MPI_BOTTOM, 1, type,&status);
581 if (err != MPI_SUCCESS) {
585 throw std::logic_error(
"error reading nzval" );
588 MPI_Type_free(&type);
592 for( Int i = 1; i < numColLocal + 1; i++ ){
593 pspmat.colptrLocal[i] = pspmat.colptrLocal[i] - pspmat.colptrLocal[0] + 1;
595 pspmat.colptrLocal[0]=1;
599 MPI_File_close(&fin);
607 inline void ReadDistSparseMatrixFormatted (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
610 PushCallStack(
"ReadDistSparseMatrixFormatted");
614 Int mpirank; MPI_Comm_rank(comm, &mpirank);
615 Int mpisize; MPI_Comm_size(comm, &mpisize);
631 throw std::logic_error(
"File cannot be opened!" );
635 fin >> pspmat.size >> dummy ;
636 fin >> pspmat.nnz >> dummy;
641 MPI_Bcast(&pspmat.size, 1, MPI_INT, 0, comm);
642 MPI_Bcast(&pspmat.nnz, 1, MPI_INT, 0, comm);
646 IntNumVec colptr(pspmat.size+1);
648 Int* ptr = colptr.Data();
649 for( Int i = 0; i < pspmat.size+1; i++ )
653 MPI_Bcast(colptr.Data(), pspmat.size+1, MPI_INT, 0, comm);
656 IntNumVec numColLocalVec(mpisize);
657 Int numColLocal, numColFirst;
658 numColFirst = pspmat.size / mpisize;
659 SetValue( numColLocalVec, numColFirst );
660 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
661 numColLocal = numColLocalVec[mpirank];
663 pspmat.colptrLocal.Resize( numColLocal + 1 );
664 for( Int i = 0; i < numColLocal + 1; i++ ){
665 pspmat.colptrLocal[i] = colptr[mpirank * numColFirst+i] - colptr[mpirank * numColFirst] + 1;
669 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
671 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
672 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
679 for( Int ip = 0; ip < mpisize; ip++ ){
680 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
681 colptr[ip*numColFirst];
683 Int *ptr = buf.Data();
684 for( Int i = 0; i < numRead; i++ ){
688 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
689 MPI_Send(buf.Data(), numRead, MPI_INT, ip, 1, comm);
692 pspmat.rowindLocal = buf;
698 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
699 if( numRead != pspmat.nnzLocal ){
700 std::ostringstream msg;
701 msg <<
"The number of columns in row indices do not match." << std::endl
702 <<
"numRead = " << numRead << std::endl
703 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
707 throw std::logic_error( msg.str().c_str() );
710 pspmat.rowindLocal.Resize( numRead );
711 MPI_Recv( pspmat.rowindLocal.Data(), numRead, MPI_INT, 0, 1, comm, &mpistat );
723 for( Int ip = 0; ip < mpisize; ip++ ){
724 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
725 colptr[ip*numColFirst];
727 Real *ptr = buf.Data();
728 for( Int i = 0; i < numRead; i++ ){
732 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
733 MPI_Send(buf.Data(), numRead, MPI_DOUBLE, ip, 1, comm);
736 pspmat.nzvalLocal = buf;
742 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
743 if( numRead != pspmat.nnzLocal ){
744 std::ostringstream msg;
745 msg <<
"The number of columns in values do not match." << std::endl
746 <<
"numRead = " << numRead << std::endl
747 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
751 throw std::logic_error( msg.str().c_str() );
754 pspmat.nzvalLocal.Resize( numRead );
755 MPI_Recv( pspmat.nzvalLocal.Data(), numRead, MPI_DOUBLE, 0, 1, comm, &mpistat );
775 inline void ParaReadDistSparseMatrix (
const char* filename, DistSparseMatrix<Complex>& pspmat, MPI_Comm comm )
778 PushCallStack(
"ParaReadDistSparseMatrix");
782 Int mpirank; MPI_Comm_rank(comm, &mpirank);
783 Int mpisize; MPI_Comm_size(comm, &mpisize);
788 MPI_Datatype types[3];
791 int filemode = MPI_MODE_RDONLY | MPI_MODE_UNIQUE_OPEN;
799 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fin);
801 if (err != MPI_SUCCESS) {
805 throw std::logic_error(
"File cannot be opened!" );
811 err = MPI_File_read_at(fin, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
812 err = MPI_File_read_at(fin,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
819 MPI_Address(&pspmat.size, &disps[0]);
820 MPI_Address(&pspmat.nnz, &disps[1]);
823 MPI_Type_struct(2, lens, disps, types, &type);
824 MPI_Type_commit(&type);
828 MPI_Bcast(MPI_BOTTOM, 1, type, 0, comm);
830 MPI_Type_free(&type);
833 IntNumVec numColLocalVec(mpisize);
834 Int numColLocal, numColFirst;
835 numColFirst = pspmat.size / mpisize;
836 SetValue( numColLocalVec, numColFirst );
837 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
838 numColLocal = numColLocalVec[mpirank];
839 pspmat.colptrLocal.Resize( numColLocal + 1 );
843 MPI_Offset myColPtrOffset = (2 + ((mpirank==0)?0:1) )*
sizeof(
int) + (mpirank*numColFirst)*
sizeof(Int);
846 lens[0] = (mpirank==0)?1:0;
847 lens[1] = numColLocal + 1;
849 MPI_Address(&np1, &disps[0]);
850 MPI_Address(pspmat.colptrLocal.Data(), &disps[1]);
852 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
853 MPI_Type_commit(&type);
855 err= MPI_File_read_at_all(fin, myColPtrOffset, MPI_BOTTOM, 1, type, &status);
857 if (err != MPI_SUCCESS) {
861 throw std::logic_error(
"error reading colptr" );
863 MPI_Type_free(&type);
866 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
869 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
870 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
873 MPI_Offset myRowIdxOffset = (3 + ((mpirank==0)?0:1) )*
sizeof(
int) + (pspmat.size+1 + pspmat.colptrLocal[0]-1)*
sizeof(Int);
875 lens[0] = (mpirank==0)?1:0;
876 lens[1] = pspmat.nnzLocal;
878 MPI_Address(&np1, &disps[0]);
879 MPI_Address(pspmat.rowindLocal.Data(), &disps[1]);
881 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
882 MPI_Type_commit(&type);
884 err= MPI_File_read_at_all(fin, myRowIdxOffset, MPI_BOTTOM, 1, type,&status);
886 if (err != MPI_SUCCESS) {
890 throw std::logic_error(
"error reading rowind" );
892 MPI_Type_free(&type);
896 MPI_Offset myNzValOffset = (4 + ((mpirank==0)?0:1) )*
sizeof(
int) + (pspmat.size+1 + pspmat.nnz)*
sizeof(
int) + (pspmat.colptrLocal[0]-1)*
sizeof(Complex);
898 lens[0] = (mpirank==0)?1:0;
899 lens[1] = pspmat.nnzLocal;
901 MPI_Address(&np1, &disps[0]);
902 MPI_Address(pspmat.nzvalLocal.Data(), &disps[1]);
905 types[1] = MPI_DOUBLE_COMPLEX;
907 MPI_Type_create_struct(2, lens, disps, types, &type);
908 MPI_Type_commit(&type);
910 err = MPI_File_read_at_all(fin, myNzValOffset, MPI_BOTTOM, 1, type,&status);
912 if (err != MPI_SUCCESS) {
916 throw std::logic_error(
"error reading nzval" );
919 MPI_Type_free(&type);
923 for( Int i = 1; i < numColLocal + 1; i++ ){
924 pspmat.colptrLocal[i] = pspmat.colptrLocal[i] - pspmat.colptrLocal[0] + 1;
926 pspmat.colptrLocal[0]=1;
930 MPI_File_close(&fin);
938 inline void ParaWriteDistSparseMatrix (
const char* filename, DistSparseMatrix<Complex>& pspmat, MPI_Comm comm )
941 PushCallStack(
"ParaWriteDistSparseMatrix");
945 Int mpirank; MPI_Comm_rank(comm, &mpirank);
946 Int mpisize; MPI_Comm_size(comm, &mpisize);
952 int filemode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_UNIQUE_OPEN;
959 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fout);
961 if (err != MPI_SUCCESS) {
965 throw std::logic_error(
"File cannot be opened!" );
971 err = MPI_File_write_at(fout, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
972 err = MPI_File_write_at(fout,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
977 Int numColLocal = pspmat.colptrLocal.m()-1;
978 Int numColFirst = pspmat.size / mpisize;
979 IntNumVec colptrChunk(numColLocal+1);
982 MPI_Exscan(&pspmat.nnzLocal, &prev_nz, 1, MPI_INT, MPI_SUM, comm);
984 for( Int i = 0; i < numColLocal + 1; i++ ){
985 colptrChunk[i] = pspmat.colptrLocal[i] + prev_nz;
989 MPI_Datatype memtype, filetype;
992 MPI_Datatype types[6] = {MPI_INT,MPI_INT, MPI_INT,MPI_INT, MPI_INT,MPI_DOUBLE_COMPLEX};
995 blklens[0] = (mpirank==0)?1:0;
996 blklens[1] = numColLocal+1;
997 blklens[2] = (mpirank==0)?1:0;
998 blklens[3] = pspmat.nnzLocal;
999 blklens[4] = (mpirank==0)?1:0;
1000 blklens[5] = pspmat.nnzLocal;
1006 MPI_Offset myColPtrOffset, myRowIdxOffset, myNzValOffset;
1007 myColPtrOffset = 3*
sizeof(int) + (mpirank*numColFirst)*
sizeof(Int);
1008 myRowIdxOffset = 3*
sizeof(int) + (pspmat.size +1 + prev_nz)*
sizeof(Int);
1009 myNzValOffset = 4*
sizeof(int) + (pspmat.size +1 + pspmat.nnz)*
sizeof(Int)+ prev_nz*
sizeof(Complex);
1010 disps[0] = 2*
sizeof(int);
1011 disps[1] = myColPtrOffset;
1012 disps[2] = myRowIdxOffset;
1013 disps[3] =
sizeof(int)+myRowIdxOffset;
1014 disps[4] = myNzValOffset;
1015 disps[5] =
sizeof(int)+myNzValOffset;
1019 #if ( _DEBUGlevel_ >= 1 )
1022 tmp += sprintf(tmp,
"P%d ",mpirank);
1023 for(
int i = 0; i<6; ++i){
1025 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(Complex));
1027 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(
int));
1029 tmp += sprintf(tmp,
"\n");
1036 MPI_Type_create_struct(6, blklens, disps, types, &filetype);
1037 MPI_Type_commit(&filetype);
1040 Int np1 = pspmat.size+1;
1041 MPI_Address( (
void *)&np1, &disps[0]);
1042 MPI_Address(colptrChunk.Data(), &disps[1]);
1043 MPI_Address( (
void *)&pspmat.nnz, &disps[2]);
1044 MPI_Address((
void *)pspmat.rowindLocal.Data(), &disps[3]);
1045 MPI_Address( (
void *)&pspmat.nnz, &disps[4]);
1046 MPI_Address((
void *)pspmat.nzvalLocal.Data(), &disps[5]);
1048 MPI_Type_create_struct(6, blklens, disps, types, &memtype);
1049 MPI_Type_commit(&memtype);
1054 err = MPI_File_set_view(fout, 0, MPI_BYTE, filetype,
"native",MPI_INFO_NULL);
1060 err = MPI_File_write_all(fout, MPI_BOTTOM, 1, memtype, &status);
1062 MPI_Type_free(&filetype);
1063 MPI_Type_free(&memtype);
1069 MPI_Barrier( comm );
1071 MPI_File_close(&fout);
1081 inline void ReadDistSparseMatrixFormatted (
const char* filename, DistSparseMatrix<Complex>& pspmat, MPI_Comm comm )
1084 PushCallStack(
"ReadDistSparseMatrixFormatted");
1087 MPI_Barrier( comm );
1088 Int mpirank; MPI_Comm_rank(comm, &mpirank);
1089 Int mpisize; MPI_Comm_size(comm, &mpisize);
1105 throw std::logic_error(
"File cannot be opened!" );
1109 fin >> pspmat.size >> dummy;
1110 fin >> pspmat.nnz >> dummy;
1115 MPI_Bcast(&pspmat.size, 1, MPI_INT, 0, comm);
1116 MPI_Bcast(&pspmat.nnz, 1, MPI_INT, 0, comm);
1120 IntNumVec colptr(pspmat.size+1);
1122 Int* ptr = colptr.Data();
1123 for( Int i = 0; i < pspmat.size+1; i++ )
1127 MPI_Bcast(colptr.Data(), pspmat.size+1, MPI_INT, 0, comm);
1130 IntNumVec numColLocalVec(mpisize);
1131 Int numColLocal, numColFirst;
1132 numColFirst = pspmat.size / mpisize;
1133 SetValue( numColLocalVec, numColFirst );
1134 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
1135 numColLocal = numColLocalVec[mpirank];
1137 pspmat.colptrLocal.Resize( numColLocal + 1 );
1138 for( Int i = 0; i < numColLocal + 1; i++ ){
1139 pspmat.colptrLocal[i] = colptr[mpirank * numColFirst+i] - colptr[mpirank * numColFirst] + 1;
1143 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
1145 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
1146 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
1153 for( Int ip = 0; ip < mpisize; ip++ ){
1154 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
1155 colptr[ip*numColFirst];
1158 buf.Resize(numRead);
1159 Int *ptr = buf.Data();
1160 for( Int i = 0; i < numRead; i++ ){
1164 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
1165 MPI_Send(buf.Data(), numRead, MPI_INT, ip, 1, comm);
1168 pspmat.rowindLocal = buf;
1174 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
1175 if( numRead != pspmat.nnzLocal ){
1176 std::ostringstream msg;
1177 msg <<
"The number of columns in row indices do not match." << std::endl
1178 <<
"numRead = " << numRead << std::endl
1179 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
1183 throw std::logic_error( msg.str().c_str() );
1186 pspmat.rowindLocal.Resize( numRead );
1187 MPI_Recv( pspmat.rowindLocal.Data(), numRead, MPI_INT, 0, 1, comm, &mpistat );
1199 for( Int ip = 0; ip < mpisize; ip++ ){
1200 numRead = 2* (colptr[ip*numColFirst + numColLocalVec[ip]] -
1201 colptr[ip*numColFirst]);
1204 buf.Resize(numRead);
1208 ptr =
reinterpret_cast<Real*
>(pspmat.nzvalLocal.Data());
1212 for( Int i = 0; i < numRead; i++ ){
1217 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
1218 MPI_Send(buf.Data(), numRead, MPI_DOUBLE, ip, 1, comm);
1229 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
1230 if( numRead != 2*pspmat.nnzLocal ){
1231 std::ostringstream msg;
1232 msg <<
"The number of columns in values do not match." << std::endl
1233 <<
"numRead = " << numRead << std::endl
1234 <<
"2*nnzLocal = " << 2*pspmat.nnzLocal << std::endl;
1238 throw std::logic_error( msg.str().c_str() );
1241 pspmat.nzvalLocal.Resize( numRead/2 );
1242 MPI_Recv( reinterpret_cast<Real*>(pspmat.nzvalLocal.Data()),
1243 numRead, MPI_DOUBLE, 0, 1, comm, &mpistat );
1253 MPI_Barrier( comm );
1263 template<
typename T>
inline void GetDiagonal (
const DistSparseMatrix<T>& A, NumVec<T>& diag )
1266 PushCallStack(
"GetDiagonal");
1268 Int mpirank, mpisize;
1269 MPI_Comm_rank( A.comm, &mpirank );
1270 MPI_Comm_size( A.comm, &mpisize );
1272 NumVec<T> diagLocal( A.size );
1274 diag.Resize( A.size );
1277 Int numColFirst = A.size / mpisize;
1278 Int firstCol = mpirank * numColFirst;
1279 Int numColLocal = A.colptrLocal.m() - 1;
1281 #if ( _DEBUGlevel_ >= 1 )
1282 statusOFS <<
"numColFirst = " << numColFirst << std::endl;
1283 statusOFS <<
"A.nzvalLocal.size = " << A.nzvalLocal.m() << std::endl;
1284 statusOFS <<
"A.nnzLocal = " << A.nnzLocal << std::endl;
1288 for( Int j = 0; j < numColLocal; j++ ){
1289 Int jcol = j + firstCol + 1;
1290 Int numRow = A.colptrLocal(j+1) - A.colptrLocal(j);
1291 const Int* rowPtr = &A.rowindLocal( A.colptrLocal(j) - 1 );
1294 const Int* ptr = find( rowPtr, rowPtr + numRow, jcol );
1295 if( ptr == rowPtr + numRow ){
1296 std::ostringstream msg;
1297 msg <<
"Serious problem. Did not find the row corresponding to the column." << std::endl
1298 <<
"This happens when j = " << j <<
", jcol = " << jcol <<
", and the row indices are " << std::endl
1299 << IntNumVec( numRow,
false, const_cast<Int*>(rowPtr) ) << std::endl;
1303 throw std::logic_error( msg.str().c_str() );
1305 Int diagIdx = ptr - A.rowindLocal.Data();
1306 diagLocal( jcol - 1 ) = A.nzvalLocal( diagIdx );
1309 mpi::Allreduce( &diagLocal[0], &diag[0], A.size, MPI_SUM, A.comm );
1321 template <
typename T>
void CSCToCSR(
const DistSparseMatrix<T>& sparseA, DistSparseMatrix<T> & sparseB ){
1325 MPI_Comm_rank(sparseA.comm,&mpirank);
1328 MPI_Comm_size(sparseA.comm,&mpisize);
1330 Int numRowLocalFirst = sparseA.size / mpisize;
1331 Int firstRow = mpirank * numRowLocalFirst;
1332 Int numRowLocal = -1;
1335 sparseB.size = sparseA.size;
1336 sparseB.nnz = sparseA.nnz;
1337 sparseB.comm = sparseA.comm;
1341 IntNumVec rowindGlobal;
1342 IntNumVec colptrGlobal;
1345 colptrGlobal.Resize(sparseA.size+1);
1348 IntNumVec prevnz(mpisize);
1349 IntNumVec rcounts(mpisize);
1350 MPI_Allgather(&sparseA.nnzLocal, 1, MPI_INT, rcounts.Data(), 1, MPI_INT, sparseA.comm);
1353 for (Int i = 0; i < mpisize-1; ++i) { prevnz[i+1] = prevnz[i] + rcounts[i]; }
1356 for (Int i = 0; i < mpisize; ++i) { nnz += rcounts[i]; }
1357 rowindGlobal.Resize(nnz);
1359 MPI_Allgatherv(sparseA.rowindLocal.Data(), sparseA.nnzLocal, MPI_INT, rowindGlobal.Data(),rcounts.Data(), prevnz.Data(), MPI_INT, sparseA.comm);
1363 Int numColFirst = std::max(1,sparseA.size / mpisize);
1365 rcounts[mpisize-1] = sparseA.size - numColFirst * (mpisize-1);
1367 IntNumVec rdispls(mpisize);
1369 for (Int i = 0; i < mpisize-1; ++i) { rdispls[i+1] = rdispls[i] + rcounts[i]; }
1371 MPI_Allgatherv(sparseA.colptrLocal.Data(), sparseA.colptrLocal.m()-1, MPI_INT, colptrGlobal.Data(),
1372 rcounts.Data(), rdispls.Data(), MPI_INT, sparseA.comm);
1375 for (Int p = 1; p < mpisize; p++) {
1376 Int idx = rdispls[p];
1377 for (Int j = 0; j < rcounts[p]; ++j) colptrGlobal[idx++] += prevnz[p];
1379 colptrGlobal(sparseA.size)= nnz+1;
1384 IntNumVec rowptrGlobal;
1385 IntNumVec colindGlobal;
1390 colindGlobal.Resize(nnz);
1391 rowptrGlobal.Resize(sparseA.size+1);
1392 IntNumVec row_nnz(sparseA.size);
1395 for (i = 0; i < nnz; i++) {
1396 Int k = rowindGlobal[i];
1401 for (i = 1; i <= sparseA.size; i++)
1403 rowptrGlobal[i] = rowptrGlobal[i-1] + row_nnz[i-1];
1412 for (j = 0; j < colptrGlobal.m()-1; j++)
1417 nnz_col = colptrGlobal[j+1] - colptrGlobal[j];
1419 for (k = colptrGlobal[j]; k < colptrGlobal[j+1]; k++)
1421 Int i = rowindGlobal[ k - 1 ];
1422 Int h = rowptrGlobal[i-1] + row_nnz[i-1];
1425 colindGlobal[ h - 1 ] = j+1;
1451 std::vector<Int > numRowVec(mpisize,numRowLocalFirst);
1452 numRowVec[mpisize-1] = sparseA.size - (mpisize-1)*numRowLocalFirst;
1454 numRowLocal = numRowVec[mpirank];
1455 Int myFirstCol = mpirank*numRowLocalFirst+1;
1456 Int myLastCol = myFirstCol + numRowLocal -1;
1458 sparseB.colptrLocal.Resize(numRowLocal+1);
1459 Int * rowptrLocal = &sparseB.colptrLocal[0];
1462 std::copy(&rowptrGlobal[myFirstCol-1],
1463 &rowptrGlobal[myLastCol]+1,
1466 nnzLocal = rowptrLocal[numRowLocal] - rowptrLocal[0];
1468 sparseB.nnzLocal = nnzLocal;
1470 sparseB.rowindLocal.Resize(nnzLocal);
1471 Int * colindLocal = &sparseB.rowindLocal[0];
1473 sparseB.nzvalLocal.Resize(nnzLocal);
1474 T * nzvalLocal = &sparseB.nzvalLocal[0];
1477 std::copy(&colindGlobal[rowptrLocal[0]-1],
1478 &colindGlobal[rowptrLocal[0]-1]+nnzLocal,
1482 for( Int i = 1; i < numRowLocal + 1; i++ ){
1483 rowptrLocal[i] = rowptrLocal[i] - rowptrLocal[0] + 1;
1507 std::vector<Int> * row_nnz =
new std::vector<Int>(numRowLocal,0);
1509 for(
int p =0; p<mpisize;p++){
1510 std::vector< char > send_buffer;
1511 std::vector< char > recv_buffer;
1512 std::vector<int> displs(mpisize+1,0);
1513 std::vector<int> bufsizes(mpisize,0);
1516 Int firstCol = p*numRowLocalFirst+1;
1517 Int lastCol = firstCol + numRowVec[p]-1;
1518 for(Int col = 1; col<colptrGlobal.m();++col){
1519 if(col>= firstCol && col<= lastCol){
1520 Int colbeg = colptrGlobal[col-1];
1521 Int colend = colptrGlobal[col]-1;
1522 for(Int i=colbeg;i<=colend;++i){
1523 Int row = rowindGlobal[i-1];
1525 Int p_dest = min(mpisize-1,(row-1)/(numRowLocalFirst));
1526 bufsizes[p_dest]+=
sizeof(T);
1529 else if(col>lastCol){
1535 std::partial_sum(bufsizes.begin(),bufsizes.end(),displs.begin()+1);
1538 std::vector<int> bufpos(mpisize,0);
1541 Int send_buffer_size = displs[mpisize];
1542 send_buffer.resize(displs[mpisize]);
1545 for(Int j = 1; j<sparseA.colptrLocal.m();++j){
1546 Int gCol = mpirank*numRowLocalFirst + j;
1547 Int colbeg = sparseA.colptrLocal[j-1];
1548 Int colend = sparseA.colptrLocal[j]-1;
1549 for(Int i=colbeg;i<=colend;++i){
1550 Int row = sparseA.rowindLocal[i-1];
1552 Int p_dest = min(mpisize-1,(row-1)/(numRowLocalFirst));
1553 Int p_displs = displs[p_dest];
1554 Int p_bufpos = bufpos[p_dest];
1555 *((T *)&send_buffer.at( displs[p_dest] + bufpos[p_dest] )) = sparseA.nzvalLocal[i-1];
1557 bufpos[p_dest]+=
sizeof(T);
1564 Int recv_buffer_size = bufsizes[mpirank];
1565 recv_buffer.resize(bufsizes[mpirank]);
1568 MPI_Scatterv(&send_buffer[0], &bufsizes[0], &displs[0], MPI_BYTE, &recv_buffer[0], bufsizes[mpirank], MPI_BYTE, p, sparseA.comm);
1573 for(Int col = 1; col<colptrGlobal.m();++col){
1574 if(col>= firstCol && col<= lastCol){
1575 Int colbeg = colptrGlobal[col-1];
1576 Int colend = colptrGlobal[col]-1;
1577 for(Int i=colbeg;i<=colend;++i){
1578 Int row = rowindGlobal[i-1];
1579 Int p_dest = min(mpisize-1,(row-1)/(numRowLocalFirst));
1580 if(p_dest==mpirank){
1582 Int local_row = row - mpirank*numRowLocalFirst;
1583 Int h = rowptrLocal[local_row-1] + row_nnz->at(local_row-1);
1584 *((T*)&nzvalLocal[h-1]) = *((T*)&recv_buffer.at(recv_pos));
1586 row_nnz->at(local_row-1)++;
1588 recv_pos+=
sizeof(T);
1592 else if(col>lastCol){
1605 #endif //_PEXSI_UTILITY_IMPL_HPP_
void SetValue(NumMat< F > &M, F val)
SetValue sets a numerical matrix to a constant val.
Definition: NumMat_impl.hpp:171