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.
410 lines
12 KiB
C
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;
|
|
}
|
|
|