hypre/parcsr_ls/par_schwarz.c
baker59 cbca5f0384 Added the option to not assume the matrix blocks for the Schwarz
smoothers are SPD (this primarily involved adding a new user option
and replacing the LAPACK and ESSL functions that do the inversions
with ones that use LU instead of Cholesky factorizations).

Added the new hypre error checking to Schwarz smoothers.
2008-01-29 23:44:05 +00:00

410 lines
12 KiB
C

/*BHEADER**********************************************************************
* Copyright (c) 2007, Lawrence Livermore National Security, LLC.
* Produced at the Lawrence Livermore National Laboratory.
* Written by the HYPRE team. UCRL-CODE-222953.
* All rights reserved.
*
* This file is part of HYPRE (see http://www.llnl.gov/CASC/hypre/).
* Please see the COPYRIGHT_and_LICENSE file for the copyright notice,
* disclaimer, contact information and the GNU Lesser General Public License.
*
* HYPRE is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License (as published by the Free Software
* Foundation) version 2.1 dated February 1999.
*
* HYPRE is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the terms and conditions of the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Revision$
***********************************************************************EHEADER*/
/******************************************************************************
*
* Schwarz functions
*
*****************************************************************************/
#include "headers.h"
#include "schwarz.h"
/*--------------------------------------------------------------------------
* hypre_SchwarzCreate
*--------------------------------------------------------------------------*/
void *
hypre_SchwarzCreate()
{
hypre_SchwarzData *schwarz_data;
int variant;
int domain_type;
int overlap;
int num_functions;
int use_nonsymm;
double relax_weight;
/*-----------------------------------------------------------------------
* Setup default values for parameters
*-----------------------------------------------------------------------*/
/* setup params */
variant = 0; /* multiplicative Schwarz */
overlap = 1; /* minimal overlap */
domain_type = 2; /* domains generated by agglomeration */
num_functions = 1;
use_nonsymm = 0;
relax_weight = 1.0;
schwarz_data = hypre_CTAlloc(hypre_SchwarzData,1);
hypre_SchwarzSetVariant(schwarz_data, variant);
hypre_SchwarzSetDomainType(schwarz_data, domain_type);
hypre_SchwarzSetOverlap(schwarz_data, overlap);
hypre_SchwarzSetNumFunctions(schwarz_data, num_functions);
hypre_SchwarzSetNonSymm(schwarz_data, use_nonsymm);
hypre_SchwarzSetRelaxWeight(schwarz_data, relax_weight);
hypre_SchwarzDataDomainStructure(schwarz_data) = NULL;
hypre_SchwarzDataABoundary(schwarz_data) = NULL;
hypre_SchwarzDataScale(schwarz_data) = NULL;
hypre_SchwarzDataVtemp(schwarz_data) = NULL;
hypre_SchwarzDataDofFunc(schwarz_data) = NULL;
return (void *) schwarz_data;
}
/*--------------------------------------------------------------------------
* hypre_SchwarzDestroy
*--------------------------------------------------------------------------*/
int
hypre_SchwarzDestroy( void *data )
{
hypre_SchwarzData *schwarz_data = data;
if (hypre_SchwarzDataScale(schwarz_data))
hypre_TFree (hypre_SchwarzDataScale(schwarz_data));
if (hypre_SchwarzDataDofFunc(schwarz_data))
hypre_TFree (hypre_SchwarzDataDofFunc(schwarz_data));
hypre_CSRMatrixDestroy(hypre_SchwarzDataDomainStructure(schwarz_data));
if (hypre_SchwarzDataVariant(schwarz_data) == 3);
hypre_CSRMatrixDestroy(hypre_SchwarzDataABoundary(schwarz_data));
hypre_ParVectorDestroy(hypre_SchwarzDataVtemp(schwarz_data));
if (hypre_SchwarzDataPivots(schwarz_data))
hypre_TFree (hypre_SchwarzDataPivots(schwarz_data));
hypre_TFree(schwarz_data);
return hypre_error_flag;
}
int
hypre_SchwarzSetup(void *schwarz_vdata,
hypre_ParCSRMatrix *A,
hypre_ParVector *f,
hypre_ParVector *u )
{
hypre_SchwarzData *schwarz_data = schwarz_vdata;
int *dof_func;
double *scale;
hypre_CSRMatrix *domain_structure;
hypre_CSRMatrix *A_boundary;
hypre_ParVector *Vtemp;
int *pivots = NULL;
int variant = hypre_SchwarzDataVariant(schwarz_data);
int domain_type = hypre_SchwarzDataDomainType(schwarz_data);
int overlap = hypre_SchwarzDataOverlap(schwarz_data);
int num_functions = hypre_SchwarzDataNumFunctions(schwarz_data);
double relax_weight = hypre_SchwarzDataRelaxWeight(schwarz_data);
int use_nonsymm = hypre_SchwarzDataUseNonSymm(schwarz_data);
dof_func = hypre_SchwarzDataDofFunc(schwarz_data);
Vtemp = hypre_ParVectorCreate(hypre_ParCSRMatrixComm(A),
hypre_ParCSRMatrixGlobalNumRows(A),
hypre_ParCSRMatrixRowStarts(A));
hypre_ParVectorSetPartitioningOwner(Vtemp,0);
hypre_ParVectorInitialize(Vtemp);
hypre_SchwarzDataVtemp(schwarz_data) = Vtemp;
if (variant > 1)
{
hypre_ParAMGCreateDomainDof(A,
domain_type, overlap,
num_functions, dof_func,
&domain_structure, &pivots, use_nonsymm);
if (variant == 2)
{
hypre_ParGenerateScale(A, domain_structure, relax_weight,
&scale);
hypre_SchwarzDataScale(schwarz_data) = scale;
}
else
{
hypre_ParGenerateHybridScale(A, domain_structure, &A_boundary, &scale);
hypre_SchwarzDataScale(schwarz_data) = scale;
if (hypre_CSRMatrixNumCols(hypre_ParCSRMatrixOffd(A)))
hypre_SchwarzDataABoundary(schwarz_data) = A_boundary;
else
hypre_SchwarzDataABoundary(schwarz_data) = NULL;
}
}
else
{
hypre_AMGCreateDomainDof (hypre_ParCSRMatrixDiag(A),
domain_type, overlap,
num_functions, dof_func,
&domain_structure, &pivots, use_nonsymm);
if (variant == 1)
{
hypre_GenerateScale(domain_structure,
hypre_CSRMatrixNumRows(hypre_ParCSRMatrixDiag(A)),
relax_weight, &scale);
hypre_SchwarzDataScale(schwarz_data) = scale;
}
}
hypre_SchwarzDataDomainStructure(schwarz_data) = domain_structure;
hypre_SchwarzDataPivots(schwarz_data) = pivots;
return hypre_error_flag;
}
/*--------------------------------------------------------------------
* hypre_SchwarzSolve
*--------------------------------------------------------------------*/
int
hypre_SchwarzSolve(void *schwarz_vdata,
hypre_ParCSRMatrix *A,
hypre_ParVector *f,
hypre_ParVector *u )
{
hypre_SchwarzData *schwarz_data = schwarz_vdata;
hypre_CSRMatrix *domain_structure =
hypre_SchwarzDataDomainStructure(schwarz_data);
hypre_CSRMatrix *A_boundary = hypre_SchwarzDataABoundary(schwarz_data);
double *scale = hypre_SchwarzDataScale(schwarz_data);
hypre_ParVector *Vtemp = hypre_SchwarzDataVtemp(schwarz_data);
int variant = hypre_SchwarzDataVariant(schwarz_data);
double relax_wt = hypre_SchwarzDataRelaxWeight(schwarz_data);
int use_nonsymm = hypre_SchwarzDataUseNonSymm(schwarz_data);
int *pivots = hypre_SchwarzDataPivots(schwarz_data);
if (variant == 2)
{
hypre_ParAdSchwarzSolve(A, f, domain_structure, scale, u, Vtemp, pivots, use_nonsymm);
}
else if (variant == 3)
{
hypre_ParMPSchwarzSolve(A, A_boundary, f, domain_structure, u,
relax_wt, scale, Vtemp, pivots, use_nonsymm);
}
else if (variant == 1)
{
hypre_AdSchwarzSolve(A, f, domain_structure, scale, u, Vtemp, pivots, use_nonsymm);
}
else if (variant == 4)
{
hypre_MPSchwarzFWSolve(A, hypre_ParVectorLocalVector(f),
domain_structure, u, relax_wt,
hypre_ParVectorLocalVector(Vtemp), pivots, use_nonsymm);
}
else
{
hypre_MPSchwarzSolve(A, hypre_ParVectorLocalVector(f),
domain_structure, u, relax_wt,
hypre_ParVectorLocalVector(Vtemp), pivots, use_nonsymm);
}
return hypre_error_flag;
}
/*--------------------------------------------------------------------
* hypre_SchwarzCFSolve
*--------------------------------------------------------------------*/
int
hypre_SchwarzCFSolve(void *schwarz_vdata,
hypre_ParCSRMatrix *A,
hypre_ParVector *f,
hypre_ParVector *u,
int *CF_marker,
int rlx_pt)
{
hypre_SchwarzData *schwarz_data = schwarz_vdata;
hypre_CSRMatrix *domain_structure =
hypre_SchwarzDataDomainStructure(schwarz_data);
double *scale = hypre_SchwarzDataScale(schwarz_data);
hypre_ParVector *Vtemp = hypre_SchwarzDataVtemp(schwarz_data);
int variant = hypre_SchwarzDataVariant(schwarz_data);
double relax_wt = hypre_SchwarzDataRelaxWeight(schwarz_data);
int use_nonsymm = hypre_SchwarzDataUseNonSymm(schwarz_data);
int *pivots = hypre_SchwarzDataPivots(schwarz_data);
if (variant == 1)
{
hypre_AdSchwarzCFSolve(A, f, domain_structure, scale, u, Vtemp,
CF_marker, rlx_pt, pivots, use_nonsymm);
}
else if (variant == 4)
{
hypre_MPSchwarzCFFWSolve(A, hypre_ParVectorLocalVector(f),
domain_structure, u, relax_wt,
hypre_ParVectorLocalVector(Vtemp),
CF_marker, rlx_pt, pivots, use_nonsymm);
}
else
{
hypre_MPSchwarzCFSolve(A, hypre_ParVectorLocalVector(f),
domain_structure, u, relax_wt,
hypre_ParVectorLocalVector(Vtemp),
CF_marker, rlx_pt, pivots, use_nonsymm);
}
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* Routines to set various parameters
*--------------------------------------------------------------------------*/
int
hypre_SchwarzSetVariant( void *data, int variant )
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataVariant(schwarz_data) = variant;
return hypre_error_flag;
}
int
hypre_SchwarzSetDomainType( void *data, int domain_type )
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataDomainType(schwarz_data) = domain_type;
return hypre_error_flag;
}
int
hypre_SchwarzSetOverlap( void *data, int overlap )
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataOverlap(schwarz_data) = overlap;
return hypre_error_flag;
}
int
hypre_SchwarzSetNumFunctions( void *data, int num_functions )
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataNumFunctions(schwarz_data) = num_functions;
return hypre_error_flag;
}
int
hypre_SchwarzSetNonSymm( void *data, int value )
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataUseNonSymm(schwarz_data) = value;
return hypre_error_flag;
}
int
hypre_SchwarzSetRelaxWeight( void *data, double relax_weight )
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataRelaxWeight(schwarz_data) = relax_weight;
return hypre_error_flag;
}
int
hypre_SchwarzSetDomainStructure( void *data, hypre_CSRMatrix *domain_structure )
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataDomainStructure(schwarz_data) = domain_structure;
return hypre_error_flag;
}
int
hypre_SchwarzSetScale( void *data, double *scale)
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataScale(schwarz_data) = scale;
return hypre_error_flag;
}
int
hypre_SchwarzReScale( void *data, int size, double value)
{
int i;
double *scale;
hypre_SchwarzData *schwarz_data = data;
scale = hypre_SchwarzDataScale(schwarz_data);
for (i=0; i < size; i++)
scale[i] *= value;
return hypre_error_flag;
}
int
hypre_SchwarzSetDofFunc( void *data, int *dof_func)
{
hypre_SchwarzData *schwarz_data = data;
hypre_SchwarzDataDofFunc(schwarz_data) = dof_func;
return hypre_error_flag;
}