29 #define BCSC_COMM_NBR 6
55 bcsc_comm = bcsc->bcsc_comm;
57 bcsc_comm->
flttype = bcsc->flttype;
58 bcsc_comm->
clustnbr = solvmtx->clustnbr;
59 bcsc_comm->
clustnum = solvmtx->clustnum;
60 bcsc_comm->
comm = solvmtx->solv_comm;
85 for ( c = 0; c < clustnbr; c++ ) {
115 #if defined(PASTIX_WITH_MPI)
149 pastix_int_t idxcnt_A, idxcnt_At, idxcnt_AAt, valcnt_A, valcnt_At, valcnt_AAt, c;
152 for ( c = 0; c < clustnbr; c++ ) {
154 if ( c == clustnum ) {
165 max_idx = pastix_imax( max_idx, idxcnt_A);
166 max_idx = pastix_imax( max_idx, idxcnt_At);
167 max_idx = pastix_imax( max_idx, idxcnt_AAt);
168 max_val = pastix_imax( max_val, valcnt_A);
169 max_val = pastix_imax( max_val, valcnt_At);
170 max_val = pastix_imax( max_val, valcnt_AAt);
172 idxsum_A += idxcnt_A;
173 valsum_A += valcnt_A;
174 idxsum_At += idxcnt_At;
175 valsum_At += valcnt_At;
176 idxsum_AAt += idxcnt_AAt;
177 valsum_AAt += valcnt_AAt;
180 data_local = bcsc_comm->
data_comm + clustnum;
188 assert( max_idx <= 2 * max_val );
232 if ( mode == PastixTagMemRecvIdx ) {
248 if ( mode == PastixTagMemRecvValAAt ) {
249 for ( c = 0; c < clustnbr; c ++ ) {
251 if ( c == clustnum ) {
261 if ( mode == PastixTagMemSend ) {
262 for ( c = 0; c < clustnbr; c ++ ) {
265 if ( c == clustnum ) {
336 if ( mode == PastixTagMemSendIdx ) {
337 for ( c = 0; c < clustnbr; c ++ ) {
339 if ( c == clustnum ) {
354 if ( mode == PastixTagMemSendValA ) {
355 for ( c = 0; c < clustnbr; c ++ ) {
357 if ( c == clustnum ) {
366 if ( mode == PastixTagMemSendValAt ) {
367 for ( c = 0; c < clustnbr; c ++ ) {
369 if ( c == clustnum ) {
378 if ( mode == PastixTagMemSendValAAt ) {
379 for ( c = 0; c < clustnbr; c ++ ) {
381 if ( c == clustnum ) {
390 if ( mode == PastixTagMemRecvIdxA ) {
397 if ( mode == PastixTagMemRecvIdxAt ) {
404 if ( mode == PastixTagMemRecvAAt ) {
440 MPI_Status statuses[(clustnbr-1)*BCSC_COMM_NBR];
441 MPI_Request requests[(clustnbr-1)*BCSC_COMM_NBR];
446 c_send = (clustnum+1) % clustnbr;
447 c_recv = (clustnum-1+clustnbr) % clustnbr;
448 for ( k = 0; k < clustnbr-1; k++ ) {
449 data_send = data_comm + c_send;
450 data_recv = data_comm + c_recv;
452 if ( c_send == clustnum ) {
458 recvs = &( data_recv->
recvA );
459 MPI_Irecv( recvs, 2, PASTIX_MPI_INT, c_recv,
460 PastixTagCountA, bcsc_comm->
comm, &requests[counter_req++] );
462 MPI_Isend( sends, 2, PASTIX_MPI_INT, c_send,
463 PastixTagCountA, bcsc_comm->
comm, &requests[counter_req++] );
467 recvs = &( data_recv->
recvAt );
468 MPI_Irecv( recvs, 2, PASTIX_MPI_INT, c_recv,
469 PastixTagCountAt, bcsc_comm->
comm, &requests[counter_req++] );
471 MPI_Isend( sends, 2, PASTIX_MPI_INT, c_send,
472 PastixTagCountAt, bcsc_comm->
comm, &requests[counter_req++] );
477 MPI_Irecv( recvs, 2, PASTIX_MPI_INT, c_recv,
478 PastixTagCountAAt, bcsc_comm->
comm, &requests[counter_req++] );
480 MPI_Isend( sends, 2, PASTIX_MPI_INT, c_send,
481 PastixTagCountAAt, bcsc_comm->
comm, &requests[counter_req++] );
483 c_send = (c_send+1) % clustnbr;
484 c_recv = (c_recv-1+clustnbr) % clustnbr;
487 MPI_Waitall( counter_req, requests, statuses );
489 bcsc_compute_max( bcsc_comm );
523 const pastix_bcsc_t *bcsc )
531 memset( col2cblk, 0xff, bcsc->gN *
sizeof(
pastix_int_t) );
536 for ( cblknum = 0; cblknum < cblknbr; cblknum++, cblk++ ) {
537 if ( cblk->
cblktype & (CBLK_FANIN|CBLK_RECV) ) {
544 for ( j = cblk->
fcolnum; j <= cblk->lcolnum; j++ ) {
545 col2cblk[j] = cblknum;
552 #if defined(PASTIX_WITH_MPI)
582 const pastix_bcsc_t *bcsc )
594 memset( col2cblk, 0xff, bcsc->gN *
sizeof(
pastix_int_t) );
596 for( c = 0; c < clustnbr; c++ ) {
597 if ( c == clustnum ) {
605 MPI_Bcast( &n, 1, PASTIX_MPI_INT, c, solvmtx->solv_comm );
612 col2cblk_bcast = tmp;
619 for ( cblknum = 0; cblknum < cblknbr; cblknum++, cblk++ ) {
620 if ( cblk->
cblktype & (CBLK_FANIN|CBLK_RECV) ) {
624 col2cblk_bcast[k] = cblk->
fcolnum;
625 col2cblk_bcast[k+1] = cblk->
lcolnum;
631 for ( j = cblk->
fcolnum; j <= cblk->lcolnum; j++ ) {
633 col2cblk[j] = cblknum;
636 assert( colcount == bcsc->n );
639 MPI_Bcast( col2cblk_bcast, n, PASTIX_MPI_INT, c, solvmtx->solv_comm );
643 MPI_Bcast( &n, 1, PASTIX_MPI_INT, c, solvmtx->solv_comm );
650 col2cblk_bcast = tmp;
659 MPI_Bcast( col2cblk_bcast, n, PASTIX_MPI_INT, c, solvmtx->solv_comm );
664 for ( k = 0; k < n; k += 2 ) {
665 fcolnum = col2cblk_bcast[k];
666 lcolnum = col2cblk_bcast[k+1];
667 for ( j = fcolnum; j <= lcolnum; j++ ) {
668 col2cblk[j] = - c - 1;
674 free( col2cblk_bcast );
710 const pastix_bcsc_t *bcsc,
711 const spmatrix_t *spm )
716 #if defined(PASTIX_WITH_MPI)
717 if ( spm->loc2glob != NULL ) {
718 col2cblk = bcsc_init_col2cblk_dst( solvmtx, bcsc );
767 for ( jg = 0; jg < spm->gN; jg++ ) {
769 dofidx = (dof > 0) ? jgp * dof : dofs[jg];
770 ptr = dofshift + dofidx;
771 dofj = (dof > 0) ? dof : dofs[jg+1] - dofs[jg];
772 for ( idof = 0; idof < dofj; idof++, ptr++ ) {
813 int sym = (spm->mtxtype == SpmSymmetric) || (spm->mtxtype == SpmHermitian);
816 assert( spm->loc2glob == NULL );
819 for ( j = 0; j < spm->n; j++, colptr++ ) {
822 frow = colptr[0] - baseval;
823 lrow = colptr[1] - baseval;
824 assert( (lrow - frow) >= 0 );
826 globcol[jgp] += (lrow - frow) * dof;
837 for ( k = frow; k < lrow; k++ ) {
838 ig = rowptr[k] - baseval;
884 int sym = (spm->mtxtype == SpmSymmetric) || (spm->mtxtype == SpmHermitian);
886 assert( spm->dof <= 0 );
887 assert( spm->loc2glob == NULL );
890 for ( j=0; j<spm->n; j++, colptr++ ) {
892 dofj = dofs[jg+1] - dofs[jg];
894 frow = colptr[0] - baseval;
895 lrow = colptr[1] - baseval;
896 assert( (lrow - frow) >= 0 );
898 for ( k=frow; k<lrow; k++ ) {
899 ig = rowptr[k] - baseval;
900 dofi = dofs[ig+1] - dofs[ig];
902 globcol[jgp] += dofi;
905 if ( sym && (ig != jg) ) {
907 globcol[igp] += dofj;
915 #if defined(PASTIX_WITH_MPI)
975 bcsc_init_global_coltab_dst_cdof(
const spmatrix_t *spm,
990 int sym = (spm->mtxtype == SpmSymmetric) || (spm->mtxtype == SpmHermitian);
996 for ( jl = 0; jl < spm->n; jl++, colptr++, loc2glob++ ) {
997 jg = *loc2glob - baseval;
1000 frow = colptr[0] - baseval;
1001 lrow = colptr[1] - baseval;
1002 assert( (lrow - frow) >= 0 );
1004 ownerj = col2cblk[jgp * dof];
1008 ownerj = - ownerj - 1;
1009 data_comm = bcsc_comm->
data_comm + ownerj;
1010 data_sendA = &( data_comm->
sendA );
1013 for ( il = frow; il < lrow; il++ ) {
1014 ig = rowptr[il] - baseval;
1020 if ( sym && ( ig == jg ) ) {
1027 owneri = col2cblk[igp* dof];
1031 owneri = - owneri - 1;
1032 data_comm = bcsc_comm->
data_comm + owneri;
1038 if ( owneri == ownerj ) {
1039 data_sendAAt = &( data_comm->
sendAAt );
1049 data_sendAt = &( data_comm->
sendAt );
1071 globcol[igp] += dof;
1079 globcol[jgp] += dof * ( lrow - frow );
1082 for ( il = frow; il < lrow; il++ ) {
1083 ig = rowptr[il] - baseval;
1089 if ( sym && ( ig == jg ) ) {
1094 owneri = col2cblk[igp* dof];
1098 owneri = - owneri - 1;
1099 data_comm = bcsc_comm->
data_comm + owneri;
1105 data_sendAt = &( data_comm->
sendAt );
1116 globcol[igp] += dof;
1159 bcsc_init_global_coltab_dst_vdof( __attribute__((unused))
const spmatrix_t *spm,
1257 MPI_Status statuses[(clustnbr-1)*BCSC_COMM_NBR];
1258 MPI_Request requests[(clustnbr-1)*BCSC_COMM_NBR];
1264 bcsc_allocate_buf( bcsc_comm, PastixTagMemRecvIdx );
1266 for ( k = 0; k < clustnbr; k++ ) {
1267 if ( k == clustnum ) {
1273 idx_cnt_A[ k ] = cntA;
1275 idx_cnt_At[ k ] = cntAt;
1277 idx_cnt_AAt[ k ] = cntAAt;
1281 c_send = (clustnum+1) % clustnbr;
1282 c_recv = (clustnum-1+clustnbr) % clustnbr;
1283 for ( k = 0; k < clustnbr-1; k++ ) {
1284 data_send = data_comm + c_send;
1285 data_recv = data_comm + c_recv;
1286 if ( c_send == clustnum ) {
1291 recv = &( data_recv->recvA );
1292 if ( recv->
idxcnt != 0 ) {
1293 MPI_Irecv( sendA_local->
idxbuf + idx_cnt_A[c_recv], recv->
idxcnt,
1294 PASTIX_MPI_INT, c_recv, PastixTagIndexesA, bcsc_comm->
comm,
1295 &requests[counter_req++] );
1297 recv = &( data_recv->recvAt );
1298 if ( recv->
idxcnt != 0 ) {
1299 MPI_Irecv( sendAt_local->
idxbuf + idx_cnt_At[c_recv], recv->
idxcnt,
1300 PASTIX_MPI_INT, c_recv, PastixTagIndexesAt, bcsc_comm->
comm,
1301 &requests[counter_req++] );
1303 recv = &( data_recv->recvAAt.size );
1304 if ( recv->
idxcnt != 0 ) {
1305 MPI_Irecv( sendAAt_local->
idxbuf + idx_cnt_AAt[c_recv], recv->
idxcnt,
1306 PASTIX_MPI_INT, c_recv, PastixTagIndexesAAt, bcsc_comm->
comm,
1307 &requests[counter_req++] );
1311 send = &( data_send->sendA );
1314 PastixTagIndexesA, bcsc_comm->
comm, &requests[counter_req++] );
1316 send = &( data_send->sendAt );
1319 PastixTagIndexesAt, bcsc_comm->
comm, &requests[counter_req++] );
1321 send = &( data_send->sendAAt );
1324 PastixTagIndexesAAt, bcsc_comm->
comm, &requests[counter_req++] );
1326 c_send = (c_send+1) % clustnbr;
1327 c_recv = (c_recv-1+clustnbr) % clustnbr;
1330 MPI_Waitall( counter_req, requests, statuses );
1358 bcsc_update_globcol(
const spmatrix_t *spm,
1379 indexes_A = sendA_local->
idxbuf;
1380 indexes_At = sendAt_local->
idxbuf;
1381 indexes_AAt = sendAAt_local->
idxbuf;
1384 for ( k = 0; k < data_local->
recvA.
idxcnt; k += 2, indexes_A += 2 ) {
1387 ig = ord->
peritab[igp] - baseval;
1390 globcol[jgp] += ( dof < 0 ) ? dofs[ ig+1 ] - dofs[ig] : dof;
1394 if ( spm->mtxtype != SpmGeneral ) {
1395 for ( k = 0; k < data_local->
recvAt.
idxcnt; k += 2, indexes_At += 2 ) {
1396 igp = indexes_At[0];
1397 jgp = indexes_At[1];
1398 jg = ord->
peritab[jgp] - baseval;
1401 globcol[igp] += ( dof < 0 ) ? dofs[ jg+1 ] - dofs[jg] : dof;
1407 igp = indexes_AAt[0];
1408 jgp = indexes_AAt[1];
1409 ig = ord->
peritab[igp] - baseval;
1410 jg = ord->
peritab[jgp] - baseval;
1413 globcol[jgp] += ( dof < 0 ) ? dofs[ ig+1 ] - dofs[ig] : dof;
1415 if ( spm->mtxtype != SpmGeneral ) {
1417 globcol[igp] += ( dof < 0 ) ? dofs[ jg+1 ] - dofs[jg] : dof;
1480 memset( globcol, 0, (spm->gN+1) *
sizeof(
pastix_int_t) );
1482 if ( bcsc_comm == NULL ) {
1483 if ( spm->dof > 0 ) {
1490 #if defined(PASTIX_WITH_MPI)
1492 if ( spm->dof > 0 ) {
1493 bcsc_init_global_coltab_dst_cdof( spm, ord, col2cblk, globcol, bcsc_comm );
1496 bcsc_init_global_coltab_dst_vdof( spm, ord, col2cblk, globcol, bcsc_comm );
1500 bcsc_exchange_amount_of_data( bcsc_comm );
1503 switch( spm->flttype ) {
1505 bcsc_sstore_data( spm, ord, col2cblk, bcsc_comm );
1508 bcsc_dstore_data( spm, ord, col2cblk, bcsc_comm );
1511 bcsc_cstore_data( spm, ord, col2cblk, bcsc_comm );
1514 bcsc_zstore_data( spm, ord, col2cblk, bcsc_comm );
1518 fprintf(stderr,
"bcsc_init: Error unknown floating type for input spm\n");
1522 bcsc_exchange_indexes( bcsc_comm );
1523 bcsc_update_globcol( spm, ord, globcol, bcsc_comm );
1525 #if !defined(NDEBUG)
1527 if ( spm->dof > 0 ) {
1532 for( ig=0; ig<spm->gN; ig++ ) {
1534 ipe = ( spm->dof > 0 ) ? ip * spm->dof : spm->dofs[ ig ] - spm->baseval;
1535 if ( col2cblk[ipe] < 0 ) {
1539 dofi = ( spm->dof > 0 ) ? spm->dof: spm->dofs[ig+1] - spm->dofs[ig];
1540 nnzl += globcol[ip] * dofi;
1542 MPI_Allreduce( &nnzl, &nnzg, 1, PASTIX_MPI_INT, MPI_SUM, spm->comm );
1544 if ( spm->mtxtype != SpmGeneral ) {
1549 nnz = spm->gnnzexp * 2;
1550 assert( nnzg <= nnz );
1551 nnz = nnz - (spm->gN * spm->dof * spm->dof);
1552 assert( nnzg >= nnz );
1556 assert( nnzg == nnz );
1607 pastix_bcsc_t *bcsc )
1613 pastix_int_t cblknum, bcscnum, iter, idxcol, nodeidx, colsize;
1616 MALLOC_INTERN( bcsc->cscftab, bcsc->cscfnbr,
bcsc_cblk_t );
1627 blockcol = bcsc->cscftab;
1628 for ( cblknum = 0; cblknum < solvmtx->
cblknbr; cblknum++, cblk++ ) {
1629 if ( cblk->
cblktype & (CBLK_FANIN|CBLK_RECV) ) {
1635 assert( cblk->
bcscnum == bcscnum );
1638 blockcol->
coltab[0] = idxcol;
1639 for ( iter = 0; iter < blockcol->
colnbr; iter++ ) {
1640 nodeidx = dofshift[ cblk->
fcolnum + iter ];
1641 colsize = globcol[nodeidx];
1645 blockcol->
coltab[iter+1] = blockcol->
coltab[iter] + colsize;
1652 assert( (blockcol - bcsc->cscftab) == bcsc->cscfnbr );
1653 assert( bcscnum == bcsc->cscfnbr );
1655 memFree_null( globcol );
1656 memFree_null( dofshift );
1660 MALLOC_INTERN( bcsc->Lvalues, idxcol * pastix_size_of( bcsc->flttype ),
char );
1663 bcsc->rowtab = NULL;
1664 bcsc->Lvalues = NULL;
1666 bcsc->Uvalues = NULL;
1694 blockcol = bcsc->cscftab;
1695 for ( index=0; index<bcsc->cscfnbr; index++, blockcol++ )
1697 for ( iter=0; iter <= blockcol->
colnbr; iter++ )
1699 idxcoltmp = blockcol->
coltab[iter];
1700 blockcol->
coltab[iter] = idxcol;
1729 pastix_bcsc_t *bcsc )
1733 bcsc->mtxtype = spm->mtxtype;
1734 bcsc->flttype = spm->flttype;
1735 bcsc->gN = spm->gNexp;
1743 bcsc->col2cblk = col2cblk;
1749 bcsc->bcsc_comm = NULL;
1750 if ( spm->loc2glob != NULL ) {
1771 if ( bcsc->col2cblk != NULL ) {
1772 memFree_null( bcsc->col2cblk );
1775 if ( bcsc->bcsc_comm != NULL ) {
1777 memFree_null( bcsc->bcsc_comm );
1817 pastix_bcsc_t *bcsc )
1829 switch( spm->flttype ) {
1831 bcsc_sinit( spm, ord, solvmtx, initAt, bcsc, valuesize );
1834 bcsc_dinit( spm, ord, solvmtx, initAt, bcsc, valuesize );
1837 bcsc_cinit( spm, ord, solvmtx, initAt, bcsc, valuesize );
1840 bcsc_zinit( spm, ord, solvmtx, initAt, bcsc, valuesize );
1844 fprintf(stderr,
"bcsc_init: Error unknown floating type for input spm\n");
1891 pastix_bcsc_t *bcsc )
1896 assert( ord->
vertnbr == spm->gN );
1899 bcsc_init( spm, ord, solvmtx, initAt, bcsc );
1922 if ( bcsc->cscftab == NULL ) {
1926 for ( i=0, cblk=bcsc->cscftab; i < bcsc->cscfnbr; i++, cblk++ ) {
1927 memFree_null( cblk->
coltab );
1930 memFree_null( bcsc->cscftab );
1931 memFree_null( bcsc->rowtab );
1933 if ( (bcsc->Uvalues != NULL) &&
1934 (bcsc->Uvalues != bcsc->Lvalues) ) {
1935 memFree_null( bcsc->Uvalues );
1938 memFree_null( bcsc->Lvalues );
static void bcsc_init_global_coltab_shm_vdof(const spmatrix_t *spm, const pastix_order_t *ord, pastix_int_t *globcol)
Initializes the coltab of a block csc matrix. The coltab corresponds to the number of rows (expended)...
static pastix_int_t * bcsc_init_global_coltab(const spmatrix_t *spm, const pastix_order_t *ord, const SolverMatrix *solvmtx, const pastix_int_t *col2cblk, bcsc_handle_comm_t *bcsc_comm)
Initializes the coltab of a block csc matrix. The coltab corresponds to the number of rows (expended)...
static void bcsc_init(const spmatrix_t *spm, const pastix_order_t *ord, const SolverMatrix *solvmtx, pastix_int_t initAt, pastix_bcsc_t *bcsc)
Initializes a block csc.
static void bcsc_init_global_coltab_shm_cdof(const spmatrix_t *spm, const pastix_order_t *ord, pastix_int_t *globcol)
Initializes the coltab of a block csc matrix. The coltab corresponds to the number of rows (expended)...
static pastix_int_t * bcsc_init_dofshift(const spmatrix_t *spm, const pastix_order_t *ord)
Initializes the dofshit array of size gNexp which gives dofshift[index_permuted] = index....
BEGIN_C_DECLS typedef int pastix_int_t
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_init_struct(const spmatrix_t *spm, const SolverMatrix *solvmtx, pastix_bcsc_t *bcsc)
Initializes a block csc.
pastix_int_t bcsc_init_coltab(const spmatrix_t *spm, const pastix_order_t *ord, const SolverMatrix *solvmtx, pastix_bcsc_t *bcsc)
Initializes the coltab of a block csc matrix. The coltab corresponds to the number of rows (expended)...
void bcsc_sinit(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 float block csc.
pastix_int_t * bcsc_init_col2cblk(const SolverMatrix *solvmtx, const pastix_bcsc_t *bcsc, const spmatrix_t *spm)
Creates the array which represents the repartition of each column in the block structure....
void bcsc_handle_comm_init(const SolverMatrix *solvmtx, pastix_bcsc_t *bcsc)
Initializes the bcsc_handle_comm_t structure.
pastix_int_t * bcsc_init_col2cblk_shm(const SolverMatrix *solvmtx, const pastix_bcsc_t *bcsc)
Creates the array which represents the repartition of each column in the block structure....
void bcsc_zinit(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_complex64_t block csc.
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.
void bcsc_exit_struct(pastix_bcsc_t *bcsc)
Cleanup the bcsc struct. (symmetric of bcsc_init_struct)
void bcsc_dinit(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 double block csc.
void bcsc_handle_comm_exit(bcsc_handle_comm_t *bcsc_comm)
Frees the bcsc_handle_comm pointers.
bcsc_proc_comm_t data_comm[1]
bcsc_data_amount_t recvAt
pastix_coeftype_t flttype
enum bcsc_tag_ bcsc_tag_e
Tags used in MPI communications.
double bcscInit(const spmatrix_t *spm, const pastix_order_t *ord, const SolverMatrix *solvmtx, pastix_int_t initAt, pastix_bcsc_t *bcsc)
Initializes the block csc matrix.
struct bcsc_handle_comm_s bcsc_handle_comm_t
Structure to manage communications with distributed spm.
struct bcsc_proc_comm_s bcsc_proc_comm_t
Informations of the data exchanged with other processors.
void bcscExit(pastix_bcsc_t *bcsc)
Frees the block csc structure but do not free the bcsc pointer.
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.
static pastix_int_t cblk_colnbr(const SolverCblk *cblk)
Compute the number of columns in a column block.
SolverCblk *restrict cblktab
Solver column block structure.
Solver column block structure.