#include "BSprivate.h"
/* a data structure used only in factoring */
/* nodes in a list of i-nodes that need to be received/sent during */
/* factorization */
typedef struct __list_type {
int length; /* length of the columns in the i-node */
int cur_len; /* don't know anymore */
FLOAT *d_buffer; /* don't know anymore */
int *i_buffer; /* don't know anymore */
int buf_size; /* don't know anymore */
int cl_ind; /* index of the clique, if local */
int in_ind; /* index of the i-node if local */
} list_type;
#include "BStree.h"
extern void BSilu_updt_matrix1(BSpar_mat *,int,BStree,BStree,int,int *,FLOAT *,
int, int *, FLOAT *, int , int , BScl_2_inode *, BSinode *, BSprocinfo *);
/*+ BSilu_factor1 - Compute the incomplete LU factor of a
matrix (no inode version)
Input Parameters:
. A - The sparse matrix to be factored
. comm - the communication structure of the factoring
. procinfo - the usual processor info
Output Parameters:
. A - The factored sparse matrix
Returns:
0 if successful, otherwise a negative number whose absolute
value is the row number of the color (less one) where the
failure occured.
+*/
typedef struct __col_list {
int count;
int *col;
FLOAT **nz;
} col_list;
int BSilu_factor1(BSpar_mat *A, BScomm *comm, BSprocinfo *procinfo)
{
BMphase *to_phase, *from_phase;
BMmsg *msg;
int i, j, k;
int cl_ind, in_ind;
int count, size, ind;
int length, gnum;
int found;
int dummy = 0;
int *intptr, *intptr2, *i_buffer;
FLOAT *d_buffer;
BScl_2_inode *clique2inode;
BSnumbering *color2clique;
BSinode *inodes;
int *data_ptr, data_len, msg_len;
FLOAT *msg_buf;
FLOAT *nzptr;
FLOAT t;
int info, fact_error;
BStree recv_tree;
BStree_ptr tree_node_ptr;
BStree inode_tree;
list_type *list_data_ptr;
int *g_row_num, *iperm;
int dd_size, *ii_buffer;
FLOAT *dd_buffer;
BStree rowtree;
BStree_ptr node_ptr;
col_list *col_list_ptr;
BMinit_comp_msg(comm->from_msg,procinfo); CHKERRN(0);
BMinit_comp_msg(comm->to_msg,procinfo); CHKERRN(0);
color2clique = A->color2clique;
clique2inode = A->clique2inode;
inodes = A->inodes->list;
g_row_num = A->global_row_num->numbers;
iperm = A->inv_perm->perm;
MY_INIT_TREE(inode_tree,(sizeof(int)*2));
for (i=0;i<color2clique->length-1;i++) {
for (cl_ind=color2clique->numbers[i];
cl_ind<color2clique->numbers[i+1];cl_ind++) {
for (in_ind=clique2inode->inode_index[cl_ind];
in_ind<clique2inode->inode_index[cl_ind+1];in_ind++) {
MY_INSERT_TREE_NODE(inode_tree,(inodes[in_ind].gcol_num),
found,tree_node_ptr,dummy);
data_ptr = (int *) MY_GET_TREE_DATA(tree_node_ptr);
data_ptr[0] = in_ind;
data_ptr[1] = cl_ind;
}
}
}
/* Create a rowtree - a data structure that stores all the cols of all */
/* local rows (ILU) */
MY_INIT_TREE(rowtree,sizeof(col_list));
for (j=0; j<A->inodes->length; j++) {
for (i=0; i<inodes[j].length; i++) {
MY_INSERT_TREE_NODE(rowtree,g_row_num[iperm[inodes[j].row_num[i]]],
found,node_ptr,dummy);
col_list_ptr = (col_list *) MY_GET_TREE_DATA(node_ptr);
if (found) {
col_list_ptr->count++;
} else {
col_list_ptr->count = 1;
/* A->max_local_row_length is used to store max_row_len */
MY_MALLOCN(col_list_ptr->col,(int *),
sizeof(int)*A->max_local_row_length,1);
MY_MALLOCN(col_list_ptr->nz,(FLOAT **),
sizeof(FLOAT *)*A->max_local_row_length,1);
}
col_list_ptr->col[col_list_ptr->count-1]=inodes[j].gcol_num;
col_list_ptr->nz[col_list_ptr->count-1]=&(inodes[j].nz[i]);
}
}
fact_error = FALSE;
/* now do this phase by phase */
for (i=0;i<color2clique->length-1;i++) {
to_phase = BMget_phase(comm->to_msg,i); CHKERRN(0);
from_phase = BMget_phase(comm->from_msg,i); CHKERRN(0);
/* send my part of each column in this color */
/* use the "from" part here */
msg = NULL;
while ((msg = BMnext_msg(from_phase,msg)) != NULL) {
CHKERRN(0);
/* allocate space for the message */
data_ptr = BMget_user(msg,&data_len); CHKERRN(0);
in_ind = data_ptr[1];
size = inodes[in_ind].length*sizeof(FLOAT)
+ inodes[in_ind].length*sizeof(int);
MY_MALLOCN(msg_buf,(FLOAT *),size,1);
BMset_msg_ptr(msg,msg_buf); CHKERRN(0);
BMset_msg_size(msg,size); CHKERRN(0);
count = 0;
nzptr = inodes[in_ind].nz;
for (k=0;k<inodes[in_ind].length;k++) {
msg_buf[count] = nzptr[k];
count++;
}
intptr = (int *) &(msg_buf[count]);
intptr2 = (int *) inodes[in_ind].row_num;
for (j=0;j<inodes[in_ind].length;j++) {
intptr[j] = g_row_num[iperm[intptr2[j]]];
}
BMsend_block_msg(from_phase,msg,procinfo); CHKERRN(0);
MY_FREE(msg_buf);
BMset_msg_ptr(msg,NULL); CHKERRN(0);
}
CHKERRN(0);
BMsend_block_msg(from_phase,NULL,procinfo); CHKERRN(0);
/* factor the cliques in this color */
for (cl_ind=color2clique->numbers[i];
cl_ind<color2clique->numbers[i+1];cl_ind++) {
if (procinfo->my_id == clique2inode->proc[cl_ind]) {
t = *(clique2inode->d_mats[cl_ind].matrix);
if (t == 0.0) {
fact_error = TRUE;
printf("ILU Error: zero pivot encountered.\n");
} else {
*(clique2inode->d_mats[cl_ind].matrix) = 1/t;
}
MLOG_flop(1);
}
}
/* figure out what I am going to receive and make room for it */
/* use the "to" part here */
MY_INIT_TREE(recv_tree,sizeof(list_type));
msg = NULL;
while ((msg = BMnext_msg(to_phase,msg)) != NULL) {
CHKERRN(0);
/* search list for this number */
data_ptr = BMget_user(msg,&data_len); CHKERRN(0);
gnum = data_ptr[0];
length = data_ptr[1];
MY_INSERT_TREE_NODE(recv_tree,gnum,found,tree_node_ptr,dummy);
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
if (found) {
list_data_ptr->length += length;
} else {
list_data_ptr->length = length;
list_data_ptr->cur_len = 0;
list_data_ptr->d_buffer = NULL;
list_data_ptr->i_buffer = NULL;
list_data_ptr->cl_ind = -1;
list_data_ptr->in_ind = -1;
}
}
CHKERRN(0);
/* add any of my parts to the list, if necessary */
for (cl_ind=color2clique->numbers[i];
cl_ind<color2clique->numbers[i+1];cl_ind++) {
/* only work on columns that I own */
if (clique2inode->proc[cl_ind] != procinfo->my_id) continue;
for (in_ind=clique2inode->inode_index[cl_ind];
in_ind<clique2inode->inode_index[cl_ind+1];in_ind++) {
MY_INSERT_TREE_NODE(recv_tree,(inodes[in_ind].gcol_num),
found,tree_node_ptr,dummy);
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
if (found) {
list_data_ptr->cl_ind = cl_ind;
list_data_ptr->in_ind = in_ind;
list_data_ptr->length += inodes[in_ind].length;
} else {
list_data_ptr->length = inodes[in_ind].length;
list_data_ptr->cur_len = 0;
list_data_ptr->d_buffer = NULL;
list_data_ptr->i_buffer = NULL;
list_data_ptr->cl_ind = cl_ind;
list_data_ptr->in_ind = in_ind;
}
}
}
/* make sure that no one has been received out of order */
if (procinfo->error_check) {
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
if (list_data_ptr->cl_ind == -1) {
MY_SETERRCN(FACTOR_ERROR,"Received column out of order\n");
}
}
}
/* allocate space for each whole column */
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
list_data_ptr->buf_size =
(list_data_ptr->length*sizeof(FLOAT)) +
(list_data_ptr->length*sizeof(int));
MY_MALLOCN(list_data_ptr->d_buffer,(FLOAT *),
list_data_ptr->buf_size,2);
list_data_ptr->i_buffer = (int *)
&(list_data_ptr->d_buffer[list_data_ptr->length]);
}
/* put my part of the column into the collected column */
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
in_ind = list_data_ptr->in_ind;
length = inodes[in_ind].length;
nzptr = inodes[in_ind].nz;
d_buffer = list_data_ptr->d_buffer;
for (k=0;k<length;k++) {
d_buffer[k] = nzptr[k];
}
d_buffer += list_data_ptr->length;
i_buffer = list_data_ptr->i_buffer;
intptr = inodes[in_ind].row_num;
/* while copying, convert i_buffer from new local to new global */
for (j=0;j<length;j++) {
i_buffer[j] = g_row_num[iperm[intptr[j]]];
}
list_data_ptr->cur_len += length;
}
/* collect all the parts of "my" columns */
while ((msg = BMrecv_block_msg(to_phase,procinfo)) != NULL) {
CHKERRN(0);
BMcheck_on_async_block(from_phase); CHKERRN(0);
msg_buf = (FLOAT *) BMget_msg_ptr(msg); CHKERRN(0);
BMset_msg_ptr(msg,NULL); CHKERRN(0);
data_ptr = BMget_user(msg,&msg_len); CHKERRN(0);
gnum = data_ptr[0];
length = data_ptr[1];
MY_SEARCH_TREE(recv_tree,gnum,found,tree_node_ptr);
if (found) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
d_buffer = &(list_data_ptr->d_buffer[list_data_ptr->cur_len]);
for (k=0;k<length;k++) {
d_buffer[k] = msg_buf[k];
}
d_buffer += list_data_ptr->length;
i_buffer = &(list_data_ptr->i_buffer[list_data_ptr->cur_len]);
intptr = (int *) &(msg_buf[length]);
for (j=0;j<length;j++) {
i_buffer[j] = intptr[j];
}
list_data_ptr->cur_len += length;
} else {
MY_SETERRCN(FACTOR_ERROR,"Can't find matching column\n");
}
}
CHKERRN(0);
BMfree_block_msg(to_phase); CHKERRN(0);
BMfinish_on_async_block(from_phase); CHKERRN(0);
/* see if the factorizations went okay, if not, then return */
/* we have to wait until here to make sure all messages are received */
/* make anything that needs free'ing is free'ed */
/* everyone agrees on success/error */
GISUM(&fact_error,1,&info,procinfo->procset);
if (fact_error != 0) {
/* free up space and return with the negative phase number */
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
MY_FREE(list_data_ptr->d_buffer);
}
MY_FREE_TREE(recv_tree);
return(-(i+1));
}
/* factor these columns */
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
if (list_data_ptr->length <= 0) continue;
cl_ind = list_data_ptr->cl_ind;
t = *(clique2inode->d_mats[cl_ind].matrix);
/* The following part is modified (ILU) */
for (j=0;j<list_data_ptr->length;j++) {
if (list_data_ptr->i_buffer[j] > clique2inode->g_offset[cl_ind])
(list_data_ptr->d_buffer[j]) *= t;
}
MLOG_flop(list_data_ptr->length);
}
/* The following part is modified (ILU) */
/* send these columns out */
msg = NULL;
while ((msg = BMnext_msg(to_phase,msg)) != NULL) {
CHKERRN(0);
data_ptr = BMget_user(msg,&data_len); CHKERRN(0);
gnum = data_ptr[0];
MY_SEARCH_TREE(recv_tree,gnum,found,tree_node_ptr);
if (found) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_SEARCH_TREE(rowtree,gnum,found,node_ptr);
if (found) {
col_list_ptr = (col_list *) MY_GET_TREE_DATA(node_ptr);
dd_size = col_list_ptr->count*sizeof(FLOAT)+
list_data_ptr->buf_size;
MY_MALLOCN(dd_buffer,(FLOAT *),dd_size,1);
for (j=0; j<list_data_ptr->length; j++)
dd_buffer[j] = list_data_ptr->d_buffer[j];
k = j;
for (j=0; j<col_list_ptr->count; j++)
dd_buffer[k+j] = col_list_ptr->nz[j][0];
ii_buffer = (int *) &(dd_buffer[k+j]);
for (j=0; j<list_data_ptr->length; j++)
ii_buffer[j] = list_data_ptr->i_buffer[j];
BMset_msg_ptr(msg,dd_buffer); CHKERRN(0);
BMset_msg_size(msg,dd_size); CHKERRN(0);
BMsend_block_msg(to_phase,msg,procinfo); CHKERRN(0);
BMset_msg_ptr(msg,NULL); CHKERRN(0);
MY_FREE(dd_buffer);
} else {
printf("Error: Something wrong with rowtree.\n");
}
} else {
MY_SETERRCN(FACTOR_ERROR,"Can't find matching column\n");
}
}
CHKERRN(0);
BMsend_block_msg(to_phase,NULL,procinfo); CHKERRN(0);
/* retrieve my part of the column and put it in the data structure */
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
if (list_data_ptr->length <= 0) continue;
in_ind = list_data_ptr->in_ind;
length = inodes[in_ind].length;
nzptr = inodes[in_ind].nz;
d_buffer = list_data_ptr->d_buffer;
for (k=0;k<length;k++) {
nzptr[k] = d_buffer[k];
}
d_buffer += list_data_ptr->length;
}
/* now update the remaining matrix using the local columns */
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
if (list_data_ptr->length <= 0) continue;
in_ind = list_data_ptr->in_ind;
gnum = inodes[in_ind].gcol_num;
MY_SEARCH_TREE(rowtree,gnum,found,node_ptr);
if (found) {
col_list_ptr = (col_list *) MY_GET_TREE_DATA(node_ptr);
MY_MALLOCN(dd_buffer,(FLOAT *),
col_list_ptr->count*sizeof(FLOAT),1);
for (j=0; j<col_list_ptr->count; j++)
dd_buffer[j] = col_list_ptr->nz[j][0];
BSilu_updt_matrix1(A,gnum,rowtree,
inode_tree,list_data_ptr->length,
list_data_ptr->i_buffer,list_data_ptr->d_buffer,
col_list_ptr->count,col_list_ptr->col,dd_buffer,
color2clique->numbers[i+1],
color2clique->numbers[color2clique->length-1],clique2inode,
inodes,procinfo); CHKERRN(0);
MY_FREE(dd_buffer);
} else {
printf("Error: Something wrong with rowtree.\n");
}
}
/* The following part is modified (ILU) */
/* receive the incoming columns and update the remaining matrix */
/* strip out the "local" part and put it in the matrix */
while ((msg = BMrecv_block_msg(from_phase,procinfo)) != NULL) {
CHKERRN(0);
BMcheck_on_async_block(to_phase); CHKERRN(0);
msg_buf = (FLOAT *) BMget_msg_ptr(msg); CHKERRN(0);
BMset_msg_ptr(msg,NULL); CHKERRN(0);
data_ptr = BMget_user(msg,&msg_len); CHKERRN(0);
cl_ind = data_ptr[0];
in_ind = data_ptr[1];
/* let gnum be first global row location of my part */
gnum = g_row_num[iperm[inodes[in_ind].row_num[0]]];
length = inodes[in_ind].length;
msg_len = BMget_msg_size(msg); CHKERRN(0);
msg_len /= 2*sizeof(FLOAT)+sizeof(int);
/* find my local part */
i_buffer = (int *) &(msg_buf[2*msg_len]);
for (ind=0; ind<msg_len; ind++) {
if (gnum == i_buffer[ind]) break;
}
nzptr = inodes[in_ind].nz;
d_buffer = &(msg_buf[ind]);
for (k=0;k<length;k++) {
nzptr[k] = d_buffer[k];
}
d_buffer += msg_len;
/* update the remaining matrix */
BSilu_updt_matrix1(A,inodes[in_ind].gcol_num,rowtree,
inode_tree,msg_len,i_buffer,msg_buf,
msg_len,i_buffer,&(msg_buf[msg_len]),
color2clique->numbers[i+1],
color2clique->numbers[color2clique->length-1],clique2inode,
inodes,procinfo); CHKERRN(0);
}
CHKERRN(0);
BMfree_block_msg(from_phase); CHKERRN(0);
BMfinish_on_async_block(to_phase); CHKERRN(0);
/* now free up the list */
MY_FIRST_IN_TREE(recv_tree,tree_node_ptr);
while (! IS_TREE_PTR_NULL(tree_node_ptr)) {
list_data_ptr = (list_type *) MY_GET_TREE_DATA(tree_node_ptr);
MY_NEXT_IN_TREE(tree_node_ptr);
MY_FREE(list_data_ptr->d_buffer);
}
MY_FREE_TREE(recv_tree);
}
/* now free up the col list */
MY_FIRST_IN_TREE(rowtree,node_ptr);
while (! IS_TREE_PTR_NULL(node_ptr)) {
col_list_ptr = (col_list *) MY_GET_TREE_DATA(node_ptr);
MY_NEXT_IN_TREE(node_ptr);
MY_FREE(col_list_ptr->col);
MY_FREE(col_list_ptr->nz);
}
MY_FREE_TREE(rowtree);
MY_FREE_TREE(inode_tree);
BMfinish_comp_msg(comm->from_msg,procinfo); CHKERRN(0);
BMfinish_comp_msg(comm->to_msg,procinfo); CHKERRN(0);
return(0);
}
/*+ BSilu_updt_matrix1 - Update the matrix using a bunch of i-nodes
Input Parameters:
A - The sparse matrix to be factored
colnum - the global column number
rowtree - a data structure that stores the local rows
inode_tree - a data structure that stores the clique index and
inode index for each node
len - the length of the factored col for elimination
updt_index - the indices of the factored colnum
updt_inode - the valuess of the factored colnum
len2 - the length of the factored row
my_inode_ind - the indices of the factored row
my_inode - the values of the factores row
start - dummy
end - dummy
Output Parameters:
I don't really know what these things do now.
Returns:
void
Notes:
This code is very complicated and could be done much better.
I keep most part of the code so that change is minimized. It
is not necessary though. (ILU)
+*/
void BSilu_updt_matrix1(BSpar_mat *A, int colnum, BStree rowtree,
BStree inode_tree, int len, int *updt_index, FLOAT *updt_inode,
int len2, int *my_inode_ind, FLOAT *my_inode, int start, int end,
BScl_2_inode *clique2inode, BSinode *inodes, BSprocinfo *procinfo)
{
int i, j;
int updt_count, offset, toffset;
int cl_ind, in_ind;
BSpermutation *iperm;
FLOAT *work, *matrix;
FLOAT work2;
int *intptr;
FLOAT *nzptr;
int tcount, count2, gnum, size;
int found;
BStree_ptr tree_node_ptr;
int *tree_data_ptr;
int *rowptr, *row_gnum, *g_iperm;
BStree_ptr node_ptr;
col_list *col_list_ptr;
/* sort the updt_inode */
iperm = BSalloc_permutation(len); CHKERR(0);
for (i=0;i<len;i++) iperm->perm[i] = i;
BSheap_sort1(len,updt_index,iperm->perm); CHKERR(0);
MY_MALLOC(work,(FLOAT *),sizeof(FLOAT)*len,1);
BSiperm_dvec(updt_inode,work,iperm); CHKERR(0);
for (j=0;j<len;j++) {
updt_inode[j] = work[j];
}
MY_FREE(work);
BSfree_permutation(iperm); CHKERR(0);
/* The following part is modified (ILU) */
row_gnum = A->global_row_num->numbers;
g_iperm = A->inv_perm->perm;
for (updt_count=0;updt_count<len;updt_count++) {
MY_SEARCH_TREE(inode_tree,updt_index[updt_count],found,tree_node_ptr);
if (found) {
tree_data_ptr = (int *) MY_GET_TREE_DATA(tree_node_ptr);
in_ind = tree_data_ptr[0];
cl_ind = tree_data_ptr[1];
/* make sure the nz are below pivot (ILU) */
if (clique2inode->g_offset[in_ind] > colnum) {
/********** update the inode */
tcount = 0;
count2 = 0;
MY_SEARCH_TREE(rowtree,updt_index[updt_count],found,node_ptr);
if (found) {
col_list_ptr = (col_list *) MY_GET_TREE_DATA(node_ptr);
intptr = col_list_ptr->col;
while ((tcount<len2) && (count2<col_list_ptr->count)) {
if ((my_inode_ind[tcount]==intptr[count2]) &
(intptr[count2] > colnum)) {
/* A is assumed to be structurally symmetric so that the */
/* following tricky searching is ok. (ILU) */
MY_SEARCH_TREE(inode_tree,intptr[count2],found,tree_node_ptr);
tree_data_ptr = (int *) MY_GET_TREE_DATA(tree_node_ptr);
i = tree_data_ptr[0];
nzptr = inodes[i].nz;
rowptr = inodes[i].row_num;
/* search the "colnum"th row (ILU)
for (j1=0; j1<inodes[i].length; j1++)
if (row_gnum[g_iperm[rowptr[j1]]] == colnum) break;
if (j1 == inodes[i].length) {
printf("Error: The matrix is not structurally symmetric!\n");
printf("1: i = %2d, colnum = %2d\n",i,colnum);
} */
/* search the row that we are going to modify (ILU) */
for (j=0; j<inodes[i].length; j++)
if (row_gnum[g_iperm[rowptr[j]]] == updt_index[updt_count])
break;
/* usual Gaussian elimination step (ILU) */
if (j < inodes[i].length)
nzptr[j] -= updt_inode[updt_count]*my_inode[tcount];
MLOG_flop(2);
tcount++;
count2++;
} else if (my_inode_ind[tcount]<intptr[count2]) {
tcount++;
} else {
count2++;
}
}
/* update a protion of the clique */
/***** update the clique (stored in UPPER triangle) */
gnum = clique2inode->g_offset[cl_ind];
offset = updt_index[updt_count]-gnum;
matrix = clique2inode->d_mats[cl_ind].matrix;
size = clique2inode->d_mats[cl_ind].size;
tcount = updt_count;
/* work2 is modified (ILU) */
for (j=0; j<len2; j++)
if (my_inode_ind[j] == gnum) break;
if (j == len2) {
printf("Error: The matrix is not structurally symmetric!\n");
printf("3: i = %2d, colnum = %2d\n",i,colnum);
printf("colnum = %2d\n",colnum);
printf("my_inode_ind :");
for (j=0; j<len2; j++) {
printf(" %2d",my_inode_ind[j]);
if (my_inode_ind[j] == colnum) break;
}
printf("\n");
}
work2 = my_inode[j];
while (tcount < len) {
toffset = updt_index[tcount]-gnum;
if (toffset < size) {
matrix[(toffset*size)+offset] -= work2*updt_inode[tcount];
MLOG_flop(2);
} else {
break;
}
tcount++;
}
/* end of clique update */
}
}
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1