hypre/parcsr_block_mv/csr_block_matop.c
falgout 46488e8cbc Added HYPRE_Complex and HYPRE_Real types in place of double.
Added an example code to test CG on a 4D HYPRE_SSTRUCT complex problem.
Added regression tests for bigint, maxdim, and complex.
Added a test to make sure double types are not added to the source.
See [Issue995] in the tracker for more details.
2013-10-11 19:48:06 +00:00

242 lines
7.8 KiB
C

/*BHEADER**********************************************************************
* Copyright (c) 2008, Lawrence Livermore National Security, LLC.
* Produced at the Lawrence Livermore National Laboratory.
* This file is part of HYPRE. See file COPYRIGHT for details.
*
* HYPRE is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License (as published by the Free
* Software Foundation) version 2.1 dated February 1999.
*
* $Revision$
***********************************************************************EHEADER*/
/******************************************************************************
*
* Matrix operation functions for hypre_CSRMatrix class.
*
*****************************************************************************/
/*--------------------------------------------------------------------------
* 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_CSRBlockMatrix *
hypre_CSRBlockMatrixAdd(hypre_CSRBlockMatrix *A, hypre_CSRBlockMatrix *B)
{
HYPRE_Complex *A_data = hypre_CSRMatrixData(A);
HYPRE_Int *A_i = hypre_CSRMatrixI(A);
HYPRE_Int *A_j = hypre_CSRMatrixJ(A);
HYPRE_Int nrows_A = hypre_CSRMatrixNumRows(A);
HYPRE_Int ncols_A = hypre_CSRMatrixNumCols(A);
HYPRE_Complex *B_data = hypre_CSRMatrixData(B);
HYPRE_Int *B_i = hypre_CSRMatrixI(B);
HYPRE_Int *B_j = hypre_CSRMatrixJ(B);
HYPRE_Int nrows_B = hypre_CSRMatrixNumRows(B);
HYPRE_Int ncols_B = hypre_CSRMatrixNumCols(B);
hypre_CSRMatrix *C;
HYPRE_Complex *C_data;
HYPRE_Int *C_i;
HYPRE_Int *C_j;
HYPRE_Int block_size = hypre_CSRBlockMatrixBlockSize(A);
HYPRE_Int block_sizeB = hypre_CSRBlockMatrixBlockSize(B);
HYPRE_Int ia, ib, ic, ii, jcol, num_nonzeros, bnnz;
HYPRE_Int pos;
HYPRE_Int *marker;
if (nrows_A != nrows_B || ncols_A != ncols_B)
{
hypre_printf("Warning! incompatible matrix dimensions!\n");
return NULL;
}
if (block_size != block_sizeB)
{
hypre_printf("Warning! incompatible matrix block size!\n");
return NULL;
}
bnnz = block_size * block_size;
marker = hypre_CTAlloc(HYPRE_Int, ncols_A);
C_i = hypre_CTAlloc(HYPRE_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_CSRBlockMatrixCreate(block_size,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;
for (ii = 0; ii < bnnz; ii++)
C_data[pos*bnnz+ii] = A_data[ia*bnnz+ii];
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;
for (ii = 0; ii < bnnz; ii++)
C_data[pos*bnnz+ii] = B_data[ib*bnnz+ii];
marker[jcol] = pos;
pos++;
}
else
{
for (ii = 0; ii < bnnz; ii++)
C_data[marker[jcol]*bnnz+ii] = B_data[ib*bnnz+ii];
}
}
}
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_CSRBlockMatrix *
hypre_CSRBlockMatrixMultiply(hypre_CSRBlockMatrix *A, hypre_CSRBlockMatrix *B)
{
HYPRE_Complex *A_data = hypre_CSRMatrixData(A);
HYPRE_Int *A_i = hypre_CSRMatrixI(A);
HYPRE_Int *A_j = hypre_CSRMatrixJ(A);
HYPRE_Int nrows_A = hypre_CSRMatrixNumRows(A);
HYPRE_Int ncols_A = hypre_CSRMatrixNumCols(A);
HYPRE_Int block_size = hypre_CSRBlockMatrixBlockSize(A);
HYPRE_Complex *B_data = hypre_CSRMatrixData(B);
HYPRE_Int *B_i = hypre_CSRMatrixI(B);
HYPRE_Int *B_j = hypre_CSRMatrixJ(B);
HYPRE_Int nrows_B = hypre_CSRMatrixNumRows(B);
HYPRE_Int ncols_B = hypre_CSRMatrixNumCols(B);
HYPRE_Int block_sizeB = hypre_CSRBlockMatrixBlockSize(B);
hypre_CSRMatrix *C;
HYPRE_Complex *C_data;
HYPRE_Int *C_i;
HYPRE_Int *C_j;
HYPRE_Int ia, ib, ic, ja, jb, num_nonzeros=0, bnnz;
HYPRE_Int row_start, counter;
HYPRE_Complex *a_entries, *b_entries, *c_entries, dzero=0.0, done=1.0;
HYPRE_Int *B_marker;
if (ncols_A != nrows_B)
{
hypre_printf("Warning! incompatible matrix dimensions!\n");
return NULL;
}
if (block_size != block_sizeB)
{
hypre_printf("Warning! incompatible matrix block size!\n");
return NULL;
}
bnnz = block_size * block_size;
B_marker = hypre_CTAlloc(HYPRE_Int, ncols_B);
C_i = hypre_CTAlloc(HYPRE_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_CSRBlockMatrixCreate(block_size,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_entries = &(A_data[ia*bnnz]);
for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
{
jb = B_j[ib];
b_entries = &(B_data[ib*bnnz]);
if (B_marker[jb] < row_start)
{
B_marker[jb] = counter;
C_j[B_marker[jb]] = jb;
c_entries = &(C_data[B_marker[jb]*bnnz]);
hypre_CSRBlockMatrixBlockMultAdd(a_entries,b_entries,dzero,
c_entries, block_size);
counter++;
}
else
{
c_entries = &(C_data[B_marker[jb]*bnnz]);
hypre_CSRBlockMatrixBlockMultAdd(a_entries,b_entries,done,
c_entries, block_size);
}
}
}
}
hypre_TFree(B_marker);
return C;
}