213 lines
6.9 KiB
C
213 lines
6.9 KiB
C
/*BHEADER**********************************************************************
|
|
* (c) 1997 The Regents of the University of California
|
|
*
|
|
* See the file COPYRIGHT_and_DISCLAIMER for a complete copyright
|
|
* notice, contact person, and disclaimer.
|
|
*
|
|
* $Revision$
|
|
*********************************************************************EHEADER*/
|
|
/******************************************************************************
|
|
*
|
|
* Constructors and destructors for stencil structure.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "headers.h"
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_StructStencilCreate
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
hypre_StructStencil *
|
|
hypre_StructStencilCreate( int dim,
|
|
int size,
|
|
hypre_Index *shape )
|
|
{
|
|
hypre_StructStencil *stencil;
|
|
|
|
int abs_offset;
|
|
int max_offset;
|
|
int s, d;
|
|
|
|
stencil = hypre_TAlloc(hypre_StructStencil, 1);
|
|
|
|
hypre_StructStencilShape(stencil) = shape;
|
|
hypre_StructStencilSize(stencil) = size;
|
|
hypre_StructStencilDim(stencil) = dim;
|
|
hypre_StructStencilRefCount(stencil) = 1;
|
|
|
|
/* compute max_offset */
|
|
max_offset = 0;
|
|
for (s = 0; s < size; s++)
|
|
{
|
|
for (d = 0; d < 3; d++)
|
|
{
|
|
abs_offset = hypre_IndexD(shape[s], d);
|
|
abs_offset = (abs_offset < 0) ? -abs_offset : abs_offset;
|
|
max_offset = hypre_max(abs_offset, max_offset);
|
|
}
|
|
}
|
|
hypre_StructStencilMaxOffset(stencil) = max_offset;
|
|
|
|
return stencil;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_StructStencilRef
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
hypre_StructStencil *
|
|
hypre_StructStencilRef( hypre_StructStencil *stencil )
|
|
{
|
|
hypre_StructStencilRefCount(stencil) ++;
|
|
|
|
return stencil;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_StructStencilDestroy
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_StructStencilDestroy( hypre_StructStencil *stencil )
|
|
{
|
|
int ierr = 0;
|
|
|
|
if (stencil)
|
|
{
|
|
hypre_StructStencilRefCount(stencil) --;
|
|
if (hypre_StructStencilRefCount(stencil) == 0)
|
|
{
|
|
hypre_TFree(hypre_StructStencilShape(stencil));
|
|
hypre_TFree(stencil);
|
|
}
|
|
}
|
|
|
|
return ierr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_StructStencilElementRank
|
|
* Returns the rank of the `stencil_element' in `stencil'.
|
|
* If the element is not found, a -1 is returned.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_StructStencilElementRank( hypre_StructStencil *stencil,
|
|
hypre_Index stencil_element )
|
|
{
|
|
hypre_Index *stencil_shape;
|
|
int rank;
|
|
int i;
|
|
|
|
rank = -1;
|
|
stencil_shape = hypre_StructStencilShape(stencil);
|
|
for (i = 0; i < hypre_StructStencilSize(stencil); i++)
|
|
{
|
|
if ((hypre_IndexX(stencil_shape[i]) == hypre_IndexX(stencil_element)) &&
|
|
(hypre_IndexY(stencil_shape[i]) == hypre_IndexY(stencil_element)) &&
|
|
(hypre_IndexZ(stencil_shape[i]) == hypre_IndexZ(stencil_element)) )
|
|
{
|
|
rank = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return rank;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_StructStencilSymmetrize:
|
|
* Computes a new "symmetrized" stencil.
|
|
*
|
|
* An integer array called `symm_elements' is also set up. A non-negative
|
|
* value of `symm_elements[i]' indicates that the `i'th stencil element
|
|
* is a "symmetric element". That is, this stencil element is the
|
|
* transpose element of an element that is not a "symmetric element".
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_StructStencilSymmetrize( hypre_StructStencil *stencil,
|
|
hypre_StructStencil **symm_stencil_ptr,
|
|
int **symm_elements_ptr )
|
|
{
|
|
hypre_Index *stencil_shape = hypre_StructStencilShape(stencil);
|
|
int stencil_size = hypre_StructStencilSize(stencil);
|
|
|
|
hypre_StructStencil *symm_stencil;
|
|
hypre_Index *symm_stencil_shape;
|
|
int symm_stencil_size;
|
|
int *symm_elements;
|
|
|
|
int no_symmetric_stencil_element;
|
|
int i, j, d;
|
|
|
|
int ierr = 0;
|
|
|
|
/*------------------------------------------------------
|
|
* Copy stencil elements into `symm_stencil_shape'
|
|
*------------------------------------------------------*/
|
|
|
|
symm_stencil_shape = hypre_CTAlloc(hypre_Index, 2*stencil_size);
|
|
for (i = 0; i < stencil_size; i++)
|
|
{
|
|
hypre_CopyIndex(stencil_shape[i], symm_stencil_shape[i]);
|
|
}
|
|
|
|
/*------------------------------------------------------
|
|
* Create symmetric stencil elements and `symm_elements'
|
|
*------------------------------------------------------*/
|
|
|
|
symm_elements = hypre_CTAlloc(int, 2*stencil_size);
|
|
for (i = 0; i < 2*stencil_size; i++)
|
|
symm_elements[i] = -1;
|
|
|
|
symm_stencil_size = stencil_size;
|
|
for (i = 0; i < stencil_size; i++)
|
|
{
|
|
if (symm_elements[i] < 0)
|
|
{
|
|
/* note: start at i to handle "center" element correctly */
|
|
no_symmetric_stencil_element = 1;
|
|
for (j = i; j < stencil_size; j++)
|
|
{
|
|
if ( (hypre_IndexX(symm_stencil_shape[j]) ==
|
|
-hypre_IndexX(symm_stencil_shape[i]) ) &&
|
|
(hypre_IndexY(symm_stencil_shape[j]) ==
|
|
-hypre_IndexY(symm_stencil_shape[i]) ) &&
|
|
(hypre_IndexZ(symm_stencil_shape[j]) ==
|
|
-hypre_IndexZ(symm_stencil_shape[i]) ) )
|
|
{
|
|
/* only "off-center" elements have symmetric entries */
|
|
if (i != j)
|
|
symm_elements[j] = i;
|
|
no_symmetric_stencil_element = 0;
|
|
}
|
|
}
|
|
|
|
if (no_symmetric_stencil_element)
|
|
{
|
|
/* add symmetric stencil element to `symm_stencil' */
|
|
for (d = 0; d < 3; d++)
|
|
{
|
|
hypre_IndexD(symm_stencil_shape[symm_stencil_size], d) =
|
|
-hypre_IndexD(symm_stencil_shape[i], d);
|
|
}
|
|
|
|
symm_elements[symm_stencil_size] = i;
|
|
symm_stencil_size++;
|
|
}
|
|
}
|
|
}
|
|
|
|
symm_stencil = hypre_StructStencilCreate(hypre_StructStencilDim(stencil),
|
|
symm_stencil_size,
|
|
symm_stencil_shape);
|
|
|
|
*symm_stencil_ptr = symm_stencil;
|
|
*symm_elements_ptr = symm_elements;
|
|
|
|
return ierr;
|
|
}
|
|
|