46 #ifndef _PEXSI_UTILITY_IMPL_HPP_
47 #define _PEXSI_UTILITY_IMPL_HPP_
65 inline void ReadSparseMatrix (
const char* filename, SparseMatrix<Real>& spmat )
71 std::istringstream iss;
72 SharedRead( filename, iss );
73 deserialize( spmat.size, iss, NO_MASK );
74 deserialize( spmat.nnz, iss, NO_MASK );
75 deserialize( spmat.colptr, iss, NO_MASK );
76 deserialize( spmat.rowind, iss, NO_MASK );
77 deserialize( spmat.nzval, iss, NO_MASK );
82 ifstream fin(filename);
83 fin >> spmat.size >> spmat.nnz;
85 spmat.colptr.Resize( spmat.size+1 );
86 spmat.rowind.Resize( spmat.nnz );
87 spmat.nzval.Resize ( spmat.nnz );
89 for( Int i = 0; i < spmat.size + 1; i++ ){
90 fin >> spmat.colptr(i);
93 for( Int i = 0; i < spmat.nnz; i++ ){
94 fin >> spmat.rowind(i);
97 for( Int i = 0; i < spmat.nnz; i++ ){
98 fin >> spmat.nzval(i);
108 inline void ReadDistSparseMatrix (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
112 Int mpirank; MPI_Comm_rank(comm, &mpirank);
113 Int mpisize; MPI_Comm_size(comm, &mpisize);
124 ErrorHandling(
"File cannot be opened!" );
126 fin.read((
char*)&pspmat.size,
sizeof(Int));
127 fin.read((
char*)&pspmat.nnz,
sizeof(Int));
132 MPI_Bcast(&pspmat.size, 1, MPI_INT, 0, comm);
133 MPI_Bcast(&pspmat.nnz, 1, MPI_INT, 0, comm);
136 IntNumVec colptr(pspmat.size+1);
139 fin.read((
char*)&tmp,
sizeof(Int));
141 if( tmp != pspmat.size+1 ){
142 ErrorHandling(
"colptr is not of the right size." );
145 fin.read((
char*)colptr.Data(),
sizeof(Int)*tmp);
149 MPI_Bcast(colptr.Data(), pspmat.size+1, MPI_INT, 0, comm);
152 IntNumVec numColLocalVec(mpisize);
153 Int numColLocal, numColFirst;
154 numColFirst = pspmat.size / mpisize;
155 SetValue( numColLocalVec, numColFirst );
156 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
157 numColLocal = numColLocalVec[mpirank];
159 pspmat.colptrLocal.Resize( numColLocal + 1 );
160 for( Int i = 0; i < numColLocal + 1; i++ ){
161 pspmat.colptrLocal[i] = colptr[mpirank * numColFirst+i] - colptr[mpirank * numColFirst] + 1;
165 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
167 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
168 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
173 fin.read((
char*)&tmp,
sizeof(Int));
175 if( tmp != pspmat.nnz ){
176 std::ostringstream msg;
178 <<
"The number of nonzeros in row indices do not match." << std::endl
179 <<
"nnz = " << pspmat.nnz << std::endl
180 <<
"size of row indices = " << tmp << std::endl;
181 ErrorHandling( msg.str().c_str() );
185 for( Int ip = 0; ip < mpisize; ip++ ){
186 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
187 colptr[ip*numColFirst];
189 fin.read( (
char*)buf.Data(), numRead*
sizeof(Int) );
192 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
193 MPI_Send(buf.Data(), numRead, MPI_INT, ip, 1, comm);
196 pspmat.rowindLocal = buf;
202 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
203 if( numRead != pspmat.nnzLocal ){
204 std::ostringstream msg;
205 msg <<
"The number of columns in row indices do not match." << std::endl
206 <<
"numRead = " << numRead << std::endl
207 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
208 ErrorHandling( msg.str().c_str() );
211 pspmat.rowindLocal.Resize( numRead );
212 MPI_Recv( pspmat.rowindLocal.Data(), numRead, MPI_INT, 0, 1, comm, &mpistat );
218 fin.read((
char*)&tmp,
sizeof(Int));
220 if( tmp != pspmat.nnz ){
221 std::ostringstream msg;
223 <<
"The number of nonzeros in values do not match." << std::endl
224 <<
"nnz = " << pspmat.nnz << std::endl
225 <<
"size of values = " << tmp << std::endl;
226 ErrorHandling( msg.str().c_str() );
230 for( Int ip = 0; ip < mpisize; ip++ ){
231 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
232 colptr[ip*numColFirst];
234 fin.read( (
char*)buf.Data(), numRead*
sizeof(Real) );
237 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
238 MPI_Send(buf.Data(), numRead, MPI_DOUBLE, ip, 1, comm);
241 pspmat.nzvalLocal = buf;
247 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
248 if( numRead != pspmat.nnzLocal ){
249 std::ostringstream msg;
250 msg <<
"The number of columns in values do not match." << std::endl
251 <<
"numRead = " << numRead << std::endl
252 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
253 ErrorHandling( msg.str().c_str() );
256 pspmat.nzvalLocal.Resize( numRead );
257 MPI_Recv( pspmat.nzvalLocal.Data(), numRead, MPI_DOUBLE, 0, 1, comm, &mpistat );
273 inline void ParaWriteDistSparseMatrix (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
277 Int mpirank; MPI_Comm_rank(comm, &mpirank);
278 Int mpisize; MPI_Comm_size(comm, &mpisize);
284 int filemode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_UNIQUE_OPEN;
291 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fout);
293 if (err != MPI_SUCCESS) {
294 ErrorHandling(
"File cannot be opened!" );
300 err = MPI_File_write_at(fout, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
301 err = MPI_File_write_at(fout,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
306 Int numColLocal = pspmat.colptrLocal.m()-1;
307 Int numColFirst = pspmat.size / mpisize;
308 IntNumVec colptrChunk(numColLocal+1);
311 MPI_Exscan(&pspmat.nnzLocal, &prev_nz, 1, MPI_INT, MPI_SUM, comm);
313 for( Int i = 0; i < numColLocal + 1; i++ ){
314 colptrChunk[i] = pspmat.colptrLocal[i] + prev_nz;
318 MPI_Datatype memtype, filetype;
321 MPI_Datatype types[6] = {MPI_INT,MPI_INT, MPI_INT,MPI_INT, MPI_INT,MPI_DOUBLE};
324 blklens[0] = (mpirank==0)?1:0;
325 blklens[1] = numColLocal+1;
326 blklens[2] = (mpirank==0)?1:0;
327 blklens[3] = pspmat.nnzLocal;
328 blklens[4] = (mpirank==0)?1:0;
329 blklens[5] = pspmat.nnzLocal;
335 MPI_Offset myColPtrOffset, myRowIdxOffset, myNzValOffset;
336 myColPtrOffset = 3*
sizeof(int) + (mpirank*numColFirst)*
sizeof(Int);
337 myRowIdxOffset = 3*
sizeof(int) + (pspmat.size +1 + prev_nz)*
sizeof(Int);
338 myNzValOffset = 4*
sizeof(int) + (pspmat.size +1 + pspmat.nnz)*
sizeof(Int)+ prev_nz*
sizeof(Real);
339 disps[0] = 2*
sizeof(int);
340 disps[1] = myColPtrOffset;
341 disps[2] = myRowIdxOffset;
342 disps[3] =
sizeof(int)+myRowIdxOffset;
343 disps[4] = myNzValOffset;
344 disps[5] =
sizeof(int)+myNzValOffset;
348 #if ( _DEBUGlevel_ >= 1 )
351 tmp += sprintf(tmp,
"P%d ",mpirank);
352 for(
int i = 0; i<6; ++i){
354 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(
double));
356 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(
int));
358 tmp += sprintf(tmp,
"\n");
365 MPI_Type_create_struct(6, blklens, disps, types, &filetype);
366 MPI_Type_commit(&filetype);
369 Int np1 = pspmat.size+1;
370 MPI_Address( (
void *)&np1, &disps[0]);
371 MPI_Address(colptrChunk.Data(), &disps[1]);
372 MPI_Address( (
void *)&pspmat.nnz, &disps[2]);
373 MPI_Address((
void *)pspmat.rowindLocal.Data(), &disps[3]);
374 MPI_Address( (
void *)&pspmat.nnz, &disps[4]);
375 MPI_Address((
void *)pspmat.nzvalLocal.Data(), &disps[5]);
377 MPI_Type_create_struct(6, blklens, disps, types, &memtype);
378 MPI_Type_commit(&memtype);
383 err = MPI_File_set_view(fout, 0, MPI_BYTE, filetype,
"native",MPI_INFO_NULL);
389 err = MPI_File_write_all(fout, MPI_BOTTOM, 1, memtype, &status);
391 MPI_Type_free(&filetype);
392 MPI_Type_free(&memtype);
400 MPI_File_close(&fout);
405 inline void ParaReadDistSparseMatrix (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
409 Int mpirank; MPI_Comm_rank(comm, &mpirank);
410 Int mpisize; MPI_Comm_size(comm, &mpisize);
415 MPI_Datatype types[3];
418 int filemode = MPI_MODE_RDONLY | MPI_MODE_UNIQUE_OPEN;
426 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fin);
428 if (err != MPI_SUCCESS) {
429 ErrorHandling(
"File cannot be opened!" );
435 err = MPI_File_read_at(fin, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
436 err = MPI_File_read_at(fin,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
443 MPI_Address(&pspmat.size, &disps[0]);
444 MPI_Address(&pspmat.nnz, &disps[1]);
447 MPI_Type_struct(2, lens, disps, types, &type);
448 MPI_Type_commit(&type);
452 MPI_Bcast(MPI_BOTTOM, 1, type, 0, comm);
454 MPI_Type_free(&type);
457 IntNumVec numColLocalVec(mpisize);
458 Int numColLocal, numColFirst;
459 numColFirst = pspmat.size / mpisize;
460 SetValue( numColLocalVec, numColFirst );
461 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
462 numColLocal = numColLocalVec[mpirank];
463 pspmat.colptrLocal.Resize( numColLocal + 1 );
467 MPI_Offset myColPtrOffset = (2 + ((mpirank==0)?0:1) )*
sizeof(
int) + (mpirank*numColFirst)*
sizeof(Int);
470 lens[0] = (mpirank==0)?1:0;
471 lens[1] = numColLocal + 1;
473 MPI_Address(&np1, &disps[0]);
474 MPI_Address(pspmat.colptrLocal.Data(), &disps[1]);
476 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
477 MPI_Type_commit(&type);
479 err= MPI_File_read_at_all(fin, myColPtrOffset, MPI_BOTTOM, 1, type, &status);
481 if (err != MPI_SUCCESS) {
482 ErrorHandling(
"error reading colptr" );
484 MPI_Type_free(&type);
487 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
490 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
491 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
494 MPI_Offset myRowIdxOffset = (3 + ((mpirank==0)?0:1) )*
sizeof(
int) + (pspmat.size+1 + (pspmat.colptrLocal[0]-1))*
sizeof(int);
496 lens[0] = (mpirank==0)?1:0;
497 lens[1] = pspmat.nnzLocal;
499 MPI_Address(&np1, &disps[0]);
500 MPI_Address(pspmat.rowindLocal.Data(), &disps[1]);
502 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
503 MPI_Type_commit(&type);
505 err= MPI_File_read_at_all(fin, myRowIdxOffset, MPI_BOTTOM, 1, type,&status);
507 if (err != MPI_SUCCESS) {
508 ErrorHandling(
"error reading rowind" );
510 MPI_Type_free(&type);
532 MPI_Offset myNzValOffset = (4 )*
sizeof(
int) + (pspmat.size+1 + pspmat.nnz)*
sizeof(
int) + (pspmat.colptrLocal[0]-1)*
sizeof(
double);
533 err = MPI_File_read_at(fin, myNzValOffset,(
char*)&np1, 1, MPI_INT, &status);
536 MPI_Offset myNzValOffset = (5 )*
sizeof(
int) + (pspmat.size+1 + pspmat.nnz)*
sizeof(
int) + (pspmat.colptrLocal[0]-1)*
sizeof(
double);
537 err = MPI_File_read_at_all(fin, myNzValOffset, pspmat.nzvalLocal.Data(), pspmat.nnzLocal, MPI_DOUBLE,&status);
541 if (err != MPI_SUCCESS) {
542 ErrorHandling(
"error reading nzval" );
548 for( Int i = 1; i < numColLocal + 1; i++ ){
549 pspmat.colptrLocal[i] = pspmat.colptrLocal[i] - pspmat.colptrLocal[0] + 1;
551 pspmat.colptrLocal[0]=1;
555 MPI_File_close(&fin);
560 inline void ReadDistSparseMatrixFormatted (
const char* filename, DistSparseMatrix<Real>& pspmat, MPI_Comm comm )
564 Int mpirank; MPI_Comm_rank(comm, &mpirank);
565 Int mpisize; MPI_Comm_size(comm, &mpisize);
578 ErrorHandling(
"File cannot be opened!" );
582 fin >> pspmat.size >> dummy ;
583 fin >> pspmat.nnz >> dummy;
588 MPI_Bcast(&pspmat.size, 1, MPI_INT, 0, comm);
589 MPI_Bcast(&pspmat.nnz, 1, MPI_INT, 0, comm);
593 IntNumVec colptr(pspmat.size+1);
595 Int* ptr = colptr.Data();
596 for( Int i = 0; i < pspmat.size+1; i++ )
600 MPI_Bcast(colptr.Data(), pspmat.size+1, MPI_INT, 0, comm);
603 IntNumVec numColLocalVec(mpisize);
604 Int numColLocal, numColFirst;
605 numColFirst = pspmat.size / mpisize;
606 SetValue( numColLocalVec, numColFirst );
607 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
608 numColLocal = numColLocalVec[mpirank];
610 pspmat.colptrLocal.Resize( numColLocal + 1 );
611 for( Int i = 0; i < numColLocal + 1; i++ ){
612 pspmat.colptrLocal[i] = colptr[mpirank * numColFirst+i] - colptr[mpirank * numColFirst] + 1;
616 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
618 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
619 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
626 for( Int ip = 0; ip < mpisize; ip++ ){
627 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
628 colptr[ip*numColFirst];
630 Int *ptr = buf.Data();
631 for( Int i = 0; i < numRead; i++ ){
635 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
636 MPI_Send(buf.Data(), numRead, MPI_INT, ip, 1, comm);
639 pspmat.rowindLocal = buf;
645 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
646 if( numRead != pspmat.nnzLocal ){
647 std::ostringstream msg;
648 msg <<
"The number of columns in row indices do not match." << std::endl
649 <<
"numRead = " << numRead << std::endl
650 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
651 ErrorHandling( msg.str().c_str() );
654 pspmat.rowindLocal.Resize( numRead );
655 MPI_Recv( pspmat.rowindLocal.Data(), numRead, MPI_INT, 0, 1, comm, &mpistat );
667 for( Int ip = 0; ip < mpisize; ip++ ){
668 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
669 colptr[ip*numColFirst];
671 Real *ptr = buf.Data();
672 for( Int i = 0; i < numRead; i++ ){
676 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
677 MPI_Send(buf.Data(), numRead, MPI_DOUBLE, ip, 1, comm);
680 pspmat.nzvalLocal = buf;
686 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
687 if( numRead != pspmat.nnzLocal ){
688 std::ostringstream msg;
689 msg <<
"The number of columns in values do not match." << std::endl
690 <<
"numRead = " << numRead << std::endl
691 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
692 ErrorHandling( msg.str().c_str() );
695 pspmat.nzvalLocal.Resize( numRead );
696 MPI_Recv( pspmat.nzvalLocal.Data(), numRead, MPI_DOUBLE, 0, 1, comm, &mpistat );
713 inline void ParaReadDistSparseMatrix (
const char* filename, DistSparseMatrix<Complex>& pspmat, MPI_Comm comm )
717 Int mpirank; MPI_Comm_rank(comm, &mpirank);
718 Int mpisize; MPI_Comm_size(comm, &mpisize);
723 MPI_Datatype types[3];
726 int filemode = MPI_MODE_RDONLY | MPI_MODE_UNIQUE_OPEN;
734 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fin);
736 if (err != MPI_SUCCESS) {
737 ErrorHandling(
"File cannot be opened!" );
743 err = MPI_File_read_at(fin, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
744 err = MPI_File_read_at(fin,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
751 MPI_Address(&pspmat.size, &disps[0]);
752 MPI_Address(&pspmat.nnz, &disps[1]);
755 MPI_Type_struct(2, lens, disps, types, &type);
756 MPI_Type_commit(&type);
760 MPI_Bcast(MPI_BOTTOM, 1, type, 0, comm);
762 MPI_Type_free(&type);
765 IntNumVec numColLocalVec(mpisize);
766 Int numColLocal, numColFirst;
767 numColFirst = pspmat.size / mpisize;
768 SetValue( numColLocalVec, numColFirst );
769 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
770 numColLocal = numColLocalVec[mpirank];
771 pspmat.colptrLocal.Resize( numColLocal + 1 );
775 MPI_Offset myColPtrOffset = (2 + ((mpirank==0)?0:1) )*
sizeof(
int) + (mpirank*numColFirst)*
sizeof(Int);
778 lens[0] = (mpirank==0)?1:0;
779 lens[1] = numColLocal + 1;
781 MPI_Address(&np1, &disps[0]);
782 MPI_Address(pspmat.colptrLocal.Data(), &disps[1]);
784 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
785 MPI_Type_commit(&type);
787 err= MPI_File_read_at_all(fin, myColPtrOffset, MPI_BOTTOM, 1, type, &status);
789 if (err != MPI_SUCCESS) {
790 ErrorHandling(
"error reading colptr" );
792 MPI_Type_free(&type);
795 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
798 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
799 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
802 MPI_Offset myRowIdxOffset = (3 + ((mpirank==0)?0:1) )*
sizeof(
int) + (pspmat.size+1 + pspmat.colptrLocal[0]-1)*
sizeof(Int);
804 lens[0] = (mpirank==0)?1:0;
805 lens[1] = pspmat.nnzLocal;
807 MPI_Address(&np1, &disps[0]);
808 MPI_Address(pspmat.rowindLocal.Data(), &disps[1]);
811 MPI_Type_hindexed(2, lens, disps, MPI_INT, &type);
812 MPI_Type_commit(&type);
814 err= MPI_File_read_at_all(fin, myRowIdxOffset, MPI_BOTTOM, 1, type,&status);
816 if (err != MPI_SUCCESS) {
817 ErrorHandling(
"error reading rowind" );
819 MPI_Type_free(&type);
841 MPI_Offset myNzValOffset = (4 )*
sizeof(
int) + (pspmat.size+1 + pspmat.nnz)*
sizeof(
int) + (pspmat.colptrLocal[0]-1)*
sizeof(Complex);
842 err = MPI_File_read_at(fin, myNzValOffset,(
char*)&np1, 1, MPI_INT, &status);
845 MPI_Offset myNzValOffset = (5 )*
sizeof(
int) + (pspmat.size+1 + pspmat.nnz)*
sizeof(
int) + (pspmat.colptrLocal[0]-1)*
sizeof(Complex);
846 err = MPI_File_read_at_all(fin, myNzValOffset, pspmat.nzvalLocal.Data(), pspmat.nnzLocal, MPI_DOUBLE_COMPLEX,&status);
850 if (err != MPI_SUCCESS) {
851 ErrorHandling(
"error reading nzval" );
857 for( Int i = 1; i < numColLocal + 1; i++ ){
858 pspmat.colptrLocal[i] = pspmat.colptrLocal[i] - pspmat.colptrLocal[0] + 1;
860 pspmat.colptrLocal[0]=1;
864 MPI_File_close(&fin);
869 inline void ParaWriteDistSparseMatrix (
const char* filename, DistSparseMatrix<Complex>& pspmat, MPI_Comm comm )
873 Int mpirank; MPI_Comm_rank(comm, &mpirank);
874 Int mpisize; MPI_Comm_size(comm, &mpisize);
880 int filemode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_UNIQUE_OPEN;
887 err = MPI_File_open(comm,(
char*) filename, filemode, MPI_INFO_NULL, &fout);
889 if (err != MPI_SUCCESS) {
890 ErrorHandling(
"File cannot be opened!" );
896 err = MPI_File_write_at(fout, 0,(
char*)&pspmat.size, 1, MPI_INT, &status);
897 err = MPI_File_write_at(fout,
sizeof(Int),(
char*)&pspmat.nnz, 1, MPI_INT, &status);
902 Int numColLocal = pspmat.colptrLocal.m()-1;
903 Int numColFirst = pspmat.size / mpisize;
904 IntNumVec colptrChunk(numColLocal+1);
907 MPI_Exscan(&pspmat.nnzLocal, &prev_nz, 1, MPI_INT, MPI_SUM, comm);
909 for( Int i = 0; i < numColLocal + 1; i++ ){
910 colptrChunk[i] = pspmat.colptrLocal[i] + prev_nz;
914 MPI_Datatype memtype, filetype;
917 MPI_Datatype types[6] = {MPI_INT,MPI_INT, MPI_INT,MPI_INT, MPI_INT,MPI_DOUBLE_COMPLEX};
920 blklens[0] = (mpirank==0)?1:0;
921 blklens[1] = numColLocal+1;
922 blklens[2] = (mpirank==0)?1:0;
923 blklens[3] = pspmat.nnzLocal;
924 blklens[4] = (mpirank==0)?1:0;
925 blklens[5] = pspmat.nnzLocal;
931 MPI_Offset myColPtrOffset, myRowIdxOffset, myNzValOffset;
932 myColPtrOffset = 3*
sizeof(int) + (mpirank*numColFirst)*
sizeof(Int);
933 myRowIdxOffset = 3*
sizeof(int) + (pspmat.size +1 + prev_nz)*
sizeof(Int);
934 myNzValOffset = 4*
sizeof(int) + (pspmat.size +1 + pspmat.nnz)*
sizeof(Int)+ prev_nz*
sizeof(Complex);
935 disps[0] = 2*
sizeof(int);
936 disps[1] = myColPtrOffset;
937 disps[2] = myRowIdxOffset;
938 disps[3] =
sizeof(int)+myRowIdxOffset;
939 disps[4] = myNzValOffset;
940 disps[5] =
sizeof(int)+myNzValOffset;
944 #if ( _DEBUGlevel_ >= 1 )
947 tmp += sprintf(tmp,
"P%d ",mpirank);
948 for(
int i = 0; i<6; ++i){
950 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(Complex));
952 tmp += sprintf(tmp,
"%d [%d - %d] | ",i,disps[i],disps[i]+blklens[i]*
sizeof(
int));
954 tmp += sprintf(tmp,
"\n");
961 MPI_Type_create_struct(6, blklens, disps, types, &filetype);
962 MPI_Type_commit(&filetype);
965 Int np1 = pspmat.size+1;
966 MPI_Address( (
void *)&np1, &disps[0]);
967 MPI_Address(colptrChunk.Data(), &disps[1]);
968 MPI_Address( (
void *)&pspmat.nnz, &disps[2]);
969 MPI_Address((
void *)pspmat.rowindLocal.Data(), &disps[3]);
970 MPI_Address( (
void *)&pspmat.nnz, &disps[4]);
971 MPI_Address((
void *)pspmat.nzvalLocal.Data(), &disps[5]);
973 MPI_Type_create_struct(6, blklens, disps, types, &memtype);
974 MPI_Type_commit(&memtype);
979 err = MPI_File_set_view(fout, 0, MPI_BYTE, filetype,
"native",MPI_INFO_NULL);
985 err = MPI_File_write_all(fout, MPI_BOTTOM, 1, memtype, &status);
987 MPI_Type_free(&filetype);
988 MPI_Type_free(&memtype);
996 MPI_File_close(&fout);
1003 inline void ReadDistSparseMatrixFormatted (
const char* filename, DistSparseMatrix<Complex>& pspmat, MPI_Comm comm )
1006 MPI_Barrier( comm );
1007 Int mpirank; MPI_Comm_rank(comm, &mpirank);
1008 Int mpisize; MPI_Comm_size(comm, &mpisize);
1021 ErrorHandling(
"File cannot be opened!" );
1025 fin >> pspmat.size >> dummy;
1026 fin >> pspmat.nnz >> dummy;
1031 MPI_Bcast(&pspmat.size, 1, MPI_INT, 0, comm);
1032 MPI_Bcast(&pspmat.nnz, 1, MPI_INT, 0, comm);
1036 IntNumVec colptr(pspmat.size+1);
1038 Int* ptr = colptr.Data();
1039 for( Int i = 0; i < pspmat.size+1; i++ )
1043 MPI_Bcast(colptr.Data(), pspmat.size+1, MPI_INT, 0, comm);
1046 IntNumVec numColLocalVec(mpisize);
1047 Int numColLocal, numColFirst;
1048 numColFirst = pspmat.size / mpisize;
1049 SetValue( numColLocalVec, numColFirst );
1050 numColLocalVec[mpisize-1] = pspmat.size - numColFirst * (mpisize-1);
1051 numColLocal = numColLocalVec[mpirank];
1053 pspmat.colptrLocal.Resize( numColLocal + 1 );
1054 for( Int i = 0; i < numColLocal + 1; i++ ){
1055 pspmat.colptrLocal[i] = colptr[mpirank * numColFirst+i] - colptr[mpirank * numColFirst] + 1;
1059 pspmat.nnzLocal = pspmat.colptrLocal[numColLocal] - pspmat.colptrLocal[0];
1061 pspmat.rowindLocal.Resize( pspmat.nnzLocal );
1062 pspmat.nzvalLocal.Resize ( pspmat.nnzLocal );
1069 for( Int ip = 0; ip < mpisize; ip++ ){
1070 numRead = colptr[ip*numColFirst + numColLocalVec[ip]] -
1071 colptr[ip*numColFirst];
1074 buf.Resize(numRead);
1075 Int *ptr = buf.Data();
1076 for( Int i = 0; i < numRead; i++ ){
1080 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
1081 MPI_Send(buf.Data(), numRead, MPI_INT, ip, 1, comm);
1084 pspmat.rowindLocal = buf;
1090 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
1091 if( numRead != pspmat.nnzLocal ){
1092 std::ostringstream msg;
1093 msg <<
"The number of columns in row indices do not match." << std::endl
1094 <<
"numRead = " << numRead << std::endl
1095 <<
"nnzLocal = " << pspmat.nnzLocal << std::endl;
1096 ErrorHandling( msg.str().c_str() );
1099 pspmat.rowindLocal.Resize( numRead );
1100 MPI_Recv( pspmat.rowindLocal.Data(), numRead, MPI_INT, 0, 1, comm, &mpistat );
1112 for( Int ip = 0; ip < mpisize; ip++ ){
1113 numRead = 2* (colptr[ip*numColFirst + numColLocalVec[ip]] -
1114 colptr[ip*numColFirst]);
1117 buf.Resize(numRead);
1121 ptr =
reinterpret_cast<Real*
>(pspmat.nzvalLocal.Data());
1125 for( Int i = 0; i < numRead; i++ ){
1130 MPI_Send(&numRead, 1, MPI_INT, ip, 0, comm);
1131 MPI_Send(buf.Data(), numRead, MPI_DOUBLE, ip, 1, comm);
1142 MPI_Recv(&numRead, 1, MPI_INT, 0, 0, comm, &mpistat);
1143 if( numRead != 2*pspmat.nnzLocal ){
1144 std::ostringstream msg;
1145 msg <<
"The number of columns in values do not match." << std::endl
1146 <<
"numRead = " << numRead << std::endl
1147 <<
"2*nnzLocal = " << 2*pspmat.nnzLocal << std::endl;
1148 ErrorHandling( msg.str().c_str() );
1151 pspmat.nzvalLocal.Resize( numRead/2 );
1152 MPI_Recv( reinterpret_cast<Real*>(pspmat.nzvalLocal.Data()),
1153 numRead, MPI_DOUBLE, 0, 1, comm, &mpistat );
1163 MPI_Barrier( comm );
1170 template<
typename T>
inline void GetDiagonal (
const DistSparseMatrix<T>& A, NumVec<T>& diag )
1172 Int mpirank, mpisize;
1173 MPI_Comm_rank( A.comm, &mpirank );
1174 MPI_Comm_size( A.comm, &mpisize );
1176 NumVec<T> diagLocal( A.size );
1178 diag.Resize( A.size );
1181 Int numColFirst = A.size / mpisize;
1182 Int firstCol = mpirank * numColFirst;
1183 Int numColLocal = A.colptrLocal.m() - 1;
1185 #if ( _DEBUGlevel_ >= 1 )
1186 statusOFS <<
"numColFirst = " << numColFirst << std::endl;
1187 statusOFS <<
"A.nzvalLocal.size = " << A.nzvalLocal.m() << std::endl;
1188 statusOFS <<
"A.nnzLocal = " << A.nnzLocal << std::endl;
1192 for( Int j = 0; j < numColLocal; j++ ){
1193 Int jcol = j + firstCol + 1;
1194 Int numRow = A.colptrLocal(j+1) - A.colptrLocal(j);
1195 const Int* rowPtr = &A.rowindLocal( A.colptrLocal(j) - 1 );
1198 const Int* ptr = std::find( rowPtr, rowPtr + numRow, jcol );
1199 if( ptr == rowPtr + numRow ){
1200 std::ostringstream msg;
1201 msg <<
"Serious problem. Did not find the row corresponding to the column." << std::endl
1202 <<
"This happens when j = " << j <<
", jcol = " << jcol <<
", and the row indices are " << std::endl
1203 << IntNumVec( numRow,
false, const_cast<Int*>(rowPtr) ) << std::endl;
1204 ErrorHandling( msg.str().c_str() );
1206 Int diagIdx = ptr - A.rowindLocal.Data();
1207 diagLocal( jcol - 1 ) = A.nzvalLocal( diagIdx );
1210 mpi::Allreduce( &diagLocal[0], &diag[0], A.size, MPI_SUM, A.comm );
1219 template <
typename T>
void CSCToCSR(DistSparseMatrix<T>& sparseA, DistSparseMatrix<T> & sparseB ){
1223 MPI_Comm_rank(sparseA.comm,&mpirank);
1226 MPI_Comm_size(sparseA.comm,&mpisize);
1228 Int numRowLocalFirst = sparseA.size / mpisize;
1229 Int firstRow = mpirank * numRowLocalFirst;
1230 Int numRowLocal = -1;
1233 sparseB.size = sparseA.size;
1234 sparseB.nnz = sparseA.nnz;
1235 sparseB.comm = sparseA.comm;
1239 IntNumVec rowindGlobal;
1240 IntNumVec colptrGlobal;
1243 colptrGlobal.Resize(sparseA.size+1);
1246 IntNumVec prevnz(mpisize);
1247 IntNumVec rcounts(mpisize);
1248 MPI_Allgather((
void*)&sparseA.nnzLocal, 1, MPI_INT, rcounts.Data(), 1, MPI_INT, sparseA.comm);
1251 for (Int i = 0; i < mpisize-1; ++i) { prevnz[i+1] = prevnz[i] + rcounts[i]; }
1254 for (Int i = 0; i < mpisize; ++i) { nnz += rcounts[i]; }
1255 rowindGlobal.Resize(nnz);
1257 MPI_Allgatherv(sparseA.rowindLocal.Data(), sparseA.nnzLocal, MPI_INT, rowindGlobal.Data(),rcounts.Data(), prevnz.Data(), MPI_INT, sparseA.comm);
1261 Int numColFirst = std::max(1,sparseA.size / mpisize);
1263 rcounts[mpisize-1] = sparseA.size - numColFirst * (mpisize-1);
1265 IntNumVec rdispls(mpisize);
1267 for (Int i = 0; i < mpisize-1; ++i) { rdispls[i+1] = rdispls[i] + rcounts[i]; }
1269 MPI_Allgatherv(sparseA.colptrLocal.Data(), sparseA.colptrLocal.m()-1, MPI_INT, colptrGlobal.Data(),
1270 rcounts.Data(), rdispls.Data(), MPI_INT, sparseA.comm);
1273 for (Int p = 1; p < mpisize; p++) {
1274 Int idx = rdispls[p];
1275 for (Int j = 0; j < rcounts[p]; ++j) colptrGlobal[idx++] += prevnz[p];
1277 colptrGlobal(sparseA.size)= nnz+1;
1282 IntNumVec rowptrGlobal;
1283 IntNumVec colindGlobal;
1288 colindGlobal.Resize(nnz);
1289 rowptrGlobal.Resize(sparseA.size+1);
1290 IntNumVec row_nnz(sparseA.size);
1293 for (i = 0; i < nnz; i++) {
1294 Int k = rowindGlobal[i];
1299 for (i = 1; i <= sparseA.size; i++)
1301 rowptrGlobal[i] = rowptrGlobal[i-1] + row_nnz[i-1];
1310 for (j = 0; j < colptrGlobal.m()-1; j++)
1315 nnz_col = colptrGlobal[j+1] - colptrGlobal[j];
1317 for (k = colptrGlobal[j]; k < colptrGlobal[j+1]; k++)
1319 Int i = rowindGlobal[ k - 1 ];
1320 Int h = rowptrGlobal[i-1] + row_nnz[i-1];
1323 colindGlobal[ h - 1 ] = j+1;
1346 std::vector<Int > numRowVec(mpisize,numRowLocalFirst);
1347 numRowVec[mpisize-1] = sparseA.size - (mpisize-1)*numRowLocalFirst;
1349 numRowLocal = numRowVec[mpirank];
1350 Int myFirstCol = mpirank*numRowLocalFirst+1;
1351 Int myLastCol = myFirstCol + numRowLocal -1;
1353 sparseB.colptrLocal.Resize(numRowLocal+1);
1354 Int * rowptrLocal = &sparseB.colptrLocal[0];
1357 std::copy(&rowptrGlobal[myFirstCol-1],
1358 &rowptrGlobal[myLastCol]+1,
1361 nnzLocal = rowptrLocal[numRowLocal] - rowptrLocal[0];
1363 sparseB.nnzLocal = nnzLocal;
1365 sparseB.rowindLocal.Resize(nnzLocal);
1366 Int * colindLocal = &sparseB.rowindLocal[0];
1368 sparseB.nzvalLocal.Resize(nnzLocal);
1369 T * nzvalLocal = &sparseB.nzvalLocal[0];
1372 std::copy(&colindGlobal[rowptrLocal[0]-1],
1373 &colindGlobal[rowptrLocal[0]-1]+nnzLocal,
1377 for( Int i = 1; i < numRowLocal + 1; i++ ){
1378 rowptrLocal[i] = rowptrLocal[i] - rowptrLocal[0] + 1;
1399 std::vector<Int> * row_nnz =
new std::vector<Int>(numRowLocal,0);
1401 for(
int p =0; p<mpisize;p++){
1402 std::vector< char > send_buffer;
1403 std::vector< char > recv_buffer;
1404 std::vector<int> displs(mpisize+1,0);
1405 std::vector<int> bufsizes(mpisize,0);
1408 Int firstCol = p*numRowLocalFirst+1;
1409 Int lastCol = firstCol + numRowVec[p]-1;
1410 for(Int col = 1; col<colptrGlobal.m();++col){
1411 if(col>= firstCol && col<= lastCol){
1412 Int colbeg = colptrGlobal[col-1];
1413 Int colend = colptrGlobal[col]-1;
1414 for(Int i=colbeg;i<=colend;++i){
1415 Int row = rowindGlobal[i-1];
1417 Int p_dest = std::min(mpisize-1,(row-1)/(numRowLocalFirst));
1418 bufsizes[p_dest]+=
sizeof(T);
1421 else if(col>lastCol){
1427 std::partial_sum(bufsizes.begin(),bufsizes.end(),displs.begin()+1);
1430 std::vector<int> bufpos(mpisize,0);
1433 Int send_buffer_size = displs[mpisize];
1434 send_buffer.resize(displs[mpisize]);
1437 for(Int j = 1; j<sparseA.colptrLocal.m();++j){
1438 Int gCol = mpirank*numRowLocalFirst + j;
1439 Int colbeg = sparseA.colptrLocal[j-1];
1440 Int colend = sparseA.colptrLocal[j]-1;
1441 for(Int i=colbeg;i<=colend;++i){
1442 Int row = sparseA.rowindLocal[i-1];
1444 Int p_dest = std::min(mpisize-1,(row-1)/(numRowLocalFirst));
1445 Int p_displs = displs[p_dest];
1446 Int p_bufpos = bufpos[p_dest];
1447 *((T *)&send_buffer.at( displs[p_dest] + bufpos[p_dest] )) = sparseA.nzvalLocal[i-1];
1449 bufpos[p_dest]+=
sizeof(T);
1456 Int recv_buffer_size = bufsizes[mpirank];
1457 recv_buffer.resize(bufsizes[mpirank]);
1460 MPI_Scatterv(&send_buffer[0], &bufsizes[0], &displs[0], MPI_BYTE, &recv_buffer[0], bufsizes[mpirank], MPI_BYTE, p, sparseA.comm);
1465 for(Int col = 1; col<colptrGlobal.m();++col){
1466 if(col>= firstCol && col<= lastCol){
1467 Int colbeg = colptrGlobal[col-1];
1468 Int colend = colptrGlobal[col]-1;
1469 for(Int i=colbeg;i<=colend;++i){
1470 Int row = rowindGlobal[i-1];
1471 Int p_dest = std::min(mpisize-1,(row-1)/(numRowLocalFirst));
1472 if(p_dest==mpirank){
1474 Int local_row = row - mpirank*numRowLocalFirst;
1475 Int h = rowptrLocal[local_row-1] + row_nnz->at(local_row-1);
1476 *((T*)&nzvalLocal[h-1]) = *((T*)&recv_buffer.at(recv_pos));
1478 row_nnz->at(local_row-1)++;
1480 recv_pos+=
sizeof(T);
1484 else if(col>lastCol){
1497 #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:153