28 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 #if defined(PRECISION_c) || defined(PRECISION_z)
46 #if defined(PASTIX_WITH_MPI)
91 bcsc_cstore_data(
const spmatrix_t *spm,
110 int sym = (spm->mtxtype == SpmSymmetric) || (spm->mtxtype == SpmHermitian);
113 bcsc_allocate_buf( bcsc_comm, PastixTagMemSend );
121 data_cntAt = data_cntA + clustnbr;
122 data_cntAAt = data_cntA + clustnbr * 2;
124 baseval = spm->baseval;
127 for ( jl = 0; jl < spm->n; jl++, colptr++, loc2glob++ ) {
128 jg = *loc2glob - baseval;
130 jgpe = ( dof > 0 ) ? jgp * dof : dofs[ jg ] - baseval;
131 dofj = ( dof > 0 ) ? dof : dofs[ jg+1 ] - dofs[ jg ];
133 frow = colptr[0] - baseval;
134 lrow = colptr[1] - baseval;
135 assert( (lrow - frow) >= 0 );
137 ownerj = col2cblk[ jgpe ];
141 ownerj = - ownerj - 1;
142 data_comm = bcsc_comm->
data_comm + ownerj;
143 data_sendA = &( data_comm->
sendA );
146 for ( il = frow; il < lrow; il++ ) {
147 ig = rowptr[il] - baseval;
149 igpe = ( dof > 0 ) ? igp * dof : dofs[ ig ] - baseval;
150 dofi = ( dof > 0 ) ? dof : dofs[ ig+1 ] - dofs[ ig ];
151 owneri = col2cblk[ igpe ];
157 if ( sym && ( ig == jg ) ) {
160 data_cntA[ownerj].
idxcnt += 2;
164 data_cntA[ownerj].
valcnt += dofi * dofj;
166 values += dofi * dofj;
172 owneri = - owneri - 1;
173 data_comm = bcsc_comm->
data_comm + owneri;
179 if ( owneri == ownerj ) {
180 data_sendAAt = &( data_comm->
sendAAt );
182 data_sendAAt->
idxbuf[data_cntAAt[ownerj].
idxcnt ] = igp;
183 data_sendAAt->
idxbuf[data_cntAAt[ownerj].
idxcnt+1] = jgp;
184 data_cntAAt[ownerj].
idxcnt += 2;
188 data_cntAAt[ownerj].
valcnt += dofi * dofj;
195 data_sendAt = &( data_comm->
sendAt );
199 data_cntAt[owneri].
idxcnt += 2;
203 data_cntAt[owneri].
valcnt += dofi * dofj;
207 data_cntA[ownerj].
idxcnt += 2;
211 data_cntA[ownerj].
valcnt += dofi * dofj;
222 data_cntA[ownerj].
idxcnt += 2;
226 data_cntA[ownerj].
valcnt += dofi * dofj;
228 values += dofi * dofj;
234 for ( il = frow; il < lrow; il++ ) {
235 ig = rowptr[il] - baseval;
237 igpe = ( dof > 0 ) ? igp * dof : dofs[ ig ] - baseval;
238 dofi = ( dof > 0 ) ? dof : dofs[ ig+1 ] - dofs[ ig ];
239 owneri = col2cblk[ igpe ];
245 if ( sym && ( ig == jg ) ) {
246 values += dofi * dofj;
252 owneri = - owneri - 1;
253 data_comm = bcsc_comm->
data_comm + owneri;
254 data_sendAt = &( data_comm->
sendAt );
262 data_cntAt[owneri].
idxcnt += 2;
266 data_cntAt[owneri].
valcnt += dofi * dofj;
268 values += dofi * dofj;
273 memFree_null( data_cntA );
314 bcsc_chandle_recv_A(
const spmatrix_t *spm,
343 for ( k = 0; k < idx_size; k+=2, indexes+=2 ) {
350 igpe = (dof > 0) ? igp * dof : dofs[ ig ] - spm->baseval;
351 jgpe = (dof > 0) ? jgp * dof : dofs[ jg ] - spm->baseval;
352 dofi = (dof > 0) ? dof : dofs[ig+1] - dofs[ig];
353 dofj = (dof > 0) ? dof : dofs[jg+1] - dofs[jg];
355 itercblk = bcsc->col2cblk[ jgpe ];
356 assert( itercblk >= 0 );
359 cblk = solvmtx->
cblktab + itercblk;
360 coltab = bcsc->cscftab[cblk->
bcscnum].coltab;
364 for ( idofj = 0; idofj < dofj; idofj++, colidx++ ) {
366 pos = coltab[ colidx ];
367 for ( idofi = 0; idofi < dofi; idofi++, rowidx++, pos++, values_buf++ ) {
369 assert( rowidx >= 0 );
370 assert( rowidx < spm->gNexp );
371 bcsc->rowtab[ pos ] = rowidx;
373 Values[ pos ] = *values_buf;
376 coltab[ colidx ] += dofi;
377 assert( coltab[colidx] <= coltab[colidx+1] );
425 bcsc_chandle_recv_At(
const spmatrix_t *spm,
452 if ( spm->mtxtype == SpmGeneral ) {
453 _bcsc_conj = __fct_id;
457 if( spm->mtxtype == SpmHermitian ) {
458 _bcsc_conj = __fct_conj;
460 if( spm->mtxtype == SpmSymmetric ) {
461 _bcsc_conj = __fct_id;
471 for ( k = 0; k < idx_size; k+=2, indexes+=2 ) {
478 igpe = (dof > 0) ? igp * dof : dofs[ ig ] - spm->baseval;
479 jgpe = (dof > 0) ? jgp * dof : dofs[ jg ] - spm->baseval;
480 dofi = (dof > 0) ? dof : dofs[ig+1] - dofs[ig];
481 dofj = (dof > 0) ? dof : dofs[jg+1] - dofs[jg];
483 itercblk = bcsc->col2cblk[ igpe ];
484 assert( itercblk >= 0 );
487 cblk = solvmtx->
cblktab + itercblk;
488 coltab = bcsc->cscftab[cblk->
bcscnum].coltab;
491 for ( idofj = 0; idofj < dofj; idofj++ ) {
492 rowidx = jgpe + idofj;
494 for ( idofi = 0; idofi < dofi; idofi++, colidx++, values_buf++ ) {
495 pos = coltab[ colidx ];
497 assert( rowidx >= 0 );
498 assert( rowidx < spm->gNexp );
499 rowtab[ pos ] = rowidx;
502 Values[ pos ] = _bcsc_conj( *values_buf );
504 assert( coltab[colidx] <= coltab[colidx+1] );
550 bcsc_chandle_recv_AAt(
const spmatrix_t *spm,
576 if ( spm->mtxtype == SpmGeneral ) {
577 _bcsc_conj = __fct_id;
581 if( spm->mtxtype == SpmHermitian ) {
582 _bcsc_conj = __fct_conj;
584 if( spm->mtxtype == SpmSymmetric ) {
585 _bcsc_conj = __fct_id;
596 for ( k = 0; k < idx_size; k+=2, indexes+=2 ) {
603 igpe = (dof > 0) ? igp * dof : dofs[ ig ] - spm->baseval;
604 jgpe = (dof > 0) ? jgp * dof : dofs[ jg ] - spm->baseval;
605 dofi = (dof > 0) ? dof : dofs[ig+1] - dofs[ig];
606 dofj = (dof > 0) ? dof : dofs[jg+1] - dofs[jg];
608 itercblki = bcsc->col2cblk[ igpe ];
609 itercblkj = bcsc->col2cblk[ jgpe ];
610 assert( itercblki >= 0 );
611 assert( itercblkj >= 0 );
614 cblki = solvmtx->
cblktab + itercblki;
615 cblkj = solvmtx->
cblktab + itercblkj;
616 coltabi = bcsc->cscftab[cblki->
bcscnum].coltab;
617 coltabj = bcsc->cscftab[cblkj->
bcscnum].coltab;
621 for ( idofj = 0; idofj < dofj; idofj++ ) {
623 posj = coltabj[ colj ];
626 for ( idofi = 0; idofi < dofi; idofi++, coli++, rowj++, posj++, values_buf++ ) {
627 posi = coltabi[ coli ];
631 assert( rowi < spm->gNexp );
632 assert( rowj < spm->gNexp );
634 rowtab[ posi ] = rowi;
635 bcsc->rowtab[ posj ] = rowj;
638 ValuesAt[ posi ] = _bcsc_conj( *values_buf );
639 ValuesA [ posj ] = *values_buf;
641 assert( coltabi[coli] <= coltabi[coli+1] );
644 coltabj[ colj ] += dofi;
645 assert( coltabj[colj] <= coltabj[colj+1] );
677 bcsc_cexchange_values_A(
const spmatrix_t *spm,
680 pastix_bcsc_t *bcsc )
694 MPI_Status statuses[clustnbr-1];
695 MPI_Request requests[clustnbr-1];
700 if ( bcsc_comm->
max_idx != 0 ) {
704 for ( k = 0; k < clustnbr; k++ ) {
705 if ( k == clustnum ) {
714 c_send = (clustnum+1) % clustnbr;
715 for ( k = 0; k < clustnbr-1; k++ ) {
716 data_send = data_comm + c_send;
718 if ( c_send == clustnum ) {
723 if ( sends->
valcnt != 0 ) {
725 c_send, PastixTagValuesA, bcsc_comm->
comm, &requests[counter_req++] );
727 c_send = (c_send+1) % clustnbr;
731 c_recv = (clustnum-1+clustnbr) % clustnbr;
732 for ( k = 0; k < clustnbr-1; k++ ) {
733 data_recv = data_comm + c_recv;
734 recvs = &( data_recv->
recvA );
735 if ( c_recv == clustnum ) {
740 if ( recvs->
valcnt != 0 ) {
741 MPI_Recv( val_buf, recvs->
valcnt, PASTIX_MPI_COMPLEX32,
742 c_recv, PastixTagValuesA, bcsc_comm->
comm, MPI_STATUS_IGNORE );
744 nbelt_recv += bcsc_chandle_recv_A( spm, ord, solvmtx, bcsc,
745 val_buf, idx_cnt[c_recv], idx_size, 0 );
747 c_recv = (c_recv-1+clustnbr) % clustnbr;
750 MPI_Waitall( counter_req, requests, statuses );
753 bcsc_free_buf( bcsc_comm, PastixTagMemSendValA );
754 bcsc_free_buf( bcsc_comm, PastixTagMemRecvIdxA );
786 bcsc_cexchange_values_At(
const spmatrix_t *spm,
790 pastix_bcsc_t *bcsc )
804 MPI_Status statuses[clustnbr-1];
805 MPI_Request requests[clustnbr-1];
810 if ( bcsc_comm->
max_idx != 0 ) {
814 for ( k = 0; k < clustnbr; k++ ) {
815 if ( k == clustnum ) {
824 c_send = (clustnum+1) % clustnbr;
825 for ( k = 0; k < clustnbr-1; k++ ) {
826 data_send = data_comm + c_send;
828 if ( c_send == clustnum ) {
833 if ( sends->
valcnt != 0 ) {
835 c_send, PastixTagValuesAt, bcsc_comm->
comm, &requests[counter_req++] );
837 c_send = (c_send+1) % clustnbr;
841 c_recv = (clustnum-1+clustnbr) % clustnbr;
842 for ( k = 0; k < clustnbr-1; k++ ) {
843 data_recv = data_comm + c_recv;
844 recvs = &( data_recv->
recvAt );
845 if ( c_recv == clustnum ) {
850 if ( recvs->
valcnt != 0 ) {
851 MPI_Recv( val_buf, recvs->
valcnt, PASTIX_MPI_COMPLEX32,
852 c_recv, PastixTagValuesAt, bcsc_comm->
comm, MPI_STATUS_IGNORE );
854 nbelt_recv += bcsc_chandle_recv_At( spm, ord, solvmtx, rowtab, bcsc,
855 val_buf, idx_cnt[c_recv], idx_size, 0 );
857 c_recv = (c_recv-1+clustnbr) % clustnbr;
860 MPI_Waitall( counter_req, requests, statuses );
863 bcsc_free_buf( bcsc_comm, PastixTagMemSendValAt );
864 bcsc_free_buf( bcsc_comm, PastixTagMemRecvIdxAt );
896 bcsc_cexchange_values_AAt(
const spmatrix_t *spm,
900 pastix_bcsc_t *bcsc )
914 MPI_Status statuses[clustnbr-1];
915 MPI_Request requests[clustnbr-1];
921 if ( bcsc_comm->
max_idx != 0 ) {
922 if ( spm->mtxtype != SpmGeneral ) {
926 if ( rowtabAt == bcsc->rowtab ) {
927 bcsc_allocate_buf( bcsc_comm, PastixTagMemRecvValAAt);
932 for ( k = 0; k < clustnbr; k++ ) {
933 if ( k == clustnum ) {
942 c_send = (clustnum+1) % clustnbr;
943 for ( k = 0; k < clustnbr-1; k++ ) {
944 if ( rowtabAt != bcsc->rowtab ) {
947 data_send = data_comm + c_send;
949 if ( c_send == clustnum ) {
954 if ( sends->
valcnt != 0 ) {
956 c_send, PastixTagValuesAAt, bcsc_comm->
comm, &requests[counter_req++] );
958 c_send = (c_send+1) % clustnbr;
962 c_recv = (clustnum-1+clustnbr) % clustnbr;
963 for ( k = 0; k < clustnbr-1; k++ ) {
964 data_recv = data_comm + c_recv;
965 recvs = &( data_recv->
recvAAt );
966 if ( c_recv == clustnum ) {
972 if ( spm->mtxtype == SpmGeneral ) {
975 if ( rowtabAt == bcsc->rowtab ) {
976 MPI_Recv( val_buf, recvs->
size.
valcnt, PASTIX_MPI_COMPLEX32,
977 c_recv, PastixTagValuesAAt, bcsc_comm->
comm, MPI_STATUS_IGNORE );
981 if ( spm->mtxtype != SpmGeneral ) {
982 nbelt_recv += bcsc_chandle_recv_AAt( spm, ord, solvmtx, rowtabAt, bcsc,
983 val_buf, idx_cnt[c_recv], idx_size );
986 if ( rowtabAt == bcsc->rowtab ) {
987 nbelt_recv += bcsc_chandle_recv_A( spm, ord, solvmtx, bcsc, val_buf,
988 idx_cnt[c_recv], idx_size, 1 );
991 nbelt_recv += bcsc_chandle_recv_At( spm, ord, solvmtx, rowtabAt, bcsc,
992 val_buf, idx_cnt[c_recv], idx_size, 1 );
996 c_recv = (c_recv-1+clustnbr) % clustnbr;
999 if ( rowtabAt == bcsc->rowtab ) {
1000 MPI_Waitall( counter_req, requests, statuses );
1002 if ( spm->mtxtype != SpmGeneral ) {
1006 if ( ( spm->mtxtype != SpmGeneral ) || ( rowtabAt != bcsc->rowtab ) ) {
1007 bcsc_free_buf( bcsc_comm, PastixTagMemRecvIdxAAt );
1008 bcsc_free_buf( bcsc_comm, PastixTagMemSendValAAt );
1010 if ( ( spm->mtxtype == SpmGeneral ) && ( rowtabAt != bcsc->rowtab ) ) {
1011 bcsc_free_buf( bcsc_comm, PastixTagMemRecvAAt );
1049 pastix_bcsc_t *bcsc )
1066 baseval = spm->baseval;
1076 for ( j = 0; j < spm->n; j++, colptr++, loc2glob++ ) {
1077 jg = ( spm->loc2glob == NULL ) ? j : *loc2glob - baseval;
1079 jgpe = ( dof > 0 ) ? jgp * dof : dofs[ jg ] - baseval;
1080 dofj = ( dof > 0 ) ? dof : dofs[ jg+1 ] - dofs[ jg ];
1082 itercblk = bcsc->col2cblk[ jgpe ];
1089 if ( itercblk >= 0 ) {
1091 cblk = solvmtx->
cblktab + itercblk;
1092 coltab = bcsc->cscftab[cblk->
bcscnum].coltab;
1098 for ( k = colptr[0]; k < colptr[1]; k++, rowptr++ ) {
1099 ig = *rowptr - baseval;
1101 igpe = ( dof > 0 ) ? igp * dof : dofs[ ig ] - baseval;
1102 dofi = ( dof > 0 ) ? dof : dofs[ ig+1 ] - dofs[ ig ];
1105 colidx = jgpe - cblk->
fcolnum;
1106 for ( idofj = 0; idofj < dofj; idofj++, colidx++ ) {
1108 pos = coltab[ colidx ];
1109 for ( idofi = 0; idofi < dofi; idofi++, rowidx++, pos++, values++ ) {
1110 assert( rowidx >= 0 );
1111 assert( rowidx < spm->gNexp );
1112 bcsc->rowtab[ pos ] = rowidx;
1113 Lvalues[ pos ] = *values;
1116 coltab[ colidx ] += dofi;
1117 assert( coltab[ colidx ] <= coltab[ colidx+1 ] );
1123 for ( k = colptr[0]; k < colptr[1]; k++, rowptr++ ) {
1124 ig = *rowptr - baseval;
1125 dofi = ( dof > 0 ) ? dof : dofs[ ig+1 ] - dofs[ ig ];
1127 values += dofi * dofj;
1176 pastix_bcsc_t *bcsc )
1195 if ( spm->mtxtype == SpmGeneral ) {
1196 _bcsc_conj = __fct_id;
1205 if( spm->mtxtype == SpmHermitian ) {
1206 _bcsc_conj = __fct_conj;
1208 if( spm->mtxtype == SpmSymmetric ) {
1209 _bcsc_conj = __fct_id;
1213 assert( _bcsc_conj != NULL );
1215 baseval = spm->baseval;
1225 for ( j = 0; j < spm->n; j++, colptr++, loc2glob++ ) {
1226 jg = ( spm->loc2glob == NULL ) ? j : *loc2glob - baseval;
1228 jgpe = ( dof > 0 ) ? jgp * dof : dofs[ jg ] - baseval;
1229 dofj = ( dof > 0 ) ? dof : dofs[ jg+1 ] - dofs[ jg ];
1236 for ( k = colptr[0]; k < colptr[1]; k++, rowptr++ ) {
1237 ig = *rowptr - baseval;
1239 igpe = ( dof > 0 ) ? igp * dof : dofs[ ig ] - baseval;
1240 dofi = ( dof > 0 ) ? dof : dofs[ ig+1 ] - dofs[ ig ];
1243 if ( ( ig == jg ) && ( spm->mtxtype != SpmGeneral ) ) {
1244 values += dofi * dofj;
1247 itercblk = bcsc->col2cblk[ igpe ];
1254 if ( itercblk >= 0 ) {
1256 cblk = solvmtx->
cblktab + itercblk;
1257 coltab = bcsc->cscftab[cblk->
bcscnum].coltab;
1260 for ( idofj = 0; idofj < dofj; idofj++ ) {
1261 rowidx = jgpe + idofj;
1262 colidx = igpe - cblk->
fcolnum;
1263 for ( idofi = 0; idofi < dofi; idofi++, colidx++, values++ ) {
1264 pos = coltab[ colidx ];
1267 assert( rowidx >= 0 );
1268 assert( rowidx < spm->gNexp );
1269 rowtab[ pos ] = rowidx;
1270 Uvalues[ pos ] = _bcsc_conj( *values );
1279 values += dofi * dofj;
1313 pastix_int_t block_num, col, len_col_block, block_nbr, col_nbr;
1316 block_nbr = bcsc->cscfnbr;
1317 block = bcsc->cscftab;
1318 for ( block_num = 0; block_num < block_nbr; block_num++, block++ ) {
1321 for ( col = 0; col < col_nbr; col++ ) {
1323 sortptr[0] = (
void*)(rowtab + block->
coltab[col]);
1324 sortptr[1] = (
void*)(valtab + block->
coltab[col]);
1326 len_col_block = block->
coltab[col+1] - block->
coltab[col];
1327 #if !defined(NDEBUG)
1332 for ( i = 0; i < len_col_block; i++ ) {
1333 assert( rowtab[ block->
coltab[col] + i ] >= 0 );
1334 assert( rowtab[ block->
coltab[col] + i ] < gN );
1339 c_qsortIntFloatAsc( sortptr, len_col_block );
1378 pastix_bcsc_t *bcsc,
1382 #if defined(PASTIX_WITH_MPI)
1388 #if defined(PASTIX_WITH_MPI)
1389 if ( bcsc_comm != NULL ) {
1390 nbelt_recv = bcsc_cexchange_values_A( spm, ord, solvmtx, bcsc );
1391 nbelt_recv += bcsc_cexchange_values_AAt( spm, ord, solvmtx, bcsc->rowtab, bcsc );
1392 nbelt += nbelt_recv;
1400 if ( spm->mtxtype != SpmGeneral ) {
1402 #if defined(PASTIX_WITH_MPI)
1403 if ( bcsc_comm != NULL ) {
1404 nbelt_recv = bcsc_cexchange_values_At( spm, ord, solvmtx, bcsc->rowtab, bcsc );
1405 nbelt += nbelt_recv;
1408 nbelt +=
bcsc_cinit_At( spm, ord, solvmtx, bcsc->rowtab, bcsc );
1415 bcsc_csort( bcsc, bcsc->rowtab, bcsc->Lvalues );
1418 if ( spm->mtxtype == SpmGeneral ) {
1425 for (i=0; i<valuesize; i++) {
1429 #if defined(PASTIX_WITH_MPI)
1430 if ( bcsc_comm != NULL ) {
1431 nbelt_recv = bcsc_cexchange_values_At( spm, ord, solvmtx, trowtab, bcsc );
1432 nbelt_recv += bcsc_cexchange_values_AAt( spm, ord, solvmtx, trowtab, bcsc );
1433 nbelt += nbelt_recv;
1446 bcsc->Uvalues = bcsc->Lvalues;
1450 #if defined(PASTIX_WITH_MPI)
BEGIN_C_DECLS typedef int pastix_int_t
float _Complex pastix_complex32_t
static void bcsc_csort(const pastix_bcsc_t *bcsc, pastix_int_t *rowtab, pastix_complex32_t *valtab)
Sorts the block csc subarray associated to each column block.
static pastix_int_t bcsc_cinit_At(const spmatrix_t *spm, const pastix_order_t *ord, const SolverMatrix *solvmtx, pastix_int_t *rowtab, pastix_bcsc_t *bcsc)
Initializes the At values in the block cscstored in the given spm.
void bcsc_restore_coltab(pastix_bcsc_t *bcsc)
Restores the coltab array when it has been modified to initialize the row and values arrays.
void bcsc_cinit(const spmatrix_t *spm, const pastix_order_t *ord, const SolverMatrix *solvmtx, int initAt, pastix_bcsc_t *bcsc, pastix_int_t valuesize)
Initializes a centralize pastix_complex32_t block csc.
static pastix_int_t bcsc_cinit_A(const spmatrix_t *spm, const pastix_order_t *ord, const SolverMatrix *solvmtx, pastix_bcsc_t *bcsc)
Initializes the A values of the block csc stored in the given spm.
bcsc_proc_comm_t data_comm[1]
bcsc_data_amount_t recvAt
Compressed colptr format for the bcsc.
Information about the amount of data.
Information about the sending data.
Structure to manage communications with distributed spm.
Informations of the data exchanged with other processors.
SolverCblk *restrict cblktab
Solver column block structure.
Solver column block structure.