hypre/seq_mv/csr_matop.c
2000-01-08 20:00:04 +00:00

282 lines
6.8 KiB
C

/*BHEADER**********************************************************************
* (c) 1998 The Regents of the University of California
*
* See the file COPYRIGHT_and_DISCLAIMER for a complete copyright
* notice, contact person, and disclaimer.
*
* $Revision$
*********************************************************************EHEADER*/
/******************************************************************************
*
* Matrix operation functions for hypre_CSRMatrix class.
*
*****************************************************************************/
#include "headers.h"
/*--------------------------------------------------------------------------
* hypre_CSRMatrixAdd:
* adds two CSR Matrices A and B and returns a CSR Matrix C;
* Note: The routine does not check for 0-elements which might be generated
* through cancellation of elements in A and B or already contained
in A and B. To remove those, use hypre_CSRMatrixDeleteZeros
*--------------------------------------------------------------------------*/
hypre_CSRMatrix *
hypre_CSRMatrixAdd( hypre_CSRMatrix *A,
hypre_CSRMatrix *B)
{
double *A_data = hypre_CSRMatrixData(A);
int *A_i = hypre_CSRMatrixI(A);
int *A_j = hypre_CSRMatrixJ(A);
int nrows_A = hypre_CSRMatrixNumRows(A);
int ncols_A = hypre_CSRMatrixNumCols(A);
double *B_data = hypre_CSRMatrixData(B);
int *B_i = hypre_CSRMatrixI(B);
int *B_j = hypre_CSRMatrixJ(B);
int nrows_B = hypre_CSRMatrixNumRows(B);
int ncols_B = hypre_CSRMatrixNumCols(B);
hypre_CSRMatrix *C;
double *C_data;
int *C_i;
int *C_j;
int ia, ib, ic, jcol, num_nonzeros;
int pos;
int *marker;
if (nrows_A != nrows_B || ncols_A != ncols_B)
{
printf("Warning! incompatible matrix dimensions!\n");
return NULL;
}
marker = hypre_CTAlloc(int, ncols_A);
C_i = hypre_CTAlloc(int, nrows_A+1);
for (ia = 0; ia < ncols_A; ia++)
marker[ia] = -1;
num_nonzeros = 0;
C_i[0] = 0;
for (ic = 0; ic < nrows_A; ic++)
{
for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
{
jcol = A_j[ia];
marker[jcol] = ic;
num_nonzeros++;
}
for (ib = B_i[ic]; ib < B_i[ic+1]; ib++)
{
jcol = B_j[ib];
if (marker[jcol] != ic)
{
marker[jcol] = ic;
num_nonzeros++;
}
}
C_i[ic+1] = num_nonzeros;
}
C = hypre_CSRMatrixCreate(nrows_A, ncols_A, num_nonzeros);
hypre_CSRMatrixI(C) = C_i;
hypre_CSRMatrixInitialize(C);
C_j = hypre_CSRMatrixJ(C);
C_data = hypre_CSRMatrixData(C);
for (ia = 0; ia < ncols_A; ia++)
marker[ia] = -1;
pos = 0;
for (ic = 0; ic < nrows_A; ic++)
{
for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
{
jcol = A_j[ia];
C_j[pos] = jcol;
C_data[pos] = A_data[ia];
marker[jcol] = pos;
pos++;
}
for (ib = B_i[ic]; ib < B_i[ic+1]; ib++)
{
jcol = B_j[ib];
if (marker[jcol] < C_i[ic])
{
C_j[pos] = jcol;
C_data[pos] = B_data[ib];
marker[jcol] = pos;
pos++;
}
else
{
C_data[marker[jcol]] += B_data[ib];
}
}
}
hypre_TFree(marker);
return C;
}
/*--------------------------------------------------------------------------
* hypre_CSRMatrixMultiply
* multiplies two CSR Matrices A and B and returns a CSR Matrix C;
* Note: The routine does not check for 0-elements which might be generated
* through cancellation of elements in A and B or already contained
in A and B. To remove those, use hypre_CSRMatrixDeleteZeros
*--------------------------------------------------------------------------*/
hypre_CSRMatrix *
hypre_CSRMatrixMultiply( hypre_CSRMatrix *A,
hypre_CSRMatrix *B)
{
double *A_data = hypre_CSRMatrixData(A);
int *A_i = hypre_CSRMatrixI(A);
int *A_j = hypre_CSRMatrixJ(A);
int nrows_A = hypre_CSRMatrixNumRows(A);
int ncols_A = hypre_CSRMatrixNumCols(A);
double *B_data = hypre_CSRMatrixData(B);
int *B_i = hypre_CSRMatrixI(B);
int *B_j = hypre_CSRMatrixJ(B);
int nrows_B = hypre_CSRMatrixNumRows(B);
int ncols_B = hypre_CSRMatrixNumCols(B);
hypre_CSRMatrix *C;
double *C_data;
int *C_i;
int *C_j;
int ia, ib, ic, ja, jb, num_nonzeros=0;
int row_start, counter;
double a_entry, b_entry;
int *B_marker;
if (ncols_A != nrows_B)
{
printf("Warning! incompatible matrix dimensions!\n");
return NULL;
}
B_marker = hypre_CTAlloc(int, ncols_B);
C_i = hypre_CTAlloc(int, nrows_A+1);
for (ib = 0; ib < ncols_B; ib++)
B_marker[ib] = -1;
for (ic = 0; ic < nrows_A; ic++)
{
for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
{
ja = A_j[ia];
for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
{
jb = B_j[ib];
if (B_marker[jb] != ic)
{
B_marker[jb] = ic;
num_nonzeros++;
}
}
C_i[ic+1] = num_nonzeros;
}
}
C = hypre_CSRMatrixCreate(nrows_A, ncols_B, num_nonzeros);
hypre_CSRMatrixI(C) = C_i;
hypre_CSRMatrixInitialize(C);
C_j = hypre_CSRMatrixJ(C);
C_data = hypre_CSRMatrixData(C);
for (ib = 0; ib < ncols_B; ib++)
B_marker[ib] = -1;
counter = 0;
for (ic = 0; ic < nrows_A; ic++)
{
row_start = C_i[ic];
for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
{
ja = A_j[ia];
a_entry = A_data[ia];
for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
{
jb = B_j[ib];
b_entry = B_data[ib];
if (B_marker[jb] < row_start)
{
B_marker[jb] = counter;
C_j[B_marker[jb]] = jb;
C_data[B_marker[jb]] = a_entry*b_entry;
counter++;
}
else
C_data[B_marker[jb]] += a_entry*b_entry;
}
}
}
hypre_TFree(B_marker);
return C;
}
hypre_CSRMatrix *
hypre_CSRMatrixDeleteZeros( hypre_CSRMatrix *A, double tol)
{
double *A_data = hypre_CSRMatrixData(A);
int *A_i = hypre_CSRMatrixI(A);
int *A_j = hypre_CSRMatrixJ(A);
int nrows_A = hypre_CSRMatrixNumRows(A);
int ncols_A = hypre_CSRMatrixNumCols(A);
int num_nonzeros = hypre_CSRMatrixNumNonzeros(A);
hypre_CSRMatrix *B;
double *B_data;
int *B_i;
int *B_j;
int zeros;
int i, j;
int pos_A, pos_B;
zeros = 0;
for (i=0; i < num_nonzeros; i++)
if (fabs(A_data[i]) <= tol)
zeros++;
if (zeros)
{
B = hypre_CSRMatrixCreate(nrows_A,ncols_A,num_nonzeros-zeros);
hypre_CSRMatrixInitialize(B);
B_i = hypre_CSRMatrixI(B);
B_j = hypre_CSRMatrixJ(B);
B_data = hypre_CSRMatrixData(B);
B_i[0] = 0;
pos_A = 0;
pos_B = 0;
for (i=0; i < nrows_A; i++)
{
for (j = A_i[i]; j < A_i[i+1]; j++)
{
if (fabs(A_data[j]) <= tol)
{
pos_A++;
}
else
{
B_data[pos_B] = A_data[pos_A];
B_j[pos_B] = A_j[pos_A];
pos_B++;
pos_A++;
}
}
B_i[i+1] = pos_B;
}
return B;
}
else
return NULL;
}