#include "BSprivate.h"
/*@ BSscale_diag - Symmetrically scale the matrix by a diagonal matrix
Input Parameters:
. A - a sparse matrix
. sc_diag - the diagonal matrix (stored as a vector) to scale A by
. procinfo - the usual processor stuff
Output Parameters:
. A - a sparse matrix scaled by a diagonal matrix
Returns:
void
@*/
void BSscale_diag(BSpar_mat *A, FLOAT *sc_diag, BSprocinfo *procinfo)
{
int count, size;
BSbb_d *diag_bb;
int *addrs;
FLOAT *answs;
int cl_ind, in_ind;
BSinode *inodes;
BScl_2_inode *cliques;
int i, j;
FLOAT *p_diag;
FLOAT rdiag, cdiag;
int *inv_perm;
int loc_ind;
FLOAT *matrix, *nz;
int *row_num;
/* set scale_diag for A */
A->scale_diag = sc_diag;
/* release save_diag if same as scaling since diag will be one after this */
if(A->save_diag==sc_diag) A->save_diag=NULL;
/* find the request size */
/* by counting the # of rows and subtracting the number of local rows */
inodes = A->inodes->list;
count = 0;
for (in_ind=0;in_ind<A->inodes->length;in_ind++) {
count+=inodes[in_ind].num_cols;
}
count -= A->num_rows;
/* allocate and build query */
MY_MALLOC(addrs,(int *),sizeof(int)*count,1);
count = 0;
cliques = A->clique2inode;
for (cl_ind=0;cl_ind<cliques->num_cols;cl_ind++) {
if (cliques->proc[cl_ind] != procinfo->my_id) {
for (in_ind=cliques->inode_index[cl_ind];
in_ind<cliques->inode_index[cl_ind+1];in_ind++) {
for (i=0;i<inodes[in_ind].num_cols;i++) {
addrs[count] = inodes[in_ind].o_gcol_num[i];
count++;
}
}
}
}
/* get an inversely permuted copy of the diagonal */
MY_MALLOC(p_diag,(FLOAT *),sizeof(FLOAT)*A->num_rows,2);
BSperm_dvec(sc_diag,p_diag,A->inv_perm); CHKERR(0);
if(A->icc_storage) {
for (i=0;i<A->num_rows;i++) p_diag[i] = sqrt(p_diag[i]);
} else {
/* We should take absolute value first before taking sqrt (ILU) */
for (i=0;i<A->num_rows;i++) p_diag[i] = sqrt(fabs(p_diag[i]));
}
/* set up bulletin board and do query */
diag_bb = BSinit_bb_d(A->num_rows,A->map); CHKERR(0);
BSpost_noaddr_bb_d(diag_bb,A->num_rows,p_diag); CHKERR(0);
MY_MALLOC(answs,(FLOAT *),sizeof(FLOAT)*count,3);
BSquery_nomatch_bb_d(diag_bb,count,addrs,answs,procinfo); CHKERR(0);
BSfree_bb_d(diag_bb); CHKERR(0);
MY_FREE(addrs);
/* now, do the scaling */
inv_perm = A->inv_perm->perm;
count = 0;
for (cl_ind=0;cl_ind<cliques->num_cols;cl_ind++) {
if (cliques->proc[cl_ind] == procinfo->my_id) {
/* first, do dense block */
loc_ind = cliques->d_mats[cl_ind].local_ind;
size = cliques->d_mats[cl_ind].size;
matrix = cliques->d_mats[cl_ind].matrix;
for (i=0;i<size;i++) {
cdiag = p_diag[inv_perm[loc_ind+i]];
if (cdiag == 0.0) cdiag = 1.0;
if(A->icc_storage) {
for (j=i;j<size;j++) {
rdiag = p_diag[inv_perm[loc_ind+j]];
if (rdiag == 0.0) rdiag = 1.0;
matrix[(i*size)+j] /= (cdiag*rdiag);
}
} else {
for (j=0;j<size;j++) {
rdiag = p_diag[inv_perm[loc_ind+j]];
if (rdiag == 0.0) rdiag = 1.0;
matrix[(i*size)+j] /= (cdiag*rdiag);
}
}
}
for (in_ind=cliques->inode_index[cl_ind];
in_ind<cliques->inode_index[cl_ind+1];in_ind++) {
row_num = inodes[in_ind].row_num;
nz = inodes[in_ind].nz;
size = inodes[in_ind].length;
for (i=0;i<inodes[in_ind].num_cols;i++) {
rdiag = p_diag[inv_perm[loc_ind]];
if (rdiag == 0.0) rdiag = 1.0;
loc_ind++;
for (j=0;j<size;j++) {
cdiag = p_diag[inv_perm[row_num[j]]];
if (cdiag == 0.0) cdiag = 1.0;
nz[(i*size)+j] /= (rdiag*cdiag);
}
}
}
} else {
for (in_ind=cliques->inode_index[cl_ind];
in_ind<cliques->inode_index[cl_ind+1];in_ind++) {
row_num = inodes[in_ind].row_num;
nz = inodes[in_ind].nz;
size = inodes[in_ind].length;
for (i=0;i<inodes[in_ind].num_cols;i++) {
rdiag = answs[count];
if (rdiag == 0.0) rdiag = 1.0;
count++;
for (j=0;j<size;j++) {
cdiag = p_diag[inv_perm[row_num[j]]];
if (cdiag == 0.0) cdiag = 1.0;
nz[(i*size)+j] /= (rdiag*cdiag);
}
}
}
}
}
MY_FREE(answs);
MY_FREE(p_diag);
}
syntax highlighted by Code2HTML, v. 0.9.1