ccseapps-2.5/ 0000755 0001750 0001750 00000000000 11634153217 014316 5 ustar amckinstry amckinstry ccseapps-2.5/NOTES 0000644 0001750 0001750 00000001265 11634153073 015135 0 ustar amckinstry amckinstry
From Akira:
Akira has mucked with the header files. The reason for this is as follows:
-> The serial build of Boxlib fakes MPI under the covers
-> When we try to build an AVT boxlib reader, a parallel version of the reader
is built.
-> That reader links against MPI, which conflicts with the way the Boxlib
library fakes MPI under the covers.
-> Problems emerge.
So use Akira's headers.
As far as building Boxlib:
-> Untar the tarball in this directory.
-> Go to the Boxlib subdirectory and modify the GNUmakefile.
-> It will figure out the platform, etc.
-> You pretty much just need to specify the dimension.
-> Rename the library to be something like libbox2D.a or libbox3D.a
ccseapps-2.5/CCSEApps/ 0000755 0001750 0001750 00000000000 11634153073 015657 5 ustar amckinstry amckinstry ccseapps-2.5/CCSEApps/mglib/ 0000755 0001750 0001750 00000000000 11634153073 016751 5 ustar amckinstry amckinstry ccseapps-2.5/CCSEApps/mglib/Banner.html 0000644 0001750 0001750 00000000567 11634153073 021054 0 ustar amckinstry amckinstry
Problems with this Web page should be sent to webmaster@mothra.lbl.gov
Bugs in the software should be sent to guthamr-bugs@mothra.lbl.gov
(C)opyright by Lawrence Berkeley National Laboratory
ccseapps-2.5/CCSEApps/mglib/Make.package 0000644 0001750 0001750 00000001562 11634153073 021147 0 ustar amckinstry amckinstry #
# $Id: Make.package,v 1.2 1999/04/01 21:43:11 car Exp $
#
MGLIB_BASE=EXE
ifeq ($(LBASE),mg)
MGLIB_BASE=LIB
endif
C$(MGLIB_BASE)_sources += ABecLaplacian.cpp BndryData.cpp CGSolver.cpp \
InterpBndryData.cpp LinOp.cpp \
Mask.cpp MultiGrid.cpp
C$(MGLIB_BASE)_sources += Laplacian.cpp
C$(MGLIB_BASE)_headers += ABecLaplacian.H BndryData.H BoundCond.H \
CGSolver.H InterpBndryData.H LO_BCTYPES.H \
LinOp.H Mask.H MultiGrid.H
C$(MGLIB_BASE)_headers += Laplacian.H
F$(MGLIB_BASE)_headers += ABec_F.H CG_F.H INTERPBNDRYDATA_F.H LO_F.H \
LP_F.H MG_F.H
F$(MGLIB_BASE)_sources += ABec_$(DIM)D.F ABec_UTIL.F CG_$(DIM)D.F \
INTERPBNDRYDATA_$(DIM)D.F LO_$(DIM)D.F \
LO_UTIL.F LP_$(DIM)D.F MG_$(DIM)D.F
ccseapps-2.5/CCSEApps/mglib/InterpBndryData.H 0000644 0001750 0001750 00000014314 11634153073 022117 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
#ifndef _INTERPBNDRYDATA_H_
#define _INTERPBNDRYDATA_H_
//
// $Id: InterpBndryData.H,v 1.8 2000/10/02 20:51:16 lijewski Exp $
//
#include
#include
#include
#include
#include
#include
#include
#include
//@Man:
/*@Memo:
An InterpBndryData object adds to a BndryData object the ability to
manipulate and set the data stored in the boundary cells.
*/
/*@Doc:
The "Interpbndrydata" class is a virtual base class derived from
BndryData. It is intended to provide a more physical method for
filling boundary-related data. Boundary values in a BndryData object
are stored in FabSets around each grid in the domain, and the
InterpBndryData class provides a mechanism for filling these FabSets,
consistent with AMR-like numerical discretizations. When asked to
set it's boundary values, an InterpBndryData object:
\begin{enumerate}
\item Fills with physical boundary values if the FAB is on the
domain boundary ({\it the corresponding values are presumed to be
stored in the ghost cells of a MultiFab given to the boundary filling
routine})
\item Fills on intersection with data from the VALID region of the
input MultiFab, ensuring that adjacent FABs use consistent data at
their intersection, and otherwise,
\item Fills with values interpolated from a coarser FAB that
bounds the cells that do not meet the above two criteria
\end{enumerate}
This class does NOT provide a copy constructor or assignment operator.
*/
class InterpBndryData
:
public BndryData
{
public:
//
//@ManDoc: default constructor
//
InterpBndryData ()
:
BndryData() {}
//
//@ManDoc: constructor for given BoxArray, etc
//
InterpBndryData (const BoxArray& _grids,
int _ncomp,
const Geometry& geom);
//
//@ManDoc: Copy constructor.
//
InterpBndryData (const InterpBndryData& rhs) : BndryData(rhs) {}
//
//@ManDoc: Copy assignment operator.
//
InterpBndryData& operator= (const InterpBndryData& rhs)
{
if (!(this == &rhs))
{
BndryData::operator=(rhs);
}
return *this;
}
//
//@ManDoc: interpret user BCs to those expected by LinOp: takes integer ratio and
// is a wrapper to the IntVect version
//
void setBndryConds (const BCRec& phys_bc,
int ratio);
//
//@ManDoc: interpret user BCs to those expected by LinOp: takes IntVect ratio
//
virtual void setBndryConds (const BCRec& phys_bc,
IntVect& ratio,
int comp=0) = 0;
//
//@ManDoc: set bndry values at coarse level (non interpolation performed)
//
void setBndryValues (const MultiFab& mf,
int mf_start,
int bnd_start,
int num_comp,
const BCRec& phys_bc);
//
//@ManDoc: set bndry values at fine level, performing necessary interpolations
//
void setBndryValues (::BndryRegister& crse,
int c_start,
const MultiFab& fine,
int f_start,
int bnd_start,
int num_comp,
int ratio,
const BCRec& phys_bc);
//
//@ManDoc: set bndry values at fine level, performing necessary interpolations
//
void setBndryValues (::BndryRegister& crse,
int c_start,
const MultiFab& fine,
int f_start,
int bnd_start,
int num_comp,
IntVect& ratio,
const BCRec& phys_bc);
};
inline
void
InterpBndryData::setBndryValues (::BndryRegister& crse,
int c_start,
const MultiFab& fine,
int f_start,
int bnd_start,
int num_comp,
int ratio,
const BCRec& bc)
{
IntVect ratio_vect = ratio * IntVect::TheUnitVector();
setBndryValues(crse,c_start,fine,f_start,bnd_start,num_comp,ratio_vect,bc);
}
inline
void
InterpBndryData::setBndryConds (const BCRec& phys_bc,
int ratio)
{
IntVect ratio_vect = ratio * IntVect::TheUnitVector();
setBndryConds(phys_bc, ratio_vect);
}
#endif /*_INTERPBNDRYDATA_H_*/
ccseapps-2.5/CCSEApps/mglib/Mask.H 0000644 0001750 0001750 00000012232 11634153073 017755 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
#ifndef _MASK_H_
#define _MASK_H_
//
// $Id: Mask.H,v 1.5 2001/08/01 21:51:04 lijewski Exp $
//
#include
#include
//@Man:
/*@Memo:
A Mask is a derived Fab class whose elements maintain a logical
"TRUE" or "FALSE" state. A Mask can perform several elementary
logical operations on its data members.
*/
/*@Doc:
Implement a logical class Mask to maintain the TRUE or FALSE state
of elements in a box. A Mask can perform element-wise logical
operations, but is otherwise very similar to an FArrayBox object.
A Mask object can set its components based on comparing (a subregion
of a) real-valued FArrayBox element magnitudes to a scalar value, or
by "and", "or" operations with (the a subregion of) other Masks.
This class does NOT provide a copy constructor or assignment operator.
*/
class Mask
:
public BaseFab
{
public:
//
//@ManDoc: default constructor
//
Mask ()
:
BaseFab() {}
//
//@ManDoc: allocating constructor (nc=number of components)
//
Mask (const Box& bx,
int nc = 1)
:
BaseFab(bx,nc) {}
//
//@ManDoc: construct from input stream
//
Mask (std::istream& is);
//
//@ManDoc: destructor
//
virtual ~Mask () {}
//
//@ManDoc: Initialize from stream.
//
friend std::istream& operator>> (std::istream&, Mask&);
//
//@ManDoc: initialize from stream, FAB-style
//
void readFrom (std::istream&);
//
//@ManDoc: output to stream
//
friend std::ostream& operator<< (std::ostream&, const Mask&);
//
//@ManDoc: output to stream, FAB-style
//
void writeOn (std::ostream&) const;
//
//@ManDoc: in-place And operator
//
Mask& operator&= (const Mask& src) { return And(src); }
//
//@ManDoc: in-place And
//
Mask& And (const Mask& src);
//
//@ManDoc: as above, but specify source/destination/number of components
//
Mask& And (const Mask& src,
int srccomp,
int destcomp,
int numcomp = 1);
//
//@ManDoc: as above, and specify subregion
//
Mask& And (const Mask& src,
const Box& subbox,
int srccomp,
int destcomp,
int numcomp = 1);
//
//@ManDoc: in-pace And, over source components to destination components,
// and on intersection of source and destination boxes
//
Mask& And (const Mask& src,
const Box& srcbox,
const Box& destbox,
int srccomp,
int destcomp,
int numcomp = 1);
//
//@ManDoc: in-place Or operator
//
Mask& operator|= (const Mask& src) { return Or(src); }
//
//@ManDoc: in-place Or
//
Mask& Or (const Mask& src);
//
//@ManDoc: as above, but specify source/destination/number of components
//
Mask& Or (const Mask& src,
int srccomp,
int destcomp,
int numcomp = 1);
//
//@ManDoc: as above, and specify subregion
//
Mask& Or (const Mask& src,
const Box& subbox,
int srccomp,
int destcomp,
int numcomp = 1);
//
//@ManDoc: in-pace Or, over source components to destination components,
// and on intersection of source and destination boxes
//
Mask& Or (const Mask& src,
const Box& srcbox,
const Box& destbox,
int srccomp,
int destcomp,
int numcomp = 1);
private:
//
// Disallow copy constructor and operator.
//
Mask& operator= (const Mask&);
Mask (const Mask&);
};
#endif /*_MASK_H_*/
ccseapps-2.5/CCSEApps/mglib/MG_F.H 0000644 0001750 0001750 00000005504 11634153073 017636 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
#ifndef _MG_F_H_
#define _MG_F_H_
/*
** $Id: MG_F.H,v 1.3 2002/04/26 22:10:02 lijewski Exp $
*/
#include
#if defined(BL_LANG_FORT)
#if (BL_SPACEDIM == 2)
#define FORT_AVERAGE average2dgen
#define FORT_INTERP interp2dgen
#endif
#if (BL_SPACEDIM == 3)
#define FORT_AVERAGE average3dgen
#define FORT_INTERP interp3dgen
#endif
#else
#if (BL_SPACEDIM == 2)
#if defined(BL_FORT_USE_UPPERCASE)
#define FORT_AVERAGE AVERAGE2DGEN
#define FORT_INTERP INTERP2DGEN
#elif defined(BL_FORT_USE_LOWERCASE)
#define FORT_AVERAGE average2dgen
#define FORT_INTERP interp2dgen
#elif defined(BL_FORT_USE_UNDERSCORE)
#define FORT_AVERAGE average2dgen_
#define FORT_INTERP interp2dgen_
#endif
#endif
#if (BL_SPACEDIM == 3)
#if defined(BL_FORT_USE_UPPERCASE)
#define FORT_AVERAGE AVERAGE3DGEN
#define FORT_INTERP INTERP3DGEN
#elif defined(BL_FORT_USE_LOWERCASE)
#define FORT_AVERAGE average3dgen
#define FORT_INTERP interp3dgen
#elif defined(BL_FORT_USE_UNDERSCORE)
#define FORT_AVERAGE average3dgen_
#define FORT_INTERP interp3dgen_
#endif
#endif
#include
extern "C"
{
void FORT_AVERAGE (
Real* crse, ARLIM_P(crse_lo), ARLIM_P(crse_hi),
const Real* fine, ARLIM_P(fine_lo), ARLIM_P(fine_hi),
const int *tlo, const int *thi,
const int *nc);
void FORT_INTERP (
Real* fine, ARLIM_P(fine_lo), ARLIM_P(fine_hi),
const Real* crse, ARLIM_P(crse_lo), ARLIM_P(crse_hi),
const int *tlo, const int *thi,
const int *nc);
}
#endif
#endif /*_MG_F_H_*/
ccseapps-2.5/CCSEApps/mglib/ABecLaplacian.cpp 0000644 0001750 0001750 00000044652 11634153073 022067 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
//
// $Id: ABecLaplacian.cpp,v 1.20 2002/11/20 16:52:07 lijewski Exp $
//
#include
#include
#include
#include
#include
#include
#include
Real ABecLaplacian::a_def = 0.0;
Real ABecLaplacian::b_def = 1.0;
Real ABecLaplacian::alpha_def = 1.0;
Real ABecLaplacian::beta_def = 1.0;
ABecLaplacian::ABecLaplacian (const BndryData& _bd,
Real _h)
:
LinOp(_bd,_h),
alpha(alpha_def),
beta(beta_def)
{
initCoefficients(_bd.boxes());
}
ABecLaplacian::ABecLaplacian (const BndryData& _bd,
const Real* _h)
:
LinOp(_bd,_h),
alpha(alpha_def),
beta(beta_def)
{
initCoefficients(_bd.boxes());
}
ABecLaplacian::~ABecLaplacian ()
{
clearToLevel(-1);
}
Real
ABecLaplacian::norm(int nm, int level)
{
BL_ASSERT(nm == 0);
const MultiFab& a = aCoefficients(level);
D_TERM(const MultiFab& bX = bCoefficients(0,level);,
const MultiFab& bY = bCoefficients(1,level);,
const MultiFab& bZ = bCoefficients(2,level););
const int nc = a.nComp();
Real res = 0.0;
for (MFIter amfi(a); amfi.isValid(); ++amfi)
{
Real tres;
#if (BL_SPACEDIM==2)
FORT_NORMA(&tres,
&alpha, &beta,
a[amfi].dataPtr(), ARLIM(a[amfi].loVect()), ARLIM(a[amfi].hiVect()),
bX[amfi].dataPtr(), ARLIM(bX[amfi].loVect()), ARLIM(bX[amfi].hiVect()),
bY[amfi].dataPtr(), ARLIM(bY[amfi].loVect()), ARLIM(bY[amfi].hiVect()),
amfi.validbox().loVect(), amfi.validbox().hiVect(), &nc,
h[level]);
#elif (BL_SPACEDIM==3)
FORT_NORMA(&tres,
&alpha, &beta,
a[amfi].dataPtr(), ARLIM(a[amfi].loVect()), ARLIM(a[amfi].hiVect()),
bX[amfi].dataPtr(), ARLIM(bX[amfi].loVect()), ARLIM(bX[amfi].hiVect()),
bY[amfi].dataPtr(), ARLIM(bY[amfi].loVect()), ARLIM(bY[amfi].hiVect()),
bZ[amfi].dataPtr(), ARLIM(bZ[amfi].loVect()), ARLIM(bZ[amfi].hiVect()),
amfi.validbox().loVect(), amfi.validbox().hiVect(), &nc,
h[level]);
#endif
res = std::max(res, tres);
}
ParallelDescriptor::ReduceRealMax(res);
return res;
}
void
ABecLaplacian::clearToLevel (int level)
{
BL_ASSERT(level >= -1);
for (int i = level+1; i < numLevels(); ++i)
{
delete acoefs[i];
a_valid[i] = false;
for (int j = 0; j < BL_SPACEDIM; ++j)
{
delete bcoefs[i][j];
}
b_valid[i] = false;
}
}
void
ABecLaplacian::prepareForLevel (int level)
{
LinOp::prepareForLevel(level);
if (level == 0 )
return;
prepareForLevel(level-1);
//
// If coefficients were marked invalid, or if not yet made, make new ones
// (Note: makeCoefficients is a LinOp routine, and it allocates AND
// fills coefficients. A more efficient implementation would allocate
// and fill in separate steps--we could then use the a_valid bool
// along with the length of a_valid to separately determine whether to
// fill or allocate the coefficient MultiFabs.
//
if (level >= a_valid.size() || a_valid[level] == false)
{
if (acoefs.size() < level+1)
{
acoefs.resize(level+1);
acoefs[level] = new MultiFab;
}
else
{
delete acoefs[level];
acoefs[level] = new MultiFab;
}
makeCoefficients(*acoefs[level], *acoefs[level-1], level);
a_valid.resize(level+1);
a_valid[level] = true;
}
if (level >= b_valid.size() || b_valid[level] == false)
{
if (bcoefs.size() < level+1)
{
bcoefs.resize(level+1);
for(int i = 0; i < BL_SPACEDIM; ++i)
bcoefs[level][i] = new MultiFab;
}
else
{
for(int i = 0; i < BL_SPACEDIM; ++i)
{
delete bcoefs[level][i];
bcoefs[level][i] = new MultiFab;
}
}
for (int i = 0; i < BL_SPACEDIM; ++i)
{
makeCoefficients(*bcoefs[level][i], *bcoefs[level-1][i], level);
}
b_valid.resize(level+1);
b_valid[level] = true;
}
}
void
ABecLaplacian::initCoefficients (const BoxArray& _ba)
{
const int nComp=1;
const int nGrow=0;
acoefs.resize(1);
bcoefs.resize(1);
acoefs[0] = new MultiFab(_ba, nComp, nGrow, Fab_allocate);
acoefs[0]->setVal(a_def);
a_valid.resize(1);
a_valid[0] = true;
for (int i = 0; i < BL_SPACEDIM; ++i)
{
BoxArray edge_boxes(_ba);
edge_boxes.surroundingNodes(i);
bcoefs[0][i] = new MultiFab(edge_boxes, nComp, nGrow, Fab_allocate);
bcoefs[0][i]->setVal(b_def);
}
b_valid.resize(1);
b_valid[0] = true;
}
void
ABecLaplacian::invalidate_a_to_level (int lev)
{
lev = (lev >= 0 ? lev : 0);
for (int i = lev; i < numLevels(); i++)
a_valid[i] = false;
}
void
ABecLaplacian::invalidate_b_to_level (int lev)
{
lev = (lev >= 0 ? lev : 0);
for (int i = lev; i < numLevels(); i++)
b_valid[i] = false;
}
void
ABecLaplacian::compFlux (D_DECL(MultiFab &xflux, MultiFab &yflux, MultiFab &zflux),
MultiFab& in, const BC_Mode& bc_mode)
{
compFlux(D_DECL(xflux, yflux, zflux), in, bc_mode, true);
}
void
ABecLaplacian::compFlux (D_DECL(MultiFab &xflux, MultiFab &yflux, MultiFab &zflux),
MultiFab& in, const BC_Mode& bc_mode, bool do_ApplyBC)
{
int level = 0;
int src_comp = 0;
int num_comp = 1;
if (do_ApplyBC)
applyBC(in,src_comp,num_comp,level,bc_mode);
const BoxArray& bxa = gbox[level];
const MultiFab& a = aCoefficients(level);
D_TERM(const MultiFab& bX = bCoefficients(0,level);,
const MultiFab& bY = bCoefficients(1,level);,
const MultiFab& bZ = bCoefficients(2,level););
int nc = in.nComp();
for (MFIter inmfi(in); inmfi.isValid(); ++inmfi)
{
BL_ASSERT(bxa[inmfi.index()] == inmfi.validbox());
FORT_FLUX(in[inmfi].dataPtr(),
ARLIM(in[inmfi].loVect()), ARLIM(in[inmfi].hiVect()),
&alpha, &beta, a[inmfi].dataPtr(),
ARLIM(a[inmfi].loVect()), ARLIM(a[inmfi].hiVect()),
bX[inmfi].dataPtr(),
ARLIM(bX[inmfi].loVect()), ARLIM(bX[inmfi].hiVect()),
bY[inmfi].dataPtr(),
ARLIM(bY[inmfi].loVect()), ARLIM(bY[inmfi].hiVect()),
#if (BL_SPACEDIM == 3)
bZ[inmfi].dataPtr(),
ARLIM(bZ[inmfi].loVect()), ARLIM(bZ[inmfi].hiVect()),
#endif
inmfi.validbox().loVect(), inmfi.validbox().hiVect(), &nc,
h[level],
xflux[inmfi].dataPtr(),
ARLIM(xflux[inmfi].loVect()), ARLIM(xflux[inmfi].hiVect()),
yflux[inmfi].dataPtr(),
ARLIM(yflux[inmfi].loVect()), ARLIM(yflux[inmfi].hiVect())
#if (BL_SPACEDIM == 3)
,zflux[inmfi].dataPtr(),
ARLIM(zflux[inmfi].loVect()), ARLIM(zflux[inmfi].hiVect())
#endif
);
}
}
#ifdef BL_THREADS
class task_gsrb
:
public WorkQueue::task
{
public:
task_gsrb(FArrayBox& solnL_,
const FArrayBox& rhsL_,
Real alpha_, Real beta_,
const FArrayBox& a_,
D_DECL(const FArrayBox& bX_,
const FArrayBox& bY_,
const FArrayBox& bZ_),
const FArrayBox& f0_, const Mask& m0_,
const FArrayBox& f1_, const Mask& m1_,
const FArrayBox& f2_, const Mask& m2_,
const FArrayBox& f3_, const Mask& m3_,
#if BL_SPACEDIM == 3
const FArrayBox& f4_, const Mask& m4_,
const FArrayBox& f5_, const Mask& m5_,
#endif
const Box& vbox_,
int nc_,
const Real* h_,
int redBlackFlag_)
:
solnL(solnL_),
rhsL(rhsL_),
alpha(alpha_), beta(beta_),
a(a_),
D_DECL(bX(bX_),
bY(bY_),
bZ(bZ_)),
f0(f0_), m0(m0_),
f1(f1_), m1(m1_),
f2(f2_), m2(m2_),
f3(f3_), m3(m3_),
#if BL_SPACEDIM == 3
f4(f4_), m4(m4_),
f5(f5_), m5(m5_),
#endif
vbox(vbox_),
nc(nc_),
h(h_),
redBlackFlag(redBlackFlag_)
{}
virtual void run();
private:
FArrayBox& solnL;
const FArrayBox& rhsL;
const Real alpha, beta;
const FArrayBox& a;
D_TERM(const FArrayBox& bX,
;const FArrayBox& bY,
;const FArrayBox& bZ);
const FArrayBox& f0;
const Mask& m0;
const FArrayBox& f1;
const Mask& m1;
const FArrayBox& f2;
const Mask& m2;
const FArrayBox& f3;
const Mask& m3;
#if BL_SPACEDIM == 3
const FArrayBox& f4;
const Mask& m4;
const FArrayBox& f5;
const Mask& m5;
#endif
const Box vbox;
const int nc;
const Real* h;
const int redBlackFlag;
};
void
task_gsrb::run ()
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "::run()");
FORT_GSRB(solnL.dataPtr(), ARLIM(solnL.loVect()),ARLIM(solnL.hiVect()),
rhsL.dataPtr(), ARLIM(rhsL.loVect()), ARLIM(rhsL.hiVect()),
&alpha, &beta,
a.dataPtr(), ARLIM(a.loVect()), ARLIM(a.hiVect()),
bX.dataPtr(), ARLIM(bX.loVect()), ARLIM(bX.hiVect()),
bY.dataPtr(), ARLIM(bY.loVect()), ARLIM(bY.hiVect()),
#if BL_SPACEDIM==3
bZ.dataPtr(), ARLIM(bZ.loVect()), ARLIM(bZ.hiVect()),
#endif
f0.dataPtr(), ARLIM(f0.loVect()), ARLIM(f0.hiVect()),
m0.dataPtr(), ARLIM(m0.loVect()), ARLIM(m0.hiVect()),
f1.dataPtr(), ARLIM(f1.loVect()), ARLIM(f1.hiVect()),
m1.dataPtr(), ARLIM(m1.loVect()), ARLIM(m1.hiVect()),
f2.dataPtr(), ARLIM(f2.loVect()), ARLIM(f2.hiVect()),
m2.dataPtr(), ARLIM(m2.loVect()), ARLIM(m2.hiVect()),
f3.dataPtr(), ARLIM(f3.loVect()), ARLIM(f3.hiVect()),
m3.dataPtr(), ARLIM(m3.loVect()), ARLIM(m3.hiVect()),
#if BL_SPACEDIM==3
f4.dataPtr(), ARLIM(f4.loVect()), ARLIM(f4.hiVect()),
m4.dataPtr(), ARLIM(m4.loVect()), ARLIM(m4.hiVect()),
f5.dataPtr(), ARLIM(f5.loVect()), ARLIM(f5.hiVect()),
m5.dataPtr(), ARLIM(m5.loVect()), ARLIM(m5.hiVect()),
#endif
vbox.loVect(), vbox.hiVect(),
&nc, h, &redBlackFlag);
}
#endif
//
// Must be defined for MultiGrid/CGSolver to work.
//
void
ABecLaplacian::Fsmooth (MultiFab& solnL,
const MultiFab& rhsL,
int level,
int redBlackFlag)
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "::Fsmooth()");
const BoxArray& bxa = gbox[level];
OrientationIter oitr;
const FabSet& f0 = (*undrrelxr[level])[oitr()]; oitr++;
const FabSet& f1 = (*undrrelxr[level])[oitr()]; oitr++;
const FabSet& f2 = (*undrrelxr[level])[oitr()]; oitr++;
const FabSet& f3 = (*undrrelxr[level])[oitr()]; oitr++;
#if (BL_SPACEDIM > 2)
const FabSet& f4 = (*undrrelxr[level])[oitr()]; oitr++;
const FabSet& f5 = (*undrrelxr[level])[oitr()]; oitr++;
#endif
const MultiFab& a = aCoefficients(level);
D_TERM(const MultiFab &bX = bCoefficients(0,level);,
const MultiFab &bY = bCoefficients(1,level);,
const MultiFab &bZ = bCoefficients(2,level););
const int nc = solnL.nComp();
for (MFIter solnLmfi(solnL); solnLmfi.isValid(); ++solnLmfi)
{
oitr.rewind();
const int gn = solnLmfi.index();
const Mask& m0 = *maskvals[level][gn][oitr()]; oitr++;
const Mask& m1 = *maskvals[level][gn][oitr()]; oitr++;
const Mask& m2 = *maskvals[level][gn][oitr()]; oitr++;
const Mask& m3 = *maskvals[level][gn][oitr()]; oitr++;
#if (BL_SPACEDIM > 2)
const Mask& m4 = *maskvals[level][gn][oitr()]; oitr++;
const Mask& m5 = *maskvals[level][gn][oitr()]; oitr++;
#endif
BL_ASSERT(bxa[solnLmfi.index()] == solnLmfi.validbox());
#ifdef BL_THREADS
BoxLib::theWorkQueue().add(new task_gsrb(solnL[gn],
rhsL[gn],
alpha, beta,
a[gn],
D_DECL(bX[gn], bY[gn], bZ[gn]),
f0[gn], m0,
f1[gn], m1,
f2[gn], m2,
f3[gn], m3,
#if BL_SPACEDIM == 3
f4[gn], m4,
f5[gn], m5,
#endif
solnLmfi.validbox(),
nc, h[level], redBlackFlag));
#else
#if (BL_SPACEDIM == 2)
FORT_GSRB(solnL[solnLmfi].dataPtr(), ARLIM(solnL[solnLmfi].loVect()),ARLIM(solnL[solnLmfi].hiVect()),
rhsL[solnLmfi].dataPtr(), ARLIM(rhsL[solnLmfi].loVect()), ARLIM(rhsL[solnLmfi].hiVect()),
&alpha, &beta,
a[solnLmfi].dataPtr(), ARLIM(a[solnLmfi].loVect()), ARLIM(a[solnLmfi].hiVect()),
bX[solnLmfi].dataPtr(), ARLIM(bX[solnLmfi].loVect()), ARLIM(bX[solnLmfi].hiVect()),
bY[solnLmfi].dataPtr(), ARLIM(bY[solnLmfi].loVect()), ARLIM(bY[solnLmfi].hiVect()),
f0[solnLmfi.index()].dataPtr(), ARLIM(f0[solnLmfi.index()].loVect()), ARLIM(f0[solnLmfi.index()].hiVect()),
m0.dataPtr(), ARLIM(m0.loVect()), ARLIM(m0.hiVect()),
f1[solnLmfi.index()].dataPtr(), ARLIM(f1[solnLmfi.index()].loVect()), ARLIM(f1[solnLmfi.index()].hiVect()),
m1.dataPtr(), ARLIM(m1.loVect()), ARLIM(m1.hiVect()),
f2[solnLmfi.index()].dataPtr(), ARLIM(f2[solnLmfi.index()].loVect()), ARLIM(f2[solnLmfi.index()].hiVect()),
m2.dataPtr(), ARLIM(m2.loVect()), ARLIM(m2.hiVect()),
f3[solnLmfi.index()].dataPtr(), ARLIM(f3[solnLmfi.index()].loVect()), ARLIM(f3[solnLmfi.index()].hiVect()),
m3.dataPtr(), ARLIM(m3.loVect()), ARLIM(m3.hiVect()),
solnLmfi.validbox().loVect(), solnLmfi.validbox().hiVect(),
&nc, h[level], &redBlackFlag);
#endif
#if (BL_SPACEDIM == 3)
FORT_GSRB(solnL[solnLmfi].dataPtr(), ARLIM(solnL[solnLmfi].loVect()),ARLIM(solnL[solnLmfi].hiVect()),
rhsL[solnLmfi].dataPtr(), ARLIM(rhsL[solnLmfi].loVect()), ARLIM(rhsL[solnLmfi].hiVect()),
&alpha, &beta,
a[solnLmfi].dataPtr(), ARLIM(a[solnLmfi].loVect()), ARLIM(a[solnLmfi].hiVect()),
bX[solnLmfi].dataPtr(), ARLIM(bX[solnLmfi].loVect()), ARLIM(bX[solnLmfi].hiVect()),
bY[solnLmfi].dataPtr(), ARLIM(bY[solnLmfi].loVect()), ARLIM(bY[solnLmfi].hiVect()),
bZ[solnLmfi].dataPtr(), ARLIM(bZ[solnLmfi].loVect()), ARLIM(bZ[solnLmfi].hiVect()),
f0[solnLmfi.index()].dataPtr(), ARLIM(f0[solnLmfi.index()].loVect()), ARLIM(f0[solnLmfi.index()].hiVect()),
m0.dataPtr(), ARLIM(m0.loVect()), ARLIM(m0.hiVect()),
f1[solnLmfi.index()].dataPtr(), ARLIM(f1[solnLmfi.index()].loVect()), ARLIM(f1[solnLmfi.index()].hiVect()),
m1.dataPtr(), ARLIM(m1.loVect()), ARLIM(m1.hiVect()),
f2[solnLmfi.index()].dataPtr(), ARLIM(f2[solnLmfi.index()].loVect()), ARLIM(f2[solnLmfi.index()].hiVect()),
m2.dataPtr(), ARLIM(m2.loVect()), ARLIM(m2.hiVect()),
f3[solnLmfi.index()].dataPtr(), ARLIM(f3[solnLmfi.index()].loVect()), ARLIM(f3[solnLmfi.index()].hiVect()),
m3.dataPtr(), ARLIM(m3.loVect()), ARLIM(m3.hiVect()),
f4[solnLmfi.index()].dataPtr(), ARLIM(f4[solnLmfi.index()].loVect()), ARLIM(f4[solnLmfi.index()].hiVect()),
m4.dataPtr(), ARLIM(m4.loVect()), ARLIM(m4.hiVect()),
f5[solnLmfi.index()].dataPtr(), ARLIM(f5[solnLmfi.index()].loVect()), ARLIM(f5[solnLmfi.index()].hiVect()),
m5.dataPtr(), ARLIM(m5.loVect()), ARLIM(m5.hiVect()),
solnLmfi.validbox().loVect(), solnLmfi.validbox().hiVect(),
&nc, h[level], &redBlackFlag);
#endif
#endif
}
BoxLib::theWorkQueue().wait();
}
void
ABecLaplacian::Fapply (MultiFab& y,
const MultiFab& x,
int level)
{
const BoxArray& bxa = gbox[level];
const MultiFab& a = aCoefficients(level);
D_TERM(const MultiFab& bX = bCoefficients(0,level);,
const MultiFab& bY = bCoefficients(1,level);,
const MultiFab& bZ = bCoefficients(2,level););
const int nc = y.nComp();
for (MFIter ymfi(y); ymfi.isValid(); ++ymfi)
{
BL_ASSERT(bxa[ymfi.index()] == ymfi.validbox());
#if (BL_SPACEDIM == 2)
FORT_ADOTX(y[ymfi].dataPtr(),
ARLIM(y[ymfi].loVect()),ARLIM(y[ymfi].hiVect()),
x[ymfi].dataPtr(),
ARLIM(x[ymfi].loVect()), ARLIM(x[ymfi].hiVect()),
&alpha, &beta, a[ymfi].dataPtr(),
ARLIM(a[ymfi].loVect()), ARLIM(a[ymfi].hiVect()),
bX[ymfi].dataPtr(),
ARLIM(bX[ymfi].loVect()), ARLIM(bX[ymfi].hiVect()),
bY[ymfi].dataPtr(),
ARLIM(bY[ymfi].loVect()), ARLIM(bY[ymfi].hiVect()),
ymfi.validbox().loVect(), ymfi.validbox().hiVect(), &nc,
h[level]);
#endif
#if (BL_SPACEDIM ==3)
FORT_ADOTX(y[ymfi].dataPtr(),
ARLIM(y[ymfi].loVect()), ARLIM(y[ymfi].hiVect()),
x[ymfi].dataPtr(),
ARLIM(x[ymfi].loVect()), ARLIM(x[ymfi].hiVect()),
&alpha, &beta, a[ymfi].dataPtr(),
ARLIM(a[ymfi].loVect()), ARLIM(a[ymfi].hiVect()),
bX[ymfi].dataPtr(),
ARLIM(bX[ymfi].loVect()), ARLIM(bX[ymfi].hiVect()),
bY[ymfi].dataPtr(),
ARLIM(bY[ymfi].loVect()), ARLIM(bY[ymfi].hiVect()),
bZ[ymfi].dataPtr(),
ARLIM(bZ[ymfi].loVect()), ARLIM(bZ[ymfi].hiVect()),
ymfi.validbox().loVect(), ymfi.validbox().hiVect(), &nc,
h[level]);
#endif
}
}
ccseapps-2.5/CCSEApps/mglib/MultiGrid.cpp 0000644 0001750 0001750 00000042327 11634153073 021365 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
//
// $Id: MultiGrid.cpp,v 1.32 2003/03/12 21:03:32 lijewski Exp $
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
bool MultiGrid::initialized = false;
int MultiGrid::def_nu_0 = 1;
int MultiGrid::def_nu_1 = 2;
int MultiGrid::def_nu_2 = 2;
int MultiGrid::def_nu_f = 8;
int MultiGrid::def_maxiter = 40;
int MultiGrid::def_maxiter_b = 80;
int MultiGrid::def_numiter = -1;
int MultiGrid::def_verbose = 0;
int MultiGrid::def_usecg = 1;
#ifndef CG_USE_OLD_CONVERGENCE_CRITERIA
Real MultiGrid::def_rtol_b = 0.001;
#else
Real MultiGrid::def_rtol_b = 0.01;
#endif
Real MultiGrid::def_atol_b = -1.0;
int MultiGrid::def_nu_b = 0;
int MultiGrid::def_numLevelsMAX = 1024;
int MultiGrid::def_smooth_on_cg_unstable = 0;
CGSolver::Solver MultiGrid::def_cg_solver = CGSolver::BiCGStab;
static
Real
norm_inf (const MultiFab& res)
{
Real restot = 0.0;
for (MFIter mfi(res); mfi.isValid(); ++mfi)
{
restot = std::max(restot, res[mfi].norm(mfi.validbox(), 0));
}
ParallelDescriptor::ReduceRealMax(restot);
return restot;
}
static
void
Spacer (std::ostream& os, int lev)
{
for (int k = 0; k < lev; k++)
{
os << " ";
}
}
void
MultiGrid::initialize ()
{
ParmParse pp("mg");
initialized = true;
pp.query("maxiter", def_maxiter);
pp.query("maxiter_b", def_maxiter_b);
pp.query("numiter", def_numiter);
pp.query("nu_0", def_nu_0);
pp.query("nu_1", def_nu_1);
pp.query("nu_2", def_nu_2);
pp.query("nu_f", def_nu_f);
pp.query("v", def_verbose);
pp.query("verbose", def_verbose);
pp.query("usecg", def_usecg);
pp.query("rtol_b", def_rtol_b);
pp.query("bot_atol", def_atol_b);
pp.query("nu_b", def_nu_b);
pp.query("numLevelsMAX", def_numLevelsMAX);
pp.query("smooth_on_cg_unstable", def_smooth_on_cg_unstable);
int ii;
if (pp.query("cg_solver", ii ))
{
switch (ii)
{
case 0: def_cg_solver = CGSolver::CG; break;
case 1: def_cg_solver = CGSolver::BiCGStab; break;
case 2: def_cg_solver = CGSolver::CG_Alt; break;
default:
BoxLib::Error("MultiGrid::initialize(): bad cg_solver value");
}
}
if (ParallelDescriptor::IOProcessor() && def_verbose)
{
std::cout << "MultiGrid settings...\n";
std::cout << " def_nu_0 = " << def_nu_0 << '\n';
std::cout << " def_nu_1 = " << def_nu_1 << '\n';
std::cout << " def_nu_2 = " << def_nu_2 << '\n';
std::cout << " def_nu_f = " << def_nu_f << '\n';
std::cout << " def_maxiter = " << def_maxiter << '\n';
std::cout << " def_usecg = " << def_usecg << '\n';
std::cout << " def_maxiter_b = " << def_maxiter_b << '\n';
std::cout << " def_rtol_b = " << def_rtol_b << '\n';
std::cout << " def_atol_b = " << def_atol_b << '\n';
std::cout << " def_nu_b = " << def_nu_b << '\n';
std::cout << " def_numLevelsMAX = " << def_numLevelsMAX << '\n';
std::cout << " def_smooth_on_cg_unstable = " << def_smooth_on_cg_unstable << '\n';
std::cout << " def_cg_solver = " << def_cg_solver << '\n';
}
}
MultiGrid::MultiGrid (LinOp &_Lp)
:
initialsolution(0),
Lp(_Lp)
{
if (!initialized)
initialize();
maxiter = def_maxiter;
numiter = def_numiter;
nu_0 = def_nu_0;
nu_1 = def_nu_1;
nu_2 = def_nu_2;
nu_f = def_nu_f;
usecg = def_usecg;
verbose = def_verbose;
maxiter_b = def_maxiter_b;
rtol_b = def_rtol_b;
atol_b = def_atol_b;
nu_b = def_nu_b;
numLevelsMAX = def_numLevelsMAX;
smooth_on_cg_unstable = def_smooth_on_cg_unstable;
cg_solver = def_cg_solver;
numlevels = numLevels();
if ( ParallelDescriptor::IOProcessor() && verbose == 1 )
{
BoxArray tmp = Lp.boxArray();
std::cout << "MultiGrid: numlevels = " << numlevels
<< ": ngrid = " << tmp.size() << ", npts = [";
for ( int i = 0; i < numlevels; ++i )
{
if ( i > 0 ) tmp.coarsen(2);
std::cout << tmp.numPts() << " ";
}
std::cout << "]" << std::endl;
}
if ( ParallelDescriptor::IOProcessor() && verbose > 2 )
{
std::cout << "MultiGrid: " << numlevels
<< " multigrid levels created for this solve" << '\n';
std::cout << "Grids: " << '\n';
BoxArray tmp = Lp.boxArray();
for (int i = 0; i < numlevels; ++i)
{
if (i > 0)
tmp.coarsen(2);
std::cout << " Level: " << i << '\n';
for (int k = 0; k < tmp.size(); k++)
{
const Box& b = tmp[k];
std::cout << " [" << k << "]: " << b << " ";
for (int j = 0; j < BL_SPACEDIM; j++)
std::cout << b.length(j) << ' ';
std::cout << '\n';
}
}
}
}
MultiGrid::~MultiGrid ()
{
delete initialsolution;
for (int i = 0; i < cor.size(); ++i)
{
delete res[i];
delete rhs[i];
delete cor[i];
}
}
Real
MultiGrid::errorEstimate (int level,
LinOp::BC_Mode bc_mode)
{
Lp.residual(*res[level], *rhs[level], *cor[level], level, bc_mode);
return norm_inf(*res[level]);
}
void
MultiGrid::prepareForLevel (int level)
{
//
// Build this level by allocating reqd internal MultiFabs if necessary.
//
if (cor.size() > level) return;
res.resize(level+1, (MultiFab*)0);
rhs.resize(level+1, (MultiFab*)0);
cor.resize(level+1, (MultiFab*)0);
Lp.prepareForLevel(level);
if (cor[level] == 0)
{
res[level] = new MultiFab(Lp.boxArray(level), 1, 1, Fab_allocate);
rhs[level] = new MultiFab(Lp.boxArray(level), 1, 1, Fab_allocate);
cor[level] = new MultiFab(Lp.boxArray(level), 1, 1, Fab_allocate);
if (level == 0)
{
initialsolution = new MultiFab(Lp.boxArray(0), 1, 1, Fab_allocate);
}
}
}
void
MultiGrid::residualCorrectionForm (MultiFab& resL,
const MultiFab& rhsL,
MultiFab& solnL,
const MultiFab& inisol,
LinOp::BC_Mode bc_mode,
int level)
{
//
// Using the linearity of the operator, Lp, we can solve this system
// instead by solving for the correction required to the initial guess.
//
initialsolution->copy(inisol);
solnL.copy(inisol);
Lp.residual(resL, rhsL, solnL, level, bc_mode);
solnL.setVal(0.0);
}
void
MultiGrid::solve (MultiFab& _sol,
const MultiFab& _rhs,
Real _eps_rel,
Real _eps_abs,
LinOp::BC_Mode bc_mode)
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "::solve()");
//
// Prepare memory for new level, and solve the general boundary
// value problem to within relative error _eps_rel. Customized
// to solve at level=0.
//
const int level = 0;
prepareForLevel(level);
residualCorrectionForm(*rhs[level],_rhs,*cor[level],_sol,bc_mode,level);
if (!solve_(_sol, _eps_rel, _eps_abs, LinOp::Homogeneous_BC, level))
{
BoxLib::Error("MultiGrid:: failed to converge!");
}
}
int
MultiGrid::solve_ (MultiFab& _sol,
Real eps_rel,
Real eps_abs,
LinOp::BC_Mode bc_mode,
int level)
{
//
// Relax system maxiter times, stop if relative error <= _eps_rel or
// if absolute err <= _abs_eps
//
int returnVal = 0;
const Real error0 = errorEstimate(level, bc_mode);
Real error = error0;
if (ParallelDescriptor::IOProcessor() && verbose)
{
Spacer(std::cout, level);
std::cout << "MultiGrid: Initial error (error0) = " << error0 << '\n';
}
if (ParallelDescriptor::IOProcessor() && eps_rel < 1.0e-16 && eps_rel > 0)
{
std::cout << "MultiGrid: Tolerance "
<< eps_rel
<< " < 1e-16 is probably set too low" << '\n';
}
//
// Initialize correction to zero at this level (auto-filled at levels below)
//
(*cor[level]).setVal(0.0);
//
// Note: if eps_rel, eps_abs < 0 then that test is effectively bypassed
//
const Real norm_rhs = norm_inf(*rhs[level]);
const Real norm_Lp = Lp.norm(0, level);
const Real new_error_0 = norm_rhs;
Real norm_cor = 0.0;
int nit = 1;
for ( ;
error > eps_abs &&
error > eps_rel*(norm_Lp*norm_cor+norm_rhs) &&
nit <= maxiter;
++nit)
{
relax(*cor[level], *rhs[level], level, eps_rel, eps_abs, bc_mode);
norm_cor = norm_inf(*cor[level]);
error = errorEstimate(level, bc_mode);
if (ParallelDescriptor::IOProcessor() && verbose > 1 )
{
const Real rel_error = (error0 != 0) ? error/new_error_0 : 0;
Spacer(std::cout, level);
std::cout << "MultiGrid: Iteration "
<< nit
<< " error/error0 "
<< rel_error << '\n';
}
}
if ( ParallelDescriptor::IOProcessor() && verbose )
{
const Real rel_error = (error0 != 0) ? error/error0 : 0;
Spacer(std::cout, level);
std::cout << "MultiGrid: iterations(" << nit
<< ") rel_error( " << rel_error << ")" << std::endl;
}
if ( nit == numiter ||
error <= eps_rel*(norm_Lp*norm_cor+norm_rhs) ||
error <= eps_abs )
{
//
// Omit ghost update since maybe not initialized in calling routine.
// Add to boundary values stored in initialsolution.
//
_sol.copy(*cor[level]);
_sol.plus(*initialsolution,0,_sol.nComp(),0);
returnVal = 1;
}
//
// Otherwise, failed to solve satisfactorily
//
return returnVal;
}
int
MultiGrid::numLevels () const
{
int ng = Lp.numGrids();
int lv = numLevelsMAX;
//
// The routine `falls through' since coarsening and refining
// a unit box does not yield the initial box.
//
const BoxArray& bs = Lp.boxArray(0);
for (int i = 0; i < ng; ++i)
{
int llv = 0;
Box tmp = bs[i];
for (;;)
{
Box ctmp = tmp; ctmp.coarsen(2);
Box rctmp = ctmp; rctmp.refine(2);
if (tmp != rctmp || ctmp.numPts() == 1)
break;
llv++;
tmp = ctmp;
}
//
// Set number of levels so that every box can be refined to there.
//
if (lv >= llv)
lv = llv;
}
return lv+1; // Including coarsest.
}
void
MultiGrid::relax (MultiFab& solL,
MultiFab& rhsL,
int level,
Real eps_rel,
Real eps_abs,
LinOp::BC_Mode bc_mode)
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "::relax()");
//
// Recursively relax system. Equivalent to multigrid V-cycle.
// At coarsest grid, call coarsestSmooth.
//
if (level < numlevels - 1 )
{
for (int i = preSmooth() ; i > 0 ; i--)
{
Lp.smooth(solL, rhsL, level, bc_mode);
}
Lp.residual(*res[level], rhsL, solL, level, bc_mode);
prepareForLevel(level+1);
average(*rhs[level+1], *res[level]);
cor[level+1]->setVal(0.0);
for (int i = cntRelax(); i > 0 ; i--)
{
relax(*cor[level+1],*rhs[level+1],level+1,eps_rel,eps_abs,bc_mode);
}
interpolate(solL, *cor[level+1]);
for (int i = postSmooth(); i > 0 ; i--)
{
Lp.smooth(solL, rhsL, level, bc_mode);
}
}
else
{
coarsestSmooth(solL, rhsL, level, eps_rel, eps_abs, bc_mode, usecg);
}
}
void
MultiGrid::coarsestSmooth (MultiFab& solL,
MultiFab& rhsL,
int level,
Real eps_rel,
Real eps_abs,
LinOp::BC_Mode bc_mode,
int local_usecg)
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "coarsestSmooth()");
prepareForLevel(level);
if (local_usecg == 0)
{
Real error0;
if (verbose)
{
error0 = errorEstimate(level, bc_mode);
if (ParallelDescriptor::IOProcessor())
std::cout << " Bottom Smoother: Initial error (error0) = "
<< error0 << '\n';
}
for (int i = finalSmooth(); i > 0; i--)
{
Lp.smooth(solL, rhsL, level, bc_mode);
if (verbose > 1 || (i == 1 && verbose))
{
Real error = errorEstimate(level, bc_mode);
const Real rel_error = (error0 != 0) ? error/error0 : 0;
if (ParallelDescriptor::IOProcessor())
std::cout << " Bottom Smoother: Iteration "
<< i
<< " error/error0 "
<< rel_error << '\n';
}
}
}
else
{
bool use_mg_precond = false;
CGSolver cg(Lp, use_mg_precond, level);
cg.setExpert(true);
cg.setMaxIter(maxiter_b);
int ret = cg.solve(solL, rhsL, rtol_b, atol_b, bc_mode, cg_solver);
if (ret != 0)
{
if (smooth_on_cg_unstable)
{
//
// If the CG solver returns a nonzero value indicating
// the problem is unstable. Assume this is not an accuracy
// issue and pound on it with the smoother.
//
if (ParallelDescriptor::IOProcessor() && def_verbose)
{
std::cout << "MultiGrid::coarsestSmooth(): CGSolver returns nonzero. Smoothing...." << std::endl;
}
coarsestSmooth(solL, rhsL, level, eps_rel, eps_abs, bc_mode, 0);
}
else
{
//
// cg failure probably indicates loss of precision accident.
// setting solL to 0 should be ok.
//
solL.setVal(0);
if (ParallelDescriptor::IOProcessor() && def_verbose)
{
std::cout << "MultiGrid::coarsestSmooth(): setting coarse corr to zero" << std::endl;
}
}
}
for (int i = 0; i < nu_b; i++)
{
Lp.smooth(solL, rhsL, level, bc_mode);
}
}
}
void
MultiGrid::average (MultiFab& c,
const MultiFab& f)
{
//
// Use Fortran function to average down (restrict) f to c.
//
for (MFIter cmfi(c); cmfi.isValid(); ++cmfi)
{
BL_ASSERT(c.boxArray().get(cmfi.index()) == cmfi.validbox());
const Box& bx = cmfi.validbox();
int nc = c.nComp();
FORT_AVERAGE(c[cmfi].dataPtr(),
ARLIM(c[cmfi].loVect()), ARLIM(c[cmfi].hiVect()),
f[cmfi].dataPtr(),
ARLIM(f[cmfi].loVect()), ARLIM(f[cmfi].hiVect()),
bx.loVect(), bx.hiVect(), &nc);
}
}
void
MultiGrid::interpolate (MultiFab& f,
const MultiFab& c)
{
//
// Use fortran function to interpolate up (prolong) c to f
// Note: returns f=f+P(c) , i.e. ADDS interp'd c to f.
//
for (MFIter fmfi(f); fmfi.isValid(); ++fmfi)
{
const Box& bx = c.boxArray()[fmfi.index()];
int nc = f.nComp();
FORT_INTERP(f[fmfi].dataPtr(),
ARLIM(f[fmfi].loVect()), ARLIM(f[fmfi].hiVect()),
c[fmfi].dataPtr(),
ARLIM(c[fmfi].loVect()), ARLIM(c[fmfi].hiVect()),
bx.loVect(), bx.hiVect(), &nc);
}
}
ccseapps-2.5/CCSEApps/mglib/GNUmakefile 0000644 0001750 0001750 00000003567 11634153073 021036 0 ustar amckinstry amckinstry #
# $Id: GNUmakefile,v 1.8 2000/06/01 20:59:38 car Exp $
#
PBOXLIB_HOME = ..
TOP = $(PBOXLIB_HOME)
PRECISION = DOUBLE
DEBUG = TRUE
DIM = 3
COMP = KCC
USE_MPI = TRUE
#
# The base name of the library we're building.
#
LBASE = mg
#
# Where libraries and include files will be installed.
#
INSTALL_ROOT = $(TOP)
include $(TOP)/mk/Make.defs Make.package
INCLUDE_LOCATIONS += $(TOP)/include
#
# Libraries to close against.
#
ifeq ($(COMP), KCC)
LibsToCloseAgainst := $(TOP)/lib/$(machineSuffix)/libamr$(DIM)d.a
LibsToCloseAgainst += $(TOP)/lib/$(machineSuffix)/libbndry$(DIM)d.a
LibsToCloseAgainst += $(TOP)/lib/$(machineSuffix)/libbox$(DIM)d.a
endif
all: $(optionsLib)
include $(TOP)/mk/Make.rules
#
# Temp stuff for doing html docs.
#
_docHeaders := $(sort $(wildcard *.H))
_htmlDir := html
#
# This will make the HTML files in the directory html provided
# any of the relevant .H files have changed more recently than the
# directory itself.
#
html: $(_docHeaders)
-if `doc++ -h > /dev/null` ; then \
$(RM) -r $(_htmlDir); \
mkdir -p $(_htmlDir); \
doc++ -f -j -B Banner.html -d $(_htmlDir) $(_docHeaders); \
fi
MgLib.tex: $(_docHeaders)
-if `doc++ -h > /dev/null` ; then \
doc++ -f -t -j -o MgLib.tex -ep docxx_squish $(_docHeaders); \
sed '/[\]usepackage[{]docxx[}]/d' < MgLib.tex > .junk; \
mv .junk MgLib.tex; \
fi
MgLib.dvi: MgLib.tex
latex MgLib.tex; latex MgLib.tex
MgLib.ps: MgLib.dvi
dvips MgLib.dvi -o MgLib.ps
#
# Install the PostScript file into $(INSTALL_ROOT)/ps
#
install_ps: MgLib.ps
-if [ ! -d $(INSTALL_ROOT)/ps ]; then \
mkdir -p $(INSTALL_ROOT)/ps; \
chmod 755 $(INSTALL_ROOT)/ps; \
fi
$(INSTALL_DATA) MgLib.ps $(INSTALL_ROOT)/ps
ccseapps-2.5/CCSEApps/mglib/Mask.cpp 0000644 0001750 0001750 00000012161 11634153073 020351 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
//
// $Id: Mask.cpp,v 1.6 2001/08/01 21:51:04 lijewski Exp $
//
#include
#include
#include
#include
const char NL = '\n';
const char SP = ' ';
Mask::Mask (std::istream& is)
{
readFrom(is);
}
std::ostream&
operator<< (std::ostream& os,
const Mask& m)
{
int ncomp = m.nComp();
os << "(Mask: " << m.box() << SP << ncomp << NL;
IntVect sm = m.box().smallEnd();
IntVect bg = m.box().bigEnd();
for (IntVect p = sm; p <= bg; m.box().next(p))
{
os << p;
for (int k = 0; k < ncomp; k++)
os << " " << m(p,k);
os << NL;
}
os << ")\n";
BL_ASSERT(os.good());
return os;
}
std::istream&
operator>> (std::istream& is,
Mask& m)
{
is.ignore(BL_IGNORE_MAX,':');
Box b;
int ncomp;
is >> b >> ncomp;
is.ignore(BL_IGNORE_MAX, '\n');
m.resize(b,ncomp);
IntVect sm = b.smallEnd();
IntVect bg = b.bigEnd();
IntVect q;
for (IntVect p = sm; p <= bg; b.next(p))
{
is >> q;
BL_ASSERT( p == q);
for( int k=0; k> m(p,k);
is.ignore(BL_IGNORE_MAX, '\n');
}
is.ignore(BL_IGNORE_MAX,'\n');
BL_ASSERT(is.good());
return is;
}
void
Mask::writeOn (std::ostream& os) const
{
os << "(Mask: " << domain << SP << nvar << NL;
const int* ptr = dataPtr();
int len = domain.numPts();
os.write( (char*) ptr, len*sizeof(int) );
os << ")\n";
}
void
Mask::readFrom (std::istream& is)
{
is.ignore(BL_IGNORE_MAX,':');
Box b;
int ncomp;
is >> b >> ncomp;
is.ignore(BL_IGNORE_MAX, '\n');
resize(b,ncomp);
int *ptr = dataPtr();
int len = domain.numPts();
is.read( (char*) ptr, len*sizeof(int) );
is.ignore(BL_IGNORE_MAX, '\n');
}
Mask&
Mask::And (const Mask& src)
{
ForAllThisXC(int,src) {
thisR = (thisR ? srcR : 0);
} EndForTX;
return *this;
}
Mask&
Mask::And (const Mask& src,
int srccomp,
int destcomp,
int numcomp)
{
Box domain(box());
ForAllThisBNNXC(int,domain,destcomp,numcomp,src,srccomp) {
thisR = (thisR ? srcR : 0);
} EndForTX;
return *this;
}
Mask&
Mask::And (const Mask& src,
const Box& subbox,
int srccomp,
int destcomp,
int numcomp)
{
ForAllThisBNNXC(int,subbox,destcomp,numcomp,src,srccomp) {
thisR = (thisR ? srcR : 0);
} EndForTX;
return *this;
}
Mask&
Mask::And (const Mask& src,
const Box& srcbox,
const Box& destbox,
int srccomp,
int destcomp,
int numcomp)
{
ForAllThisBNNXCBN(int,destbox,destcomp,numcomp,src,srcbox,srccomp) {
thisR = (thisR ? srcR : 0);
} EndForTX;
return *this;
}
Mask&
Mask::Or (const Mask& src)
{
ForAllThisXC(int,src) {
thisR = (thisR ? 1 : srcR);
} EndForTX;
return *this;
}
Mask&
Mask::Or (const Mask& src,
int srccomp,
int destcomp,
int numcomp)
{
Box domain(box());
ForAllThisBNNXC(int,domain,destcomp,numcomp,src,srccomp) {
thisR = (thisR ? 1 : srcR);
} EndForTX;
return *this;
}
Mask&
Mask::Or (const Mask& src,
const Box& subbox,
int srccomp,
int destcomp,
int numcomp)
{
ForAllThisBNNXC(int,subbox,destcomp,numcomp,src,srccomp) {
thisR = (thisR ? 1 : srcR);
} EndForTX;
return *this;
}
Mask&
Mask::Or (const Mask& src,
const Box& srcbox,
const Box& destbox,
int srccomp,
int destcomp,
int numcomp)
{
ForAllThisBNNXCBN(int,destbox,destcomp,numcomp,src,srcbox,srccomp) {
thisR = (thisR ? 1 : srcR);
} EndForTX;
return *this;
}
ccseapps-2.5/CCSEApps/mglib/LP_2D.F 0000644 0001750 0001750 00000016744 11634153073 017734 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
c
c $Id: LP_2D.F,v 1.5 2002/08/29 22:14:39 car Exp $
c
#undef BL_LANG_CC
#ifndef BL_LANG_FORT
#define BL_LANG_FORT
#endif
#include
#include
#include "LP_F.H"
#include "ArrayLim.H"
c-----------------------------------------------------------------------
c
c Gauss-Seidel Red-Black (GSRB):
c Apply the GSRB relaxation to the state phi for the equation
c L(phi) = Div(Grad(phi(x))) = rhs(x) central differenced, according
c to the arrays of boundary masks (m#) and auxiliary data (f#).
c
c In general, if the linear operator L=gamma*y-rho, the GS relaxation
c is y = (R - rho)/gamma. Near a boundary, the ghost data is filled
c using a polynomial interpolant based on the "old" phi values, so
c L=(gamma-delta)*y - rho + delta*yOld. The resulting iteration is
c
c y = (R - delta*yOld + rho)/(gamma - delta)
c
c This expression is valid additionally in the interior provided
c delta->0 there. delta is constructed by summing all the
c contributions to the central stencil element coming from boundary
c interpolants. The f#s contain the corresponding coefficient of
c the interpolating polynomial. The masks are set > 0 if the boundary
c value was filled with an interpolant involving the central stencil
c element.
c
c-----------------------------------------------------------------------
subroutine FORT_GSRB (
$ phi, DIMS(phi),
$ rhs, DIMS(rhs),
$ f0, DIMS(f0), m0, DIMS(m0),
$ f1, DIMS(f1), m1, DIMS(m1),
$ f2, DIMS(f2), m2, DIMS(m2),
$ f3, DIMS(f3), m3, DIMS(m3),
$ lo, hi, nc,
$ h, redblack
$ )
integer nc
integer DIMDEC(phi)
REAL_T phi(DIMV(phi),nc)
integer DIMDEC(rhs)
REAL_T rhs(DIMV(rhs),nc)
integer lo(BL_SPACEDIM), hi(BL_SPACEDIM)
integer DIMDEC(f0)
integer DIMDEC(f1)
integer DIMDEC(f2)
integer DIMDEC(f3)
REAL_T f0(DIMV(f0))
REAL_T f1(DIMV(f1))
REAL_T f2(DIMV(f2))
REAL_T f3(DIMV(f3))
integer DIMDEC(m0)
integer DIMDEC(m1)
integer DIMDEC(m2)
integer DIMDEC(m3)
integer m0(DIMV(m0))
integer m1(DIMV(m1))
integer m2(DIMV(m2))
integer m3(DIMV(m3))
integer redblack
REAL_T h
c
integer i, j, ioff, n
c
REAL_T cf0, cf1, cf2, cf3
REAL_T delta, gamma, rho
c
gamma = 4.0D0
do n = 1, nc
do j = lo(2), hi(2)
ioff = MOD(j + redblack,2)
do i = lo(1) + ioff,hi(1),2
c
cf0 = cvmgt(f0(lo(1),j), 0.0D0,
$ (i .eq. lo(1)) .and. (m0(lo(1)-1,j).gt.0))
cf1 = cvmgt(f1(i,lo(2)), 0.0D0,
$ (j .eq. lo(2)) .and. (m1(i,lo(2)-1).gt.0))
cf2 = cvmgt(f2(hi(1),j), 0.0D0,
$ (i .eq. hi(1)) .and. (m2(hi(1)+1,j).gt.0))
cf3 = cvmgt(f3(i,hi(2)), 0.0D0,
$ (j .eq. hi(2)) .and. (m3(i,hi(2)+1).gt.0))
c
delta = cf0 + cf1 + cf2 + cf3
c
rho = phi(i-1,j,n) + phi(i+1,j,n)
$ + phi(i,j-1,n) + phi(i,j+1,n)
c
phi(i,j,n) = (rhs(i,j,n)*h*h - rho + phi(i,j,n)*delta)
$ / (delta - gamma)
c
end do
end do
end do
end
c-----------------------------------------------------------------------
c
c Solve Preconditioned system here
c
subroutine FORT_CGPRECND(
$ zz, DIMS(zz),
$ rho,
$ rr, DIMS(rr),
$ lo, hi, nc,
$ h
$ )
integer nc
integer lo(BL_SPACEDIM)
integer hi(BL_SPACEDIM)
integer DIMDEC(zz)
REAL_T zz(DIMV(zz),nc)
integer DIMDEC(rr)
REAL_T rr(DIMV(rr),nc)
REAL_T h
REAL_T rho
c
integer i
integer j
integer n
REAL_T denom
c
rho = 0.0D0
denom = -h**2/4.0D0
do n = 1, nc
do j = lo(2), hi(2)
do i = lo(1), hi(1)
zz(i,j,n) = rr(i,j,n)*denom
rho = rho + zz(i,j,n)*rr(i,j,n)
end do
end do
end do
c
end
c-----------------------------------------------------------------------
c
c Fill in a matrix x vector operator here
c
subroutine FORT_ADOTX(
$ y, DIMS(y),
$ x, DIMS(x),
$ lo, hi, nc,
$ h
$ )
integer nc
integer lo(BL_SPACEDIM)
integer hi(BL_SPACEDIM)
integer DIMDEC(y)
REAL_T y(DIMV(y),nc)
integer DIMDEC(x)
REAL_T x(DIMV(x),nc)
REAL_T h
c
integer i, j, n
REAL_T scal
c
scal = 1.0D0/h**2
c
do n = 1, nc
do j = lo(2), hi(2)
do i = lo(1), hi(1)
y(i,j,n) = scal*
$ ( x(i-1,j,n) + x(i+1,j,n)
$ + x(i,j-1,n) + x(i,j+1,n)
$ - 4*x(i,j,n) )
end do
end do
end do
c
end
c-----------------------------------------------------------------------
subroutine FORT_ESTANORM(
& lo, hi, nc,
& h
& )
integer nc
integer lo(BL_SPACEDIM)
integer hi(BL_SPACEDIM)
integer i, j, n
REAL_T h,res
c
res = 8.0D0/h**2
end
c-----------------------------------------------------------------------
c
c Fill in fluxes
c
subroutine FORT_FLUX(
$ x,DIMS(x),
$ lo,hi,nc,
$ h,
$ xflux,DIMS(xflux),
$ yflux,DIMS(yflux)
$ )
implicit none
integer lo(BL_SPACEDIM), hi(BL_SPACEDIM), nc
integer DIMDEC(x)
integer DIMDEC(xflux)
integer DIMDEC(yflux)
REAL_T x(DIMV(x),nc)
REAL_T xflux(DIMV(xflux),nc)
REAL_T yflux(DIMV(yflux),nc)
REAL_T h(BL_SPACEDIM)
c
REAL_T dhx, dhy
integer i,j,n
c
dhx = one/h(1)
dhy = one/h(2)
c
do n = 1, nc
do j = lo(2), hi(2)
do i = lo(1), hi(1)+1
xflux(i,j,n) = - dhx*( x(i,j,n) - x(i-1,j,n) )
end do
end do
end do
do n = 1, nc
do j = lo(2), hi(2)+1
do i = lo(1), hi(1)
yflux(i,j,n) = - dhy*( x(i,j,n) - x(i,j-1,n) )
end do
end do
end do
end
ccseapps-2.5/CCSEApps/mglib/LO_BCTYPES.H 0000644 0001750 0001750 00000002721 11634153073 020567 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
#ifndef _LO_BCTYPES_H_
#define _LO_BCTYPES_H_
/*
* $Id: LO_BCTYPES.H,v 1.1 1998/03/24 07:06:14 almgren Exp $
*/
#define LO_DIRICHLET 101
#define LO_NEUMANN 102
#define LO_REFLECT_ODD 103
#endif
ccseapps-2.5/CCSEApps/mglib/CGSolver.cpp 0000644 0001750 0001750 00000065675 11634153073 021164 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
//
// $Id: CGSolver.cpp,v 1.32 2003/03/12 21:03:32 lijewski Exp $
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int CGSolver::initialized = 0;
int CGSolver::def_maxiter = 40;
int CGSolver::def_verbose = 0;
CGSolver::Solver CGSolver::def_cg_solver = BiCGStab;
double CGSolver::def_unstable_criterion = 10.;
static
void
Spacer (std::ostream& os, int lev)
{
for (int k = 0; k < lev; k++)
{
os << " ";
}
}
void
CGSolver::initialize ()
{
ParmParse pp("cg");
pp.query("maxiter", def_maxiter);
pp.query("v", def_verbose);
pp.query("verbose", def_verbose);
pp.query("unstable_criterion",def_unstable_criterion);
int ii;
if (pp.query("cg_solver", ii))
{
switch (ii)
{
case 0: def_cg_solver = CG; break;
case 1: def_cg_solver = BiCGStab; break;
case 2: def_cg_solver = CG_Alt; break;
default:
BoxLib::Error("CGSolver::initialize(): bad cg_solver");
}
}
if (ParallelDescriptor::IOProcessor() && def_verbose)
{
std::cout << "CGSolver settings...\n";
std::cout << " def_maxiter = " << def_maxiter << '\n';
std::cout << " def_unstable_criterion = " << def_unstable_criterion << '\n';
std::cout << " def_cg_solver = " << def_cg_solver << '\n';
}
initialized = 1;
}
CGSolver::CGSolver (LinOp& _Lp,
bool _use_mg_precond,
int _lev)
:
isExpert(false),
Lp(_Lp),
mg_precond(0),
lev(_lev),
use_mg_precond(_use_mg_precond)
{
if (!initialized)
initialize();
maxiter = def_maxiter;
verbose = def_verbose;
cg_solver = def_cg_solver;
set_mg_precond();
}
void
CGSolver::set_mg_precond ()
{
delete mg_precond;
if (use_mg_precond)
{
mg_precond = new MultiGrid(Lp);
mg_precond->setNumIter(1);
}
}
CGSolver::~CGSolver ()
{
delete mg_precond;
}
static
Real
norm_inf (const MultiFab& res)
{
Real restot = 0.0;
for (MFIter mfi(res); mfi.isValid(); ++mfi)
{
restot = std::max(restot, res[mfi].norm(mfi.validbox(), 0));
}
ParallelDescriptor::ReduceRealMax(restot);
return restot;
}
int
CGSolver::solve (MultiFab& sol,
const MultiFab& rhs,
Real eps_rel,
Real eps_abs,
LinOp::BC_Mode bc_mode,
Solver solver)
{
if ( solver == Automatic ) solver = cg_solver;
if ( solver == CG ) return solve_cg(sol, rhs, eps_rel, eps_abs, bc_mode);
if ( solver == BiCGStab ) return solve_bicgstab(sol, rhs, eps_rel, eps_abs, bc_mode);
if ( solver == CG_Alt ) return solve_00(sol, rhs, eps_rel, eps_abs, bc_mode);
return solve_00(sol, rhs, eps_rel, eps_abs, bc_mode);
}
int
CGSolver::solve_00 (MultiFab& sol,
const MultiFab& rhs,
Real eps_rel,
Real eps_abs,
LinOp::BC_Mode bc_mode)
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "::solve_00()");
//
// algorithm:
//
// k=0;r=rhs-A*soln_0;
// while (||r_k||^2_2 > eps^2*||r_o||^2_2 && k < maxiter {
// k++
// solve Mz_k-1 = r_k-1 (if preconditioning, else z_k-1 = r_k-1)
// rho_k-1 = r_k-1^T z_k-1
// if (k=1) { p_1 = z_0 }
// else { beta = rho_k-1/rho_k-2; p = z + beta*p }
// w = Ap
// alpha = rho_k-1/p^tw
// x += alpha p
// r -= alpha w
// }
//
BL_ASSERT(sol.boxArray() == Lp.boxArray(lev));
BL_ASSERT(rhs.boxArray() == Lp.boxArray(lev));
int nghost = 1; int ncomp = sol.nComp();
MultiFab* s = new MultiFab(sol.boxArray(), ncomp, nghost, Fab_allocate);
MultiFab* r = new MultiFab(sol.boxArray(), ncomp, nghost, Fab_allocate);
MultiFab* z = new MultiFab(sol.boxArray(), ncomp, nghost, Fab_allocate);
MultiFab* w = new MultiFab(sol.boxArray(), ncomp, nghost, Fab_allocate);
MultiFab* p = new MultiFab(sol.boxArray(), ncomp, nghost, Fab_allocate);
//
// Copy initial guess into a temp multifab guaranteed to have ghost cells.
//
int srccomp=0; int destcomp=0; ncomp=1; nghost=0;
s->copy(sol,srccomp,destcomp,ncomp);
/*
This routine assumes the LinOp is linear, and that when bc_mode =
LinOp::Homogeneous_BC, LinOp::apply() on a zero vector will return a zero
vector. Given that, we define the problem we solve here from the
original equation:
Lp(sol) = rhs --> Lp(s) + Lp(sol,bc_mode=LinOp::Homogeneous_BC) = rhs
where s is set to the incoming solution guess. Rewriting,
Lp(sol,bc_mode=LinOp::Homogeneous_BC) = r [ = rhs - Lp(s) ].
CG needs the residual of this equation on our initial guess. But
because we made the above assumption,
r - Lp(sol,bc_mode=LinOp::Homogeneous_BC) = r = rhs - Lp(s)
Which is simply the residual of the original equation evaluated at
the initial guess. Thus we get by with only one call to Lp.residual.
Without this assumption, we'd need two.
*/
Lp.residual((*r), rhs, (*s), lev, bc_mode);
//
// Set initial guess for correction to 0.
//
sol.setVal(0.0);
//
// Set bc_mode=homogeneous
//
LinOp::BC_Mode temp_bc_mode=LinOp::Homogeneous_BC;
Real rnorm = norm_inf(*r);
Real rnorm0 = rnorm;
Real minrnorm = rnorm;
int ret = 0; // will return this value if all goes well
if (verbose > 0 && ParallelDescriptor::IOProcessor())
{
Spacer(std::cout, lev);
std::cout << "CGsolver: Initial error (error0) = " << rnorm0 << '\n';
}
Real beta, rho, rhoold = 0.0;
/*
The MultiFab copies used below to update z and p require nghost=0
to avoid the possibility of filling valid regions with uninitialized
data in the invalid regions of neighboring grids. The default
behavior in MultiFab copies will likely be changed in the future.
*/
//
// If eps_rel or eps_abs < 0: that test is effectively bypassed.
//
int nit = 1;
for (;
nit <= maxiter && rnorm > eps_rel*rnorm0 && rnorm > eps_abs;
++nit)
{
if (use_mg_precond)
{
//
// Solve Mz_k-1 = r_k-1 and rho_k-1 = r_k-1^T z_k-1
//
z->setVal(0.);
mg_precond->solve(*z, *r, eps_rel, eps_abs, temp_bc_mode);
}
else
{
//
// No preconditioner, z_k-1 = r_k-1 and rho_k-1 = r_k-1^T r_k-1.
//
srccomp=0; destcomp=0; ncomp=1;
z->copy((*r), srccomp, destcomp, ncomp);
}
rho = 0.0;
int ncomp = z->nComp();
const BoxArray& gbox = r->boxArray();
for (MFIter rmfi(*r); rmfi.isValid(); ++rmfi)
{
Real trho;
BL_ASSERT(rmfi.validbox() == gbox[rmfi.index()]);
FORT_CGXDOTY(&trho,(*z)[rmfi].dataPtr(),
ARLIM((*z)[rmfi].loVect()),ARLIM((*z)[rmfi].hiVect()),
(*r)[rmfi].dataPtr(),
ARLIM((*r)[rmfi].loVect()),ARLIM((*r)[rmfi].hiVect()),
rmfi.validbox().loVect(),rmfi.validbox().hiVect(),
&ncomp);
rho += trho;
}
ParallelDescriptor::ReduceRealSum(rho);
if (nit == 1)
{
//
// k=1, p_1 = z_0
//
srccomp=0; destcomp=0; ncomp=1; nghost=0;
p->copy(*z, srccomp, destcomp, ncomp);
}
else
{
//
// k>1, beta = rho_k-1/rho_k-2 and p = z + beta*p
//
beta = rho/rhoold;
advance(*p, beta, *z);
}
//
// w = Ap, and compute Transpose(p).w
//
Real pw = axp(*w, *p, temp_bc_mode);
//
// alpha = rho_k-1/p^tw
//
Real alpha;
if( pw != 0. ){
alpha = rho/pw;
}
else {
ret = 1;
break;
}
if (ParallelDescriptor::IOProcessor() && verbose > 2)
{
Spacer(std::cout, lev);
std::cout << "CGSolver_00:"
<< " nit " << nit
<< " pw " << pw
<< " rho " << rho
<< " alpha " << alpha;
if (nit == 1)
{
std::cout << " beta undefined ...";
}
else
{
std::cout << " beta " << beta << " ...";
}
}
//
// x += alpha p and r -= alpha w
//
rhoold = rho;
update(sol, alpha, *r, *p, *w);
rnorm = norm_inf(*r);
if (rnorm > def_unstable_criterion*minrnorm)
{
ret = 2;
break;
}
else if (rnorm < minrnorm)
{
minrnorm = rnorm;
}
if (ParallelDescriptor::IOProcessor())
{
if (verbose > 1 ||
(((eps_rel > 0. && rnorm < eps_rel*rnorm0) ||
(eps_abs > 0. && rnorm < eps_abs)) && verbose))
{
const Real rel_error = (rnorm0 != 0) ? rnorm/rnorm0 : 0;
Spacer(std::cout, lev);
std::cout << "CGSolver_00: Iteration "
<< std::setw(4) << nit
<< " error/error0 "
<< rel_error << '\n';
}
}
}
if (ParallelDescriptor::IOProcessor())
{
if (verbose > 0 ||
(((eps_rel > 0. && rnorm < eps_rel*rnorm0) ||
(eps_abs > 0. && rnorm < eps_abs)) && verbose))
{
const Real rel_error = (rnorm0 != 0) ? rnorm/rnorm0 : 0;
Spacer(std::cout, lev);
std::cout << "CGSolver_00: Final: Iteration "
<< std::setw(4) << nit
<< " error/error0 "
<< rel_error << '\n';
}
}
if (ret != 0 && isExpert == false)
{
BoxLib::Error("CGSolver_00:: apparent accuracy problem; try expert setting or change unstable_criterion");
}
if (ret==0 && rnorm > eps_rel*rnorm0 && rnorm > eps_abs)
{
BoxLib::Error("CGSolver_00:: failed to converge!");
}
//
// Omit ghost update since maybe not initialized in calling routine.
// BoxLib_1.99 has no MultiFab::plus(MultiFab&) member, which would
// operate only in valid regions; do explicitly. Add to boundary
// values stored in initialsolution.
//
if (ret == 0)
{
srccomp=0; ncomp=1; nghost=0;
sol.plus(*s,srccomp,ncomp,nghost);
}
delete s;
delete r;
delete w;
delete p;
delete z;
return ret;
}
void
CGSolver::advance (MultiFab& p,
Real beta,
const MultiFab& z)
{
//
// Compute p = z + beta p
//
const BoxArray& gbox = Lp.boxArray(lev);
int ncomp = p.nComp();
const BoxArray& zbox = z.boxArray();
for (MFIter pmfi(p); pmfi.isValid(); ++pmfi)
{
BL_ASSERT(zbox[pmfi.index()] == gbox[pmfi.index()]);
FORT_CGADVCP(p[pmfi].dataPtr(),
ARLIM(p[pmfi].loVect()), ARLIM(p[pmfi].hiVect()),
z[pmfi].dataPtr(),
ARLIM(z[pmfi].loVect()), ARLIM(z[pmfi].hiVect()),
&beta,
zbox[pmfi.index()].loVect(), zbox[pmfi.index()].hiVect(),
&ncomp);
}
}
void
CGSolver::update (MultiFab& sol,
Real alpha,
MultiFab& r,
const MultiFab& p,
const MultiFab& w)
{
//
// compute x =+ alpha p and r -= alpha w
//
const BoxArray& gbox = Lp.boxArray(lev);
int ncomp = r.nComp();
for (MFIter solmfi(sol); solmfi.isValid(); ++solmfi)
{
BL_ASSERT(solmfi.validbox() == gbox[solmfi.index()]);
FORT_CGUPDATE(sol[solmfi].dataPtr(),
ARLIM(sol[solmfi].loVect()), ARLIM(sol[solmfi].hiVect()),
r[solmfi].dataPtr(),
ARLIM(r[solmfi].loVect()), ARLIM(r[solmfi].hiVect()),
&alpha,
w[solmfi].dataPtr(),
ARLIM(w[solmfi].loVect()), ARLIM(w[solmfi].hiVect()),
p[solmfi].dataPtr(),
ARLIM(p[solmfi].loVect()), ARLIM(p[solmfi].hiVect()),
solmfi.validbox().loVect(), solmfi.validbox().hiVect(),
&ncomp);
}
}
Real
CGSolver::axp (MultiFab& w,
MultiFab& p,
LinOp::BC_Mode bc_mode)
{
//
// Compute w = A.p, and return Transpose(p).w
//
Real pw = 0.0;
const BoxArray& gbox = Lp.boxArray(lev);
Lp.apply(w, p, lev, bc_mode);
int ncomp = p.nComp();
for (MFIter pmfi(p); pmfi.isValid(); ++pmfi)
{
Real tpw;
BL_ASSERT(pmfi.validbox() == gbox[pmfi.index()]);
FORT_CGXDOTY(&tpw,
p[pmfi].dataPtr(),
ARLIM(p[pmfi].loVect()), ARLIM(p[pmfi].hiVect()),
w[pmfi].dataPtr(),
ARLIM(w[pmfi].loVect()), ARLIM(w[pmfi].hiVect()),
pmfi.validbox().loVect(), pmfi.validbox().hiVect(),
&ncomp);
pw += tpw;
}
ParallelDescriptor::ReduceRealSum(pw);
return pw;
}
static
void
sxay (MultiFab& ss, const MultiFab& xx, Real a, const MultiFab& yy)
{
const int ncomp = ss.nComp();
for (MFIter smfi(ss); smfi.isValid(); ++smfi)
{
FORT_CGSXAY(ss[smfi].dataPtr(),
ARLIM(ss[smfi].loVect()), ARLIM(ss[smfi].hiVect()),
xx[smfi].dataPtr(),
ARLIM(xx[smfi].loVect()), ARLIM(xx[smfi].hiVect()),
&a,
yy[smfi].dataPtr(),
ARLIM(yy[smfi].loVect()), ARLIM(yy[smfi].hiVect()),
smfi.validbox().loVect(), smfi.validbox().hiVect(),
&ncomp);
}
}
Real
dotxy (const MultiFab& r, const MultiFab& z)
{
BL_PROFILE("CGSolver::dotxy");
int ncomp = z.nComp();
Real rho = 0.0;
for (MFIter rmfi(r); rmfi.isValid(); ++rmfi)
{
Real trho;
FORT_CGXDOTY(&trho,
z[rmfi].dataPtr(),
ARLIM(z[rmfi].loVect()),ARLIM(z[rmfi].hiVect()),
r[rmfi].dataPtr(),
ARLIM(r[rmfi].loVect()),ARLIM(r[rmfi].hiVect()),
rmfi.validbox().loVect(),rmfi.validbox().hiVect(),
&ncomp);
rho += trho;
}
ParallelDescriptor::ReduceRealSum(rho);
return rho;
}
int
CGSolver::solve_bicgstab (MultiFab& sol,
const MultiFab& rhs,
Real eps_rel,
Real eps_abs,
LinOp::BC_Mode bc_mode)
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "::solve_bicgstab()");
const int nghost = 1;
const int ncomp = 1;
BL_ASSERT(sol.boxArray() == Lp.boxArray(lev));
BL_ASSERT(rhs.boxArray() == Lp.boxArray(lev));
BL_ASSERT(sol.nComp() == 1);
MultiFab sorig(sol.boxArray(), ncomp, nghost);
MultiFab s(sol.boxArray(), ncomp, nghost);
MultiFab sh(sol.boxArray(), ncomp, nghost);
MultiFab r(sol.boxArray(), ncomp, nghost);
MultiFab rh(sol.boxArray(), ncomp, nghost);
MultiFab p(sol.boxArray(), ncomp, nghost);
MultiFab ph(sol.boxArray(), ncomp, nghost);
MultiFab v(sol.boxArray(), ncomp, nghost);
MultiFab t(sol.boxArray(), ncomp, nghost);
if (verbose && false)
{
std::cout << "eps_rel = " << eps_rel << std::endl;
std::cout << "eps_abs = " << eps_abs << std::endl;
std::cout << "lp.norm = " << Lp.norm(0, lev) << std::endl;
std::cout << "sol.norm_inf = " << norm_inf(sol) << std::endl;
std::cout << "rhs.norm_inf = " << norm_inf(rhs) << std::endl;
}
sorig.copy(sol);
Lp.residual(r, rhs, sorig, lev, bc_mode);
rh.copy(r);
sol.setVal(0.0);
const LinOp::BC_Mode temp_bc_mode=LinOp::Homogeneous_BC;
Real rnorm = norm_inf(r);
const Real rnorm0 = rnorm;
const Real Lp_norm = Lp.norm(0, lev);
const Real rh_norm = rnorm0;
Real sol_norm = 0.0;
if (verbose > 0 && ParallelDescriptor::IOProcessor())
{
Spacer(std::cout, lev);
std::cout << "CGSolver_bicgstab: Initial error (error0) = " << rnorm0 << '\n';
}
int ret = 0; // will return this value if all goes well
Real rho_1 = 0, alpha = 0, omega = 0;
int nit = 1;
if ( rnorm == 0.0 || rnorm < eps_rel*(Lp_norm*sol_norm + rh_norm ) || rnorm < eps_abs )
{
if (verbose > 0 && ParallelDescriptor::IOProcessor())
{
Spacer(std::cout, lev);
std::cout << "CGSolver_bicgstab: niter = 0,"
<< ", rnorm = " << rnorm
<< ", eps_rel*(Lp_norm*sol_norm + rh_norm )" << eps_rel*(Lp_norm*sol_norm + rh_norm )
<< ", eps_abs = " << eps_abs << std::endl;
}
return 0;
}
for (; nit <= maxiter; ++nit)
{
Real rho = dotxy(rh, r);
if ( rho == 0 )
{
ret = 1;
break;
}
if ( nit == 1 )
{
p.copy(r);
}
else
{
Real beta = (rho/rho_1)*(alpha/omega);
sxay(p, p, -omega, v);
sxay(p, r, beta, p);
}
if ( use_mg_precond )
{
ph.setVal(0.0);
mg_precond->solve(ph, p, eps_rel, eps_abs, temp_bc_mode);
}
else
{
ph.copy(p);
}
Lp.apply(v, ph, lev, temp_bc_mode);
if ( Real rhTv = dotxy(rh, v) )
{
alpha = rho/rhTv;
}
else
{
ret = 2;
break;
}
sxay(sol, sol, alpha, ph);
sxay(s, r, -alpha, v);
rnorm = norm_inf(s);
#ifndef CG_USE_OLD_CONVERGENCE_CRITERIA
sol_norm = norm_inf(sol);
if ( rnorm < eps_rel*(Lp_norm*sol_norm + rh_norm ) || rnorm < eps_abs )
{
break;
}
#else
if ( rnorm < eps_rel*rnorm0 || rnorm < eps_abs )
{
break;
}
#endif
if (ParallelDescriptor::IOProcessor())
{
if (verbose > 1 ||
(((eps_rel > 0. && rnorm < eps_rel*rnorm0) ||
(eps_abs > 0. && rnorm < eps_abs)) && verbose))
{
Spacer(std::cout, lev);
std::cout << "CGSolver_bicgstab: Half Iter "
<< std::setw(4) << nit
<< " rel. err. "
<< rnorm/(Lp_norm*sol_norm+rh_norm) << '\n';
}
}
if ( use_mg_precond )
{
sh.setVal(0.0);
mg_precond->solve(sh, s, eps_rel, eps_abs, temp_bc_mode);
}
else
{
sh.copy(s);
}
Lp.apply(t, sh, lev, temp_bc_mode);
if ( Real tTt = dotxy(t,t) )
{
omega = dotxy(t,s)/tTt;
}
else
{
ret = 3;
break;
}
sxay(sol, sol, omega, sh);
sxay(r, s, -omega, t);
rnorm = norm_inf(r);
#ifndef CG_USE_OLD_CONVERGENCE_CRITERIA
sol_norm = norm_inf(sol);
if ( rnorm < eps_rel*(Lp_norm*sol_norm + rh_norm ) || rnorm < eps_abs )
{
break;
}
#else
if ( rnorm < eps_rel*rnorm0 || rnorm < eps_abs )
{
break;
}
#endif
if ( omega == 0 )
{
ret = 4;
break;
}
if (ParallelDescriptor::IOProcessor())
{
if (verbose > 1 ||
(((eps_rel > 0. && rnorm < eps_rel*rnorm0) ||
(eps_abs > 0. && rnorm < eps_abs)) && verbose))
{
Spacer(std::cout, lev);
std::cout << "CGSolver_bicgstab: Iteration "
<< std::setw(4) << nit
<< " rel. err. "
<< rnorm/(Lp_norm*sol_norm+rh_norm) << '\n';
}
}
rho_1 = rho;
}
// std::cout << "norm(R) = " << rnorm << endl;
// std::cout << "AX+B = " << Lp.norm(0,lev)*norm(sol) + norm(rhs) << endl;
if (ParallelDescriptor::IOProcessor())
{
if (verbose > 0 ||
(((eps_rel > 0. && rnorm < eps_rel*rnorm0) ||
(eps_abs > 0. && rnorm < eps_abs)) && verbose))
{
Spacer(std::cout, lev);
std::cout << "CGSolver_bicgstab: Final: Iteration "
<< std::setw(4) << nit
<< " rel. err. "
<< rnorm/(Lp_norm*sol_norm+rh_norm) << '\n';
}
}
if( ret != 0 && isExpert == false )
{
BoxLib::Error("CGSolver_bicgstab:: apparent accuracy problem; try expert setting or change unstable_criterion");
}
#ifndef CG_USE_OLD_CONVERGENCE_CRITERIA
if ( ret == 0 && rnorm > eps_rel*(Lp_norm*sol_norm + rh_norm ) && rnorm > eps_abs )
{
BoxLib::Error("CGSolver_bicgstab:: failed to converge!");
}
#else
if ( ret == 0 && rnorm > eps_rel*rnorm0 && rnorm > eps_abs)
{
BoxLib::Error("CGSolver_bicgstab:: failed to converge!");
}
#endif
if ( ret == 0 )
{
sol.plus(sorig, 0, 1, 0);
}
return ret;
}
int
CGSolver::solve_cg (MultiFab& sol,
const MultiFab& rhs,
Real eps_rel,
Real eps_abs,
LinOp::BC_Mode bc_mode)
{
BL_PROFILE(BL_PROFILE_THIS_NAME() + "::solve_cg()");
const int nghost = 1;
const int ncomp = sol.nComp();
BL_ASSERT(sol.boxArray() == Lp.boxArray(lev));
BL_ASSERT(rhs.boxArray() == Lp.boxArray(lev));
BL_ASSERT(ncomp == 1 );
MultiFab sorig(sol.boxArray(), ncomp, nghost);
MultiFab r(sol.boxArray(), ncomp, nghost);
MultiFab z(sol.boxArray(), ncomp, nghost);
MultiFab q(sol.boxArray(), ncomp, nghost);
MultiFab p(sol.boxArray(), ncomp, nghost);
sorig.copy(sol);
Lp.residual(r, rhs, sorig, lev, bc_mode);
sol.setVal(0.0);
const LinOp::BC_Mode temp_bc_mode=LinOp::Homogeneous_BC;
Real rnorm = norm_inf(r);
const Real rnorm0 = rnorm;
Real minrnorm = rnorm;
if (verbose > 0 && ParallelDescriptor::IOProcessor())
{
Spacer(std::cout, lev);
std::cout << "CGsolver_cg: Initial error (error0) = " << rnorm0 << '\n';
}
const Real Lp_norm = Lp.norm(0, lev);
const Real rh_norm = rnorm0;
Real sol_norm = 0.0;
int ret = 0; // will return this value if all goes well
Real rho_1 = 0;
int nit = 1;
if ( rnorm == 0.0 || rnorm < eps_rel*(Lp_norm*sol_norm + rh_norm ) || rnorm < eps_abs )
{
if (verbose > 0 && ParallelDescriptor::IOProcessor())
{
Spacer(std::cout, lev);
std::cout << "CGSolver_cg: niter = 0,"
<< ", rnorm = " << rnorm
<< ", eps_rel*(Lp_norm*sol_norm + rh_norm )" << eps_rel*(Lp_norm*sol_norm + rh_norm )
<< ", eps_abs = " << eps_abs << std::endl;
}
return 0;
}
for (; nit <= maxiter; ++nit)
{
if (use_mg_precond)
{
z.setVal(0.);
mg_precond->solve(z, r, eps_rel, eps_abs, temp_bc_mode);
}
else
{
z.copy(r);
}
Real rho = dotxy(z,r);
if (nit == 1)
{
p.copy(z);
}
else
{
Real beta = rho/rho_1;
sxay(p, z, beta, p);
}
Lp.apply(q, p, lev, temp_bc_mode);
Real alpha;
if ( Real pw = dotxy(p, q) )
{
alpha = rho/pw;
}
else
{
ret = 1;
break;
}
if (ParallelDescriptor::IOProcessor() && verbose > 2)
{
Spacer(std::cout, lev);
std::cout << "CGSolver_cg:"
<< " nit " << nit
<< " rho " << rho
<< " alpha " << alpha;
}
sxay(sol, sol, alpha, p);
sxay( r, r,-alpha, q);
rnorm = norm_inf(r);
sol_norm = norm_inf(sol);
#ifndef CG_USE_OLD_CONVERGENCE_CRITERIA
if ( rnorm < eps_rel*(Lp_norm*sol_norm + rh_norm) || rnorm < eps_abs )
{
break;
}
#else
if ( rnorm < eps_rel*rnorm0 || rnorm < eps_abs )
{
break;
}
#endif
if( rnorm > def_unstable_criterion*minrnorm )
{
ret = 2;
break;
}
else if( rnorm < minrnorm )
{
minrnorm = rnorm;
}
if (ParallelDescriptor::IOProcessor())
{
if (verbose > 1 ||
(((eps_rel > 0. && rnorm < eps_rel*rnorm0) ||
(eps_abs > 0. && rnorm < eps_abs)) && verbose))
{
Spacer(std::cout, lev);
std::cout << "CGSolver_cg: Iteration "
<< std::setw(4) << nit
<< " rel. err. "
<< rnorm/(Lp_norm*sol_norm+rh_norm) << '\n';
}
}
rho_1 = rho;
}
if (ParallelDescriptor::IOProcessor())
{
if (verbose > 0 ||
(((eps_rel > 0. && rnorm < eps_rel*rnorm0) ||
(eps_abs > 0. && rnorm < eps_abs)) && verbose))
{
Spacer(std::cout, lev);
std::cout << "CGSolver_cg: Final: Iteration "
<< std::setw(4) << nit
<< " rel. err. "
<< rnorm/(Lp_norm*sol_norm+rh_norm) << '\n';
}
}
if ( ret != 0 && !isExpert )
{
BoxLib::Error("CGSolver_cg:: apparent accuracy problem; try expert setting or change unstable_criterion");
}
#ifndef CG_USE_OLD_CONVERGENCE_CRITERIA
if ( ret == 0 && rnorm > eps_rel*(Lp_norm*sol_norm + rh_norm) && rnorm > eps_abs )
{
BoxLib::Error("CGSolver_cg:: failed to converge!");
}
#else
if ( ret == 0 && rnorm > eps_rel*rnorm0 && rnorm > eps_abs )
{
BoxLib::Error("CGSolver_cg:: failed to converge!");
}
#endif
if ( ret == 0 )
{
sol.plus(sorig, 0, 1, 0);
}
return ret;
}
ccseapps-2.5/CCSEApps/mglib/ABec_F.H 0000644 0001750 0001750 00000022325 11634153073 020125 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
#ifndef _AABBEC_F_H_
#define _AABBEC_F_H_
/*
** $Id: ABec_F.H,v 1.5 2002/04/26 22:10:02 lijewski Exp $
*/
#include
#if defined(BL_LANG_FORT)
#if (BL_SPACEDIM == 2)
#define FORT_GSRB gsrb2daabbec
#define FORT_CGPRECND cgprecnd2daabbec
#define FORT_ADOTX adotx2daabbec
#define FORT_NORMA norma2daabbec
#define FORT_FLUX flux2daabbec
#endif
#if (BL_SPACEDIM == 3)
#define FORT_GSRB gsrb3daabbec
#define FORT_CGPRECND cgprecnd3daabbec
#define FORT_ADOTX adotx3daabbec
#define FORT_NORMA norma3daabbec
#define FORT_FLUX flux3daabbec
#endif
#else
#if (BL_SPACEDIM == 2)
#if defined(BL_FORT_USE_UPPERCASE)
#define FORT_GSRB GSRB2DAABBEC
#define FORT_CGPRECND CGPRECND2DAABBEC
#define FORT_ADOTX ADOTX2DAABBEC
#define FORT_NORMA NORMA2DAABBEC
#define FORT_FLUX FLUX2DAABBEC
#elif defined(BL_FORT_USE_LOWERCASE)
#define FORT_GSRB gsrb2daabbec
#define FORT_CGPRECND cgprecnd2daabbec
#define FORT_ADOTX adotx2daabbec
#define FORT_NORMA norma2daabbec
#define FORT_FLUX flux2daabbec
#elif defined(BL_FORT_USE_UNDERSCORE)
#define FORT_GSRB gsrb2daabbec_
#define FORT_CGPRECND cgprecnd2daabbec_
#define FORT_ADOTX adotx2daabbec_
#define FORT_NORMA norma2daabbec_
#define FORT_FLUX flux2daabbec_
#endif
#endif
#if (BL_SPACEDIM == 3)
#if defined(BL_FORT_USE_UPPERCASE)
#define FORT_GSRB GSRB3DAABBEC
#define FORT_CGPRECND CGPRECND3DAABBEC
#define FORT_ADOTX ADOTX3DAABBEC
#define FORT_NORMA NORMA3DAABBEC
#define FORT_FLUX FLUX3DAABBEC
#elif defined(BL_FORT_USE_LOWERCASE)
#define FORT_GSRB gsrb3daabbec
#define FORT_CGPRECND cgprecnd3daabbec
#define FORT_ADOTX adotx3daabbec
#define FORT_NORMA norma3daabbec
#define FORT_FLUX flux3daabbec
#elif defined(BL_FORT_USE_UNDERSCORE)
#define FORT_GSRB gsrb3daabbec_
#define FORT_CGPRECND cgprecnd3daabbec_
#define FORT_ADOTX adotx3daabbec_
#define FORT_NORMA norma3daabbec_
#define FORT_FLUX flux3daabbec_
#endif
#endif
#include
extern "C"
{
#if (BL_SPACEDIM == 2)
void FORT_GSRB (
Real* phi , ARLIM_P(phi_lo), ARLIM_P(phi_hi),
const Real* rhs , ARLIM_P(rhs_lo), ARLIM_P(phi_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX , ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY , ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const Real* den0, ARLIM_P(den0_lo),ARLIM_P(den0_hi),
const int* m0 , ARLIM_P(m0_lo), ARLIM_P(m0_hi),
const Real* den1, ARLIM_P(den1_lo),ARLIM_P(den1_hi),
const int* m1 , ARLIM_P(m1_lo), ARLIM_P(m1_hi),
const Real* den2, ARLIM_P(den2_lo),ARLIM_P(den2_hi),
const int* m2 , ARLIM_P(m2_lo), ARLIM_P(m2_hi),
const Real* den3, ARLIM_P(den3_lo),ARLIM_P(den3_hi),
const int* m3 , ARLIM_P(m3_lo), ARLIM_P(m3_hi),
const int* lo, const int* hi, const int *nc,
const Real *h, const int* redblack
);
void FORT_CGPRECND(
Real *tmpz , ARLIM_P(tmpz_lo), ARLIM_P(tmpz_hi),
Real *rho,
const Real *tmpr, ARLIM_P(tmpr_lo), ARLIM_P(tmpr_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const int *lo, const int *hi, const int *nc,
const Real *h
);
void FORT_ADOTX(
Real *y , ARLIM_P(y_lo), ARLIM_P(y_hi),
const Real *x, ARLIM_P(x_lo), ARLIM_P(x_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const int *lo, const int *hi, const int *nc,
const Real *h
);
void FORT_NORMA(
Real* res ,
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const int *lo, const int *hi, const int *nc,
const Real *h
);
void FORT_FLUX(
const Real *x, ARLIM_P(x_lo), ARLIM_P(x_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const int *lo, const int *hi, const int *nc,
const Real *h,
const Real* xflux, ARLIM_P(xflux_lo), ARLIM_P(xflux_hi),
const Real* yflux, ARLIM_P(yflux_lo), ARLIM_P(yflux_hi)
);
#endif
#if (BL_SPACEDIM == 3)
void FORT_GSRB (
Real* phi, ARLIM_P(phi_lo), ARLIM_P(phi_hi),
const Real* rhs, ARLIM_P(rhs_lo), ARLIM_P(rhs_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const Real* bZ, ARLIM_P(bZ_lo), ARLIM_P(bZ_hi),
const Real* den0, ARLIM_P(den0_lo), ARLIM_P(den0_hi),
const int* m0 , ARLIM_P(m0_lo), ARLIM_P(m0_hi),
const Real* den1, ARLIM_P(den1_lo), ARLIM_P(den1_hi),
const int* m1 , ARLIM_P(m1_lo), ARLIM_P(m1_hi),
const Real* den2, ARLIM_P(den2_lo), ARLIM_P(den2_hi),
const int* m2 , ARLIM_P(m2_lo), ARLIM_P(m2_hi),
const Real* den3, ARLIM_P(den3_lo), ARLIM_P(den3_hi),
const int* m3 , ARLIM_P(m3_lo), ARLIM_P(m3_hi),
const Real* den4, ARLIM_P(den4_lo), ARLIM_P(den4_hi),
const int* m4 , ARLIM_P(m4_lo), ARLIM_P(m4_hi),
const Real* den5, ARLIM_P(den5_lo), ARLIM_P(den5_hi),
const int* m5 , ARLIM_P(m5_lo), ARLIM_P(m5_hi),
const int* lo, const int* hi, const int *nc,
const Real *h, const int* redblack
);
void FORT_CGPRECND(
Real *tmpz , ARLIM_P(tmpz_lo), ARLIM_P(tmpz_hi),
Real *rho,
const Real *tmpr, ARLIM_P(tmpr_lo), ARLIM_P(tmpr_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const Real* bZ, ARLIM_P(bZ_lo), ARLIM_P(bZ_hi),
const int *lo, const int *hi, const int *nc,
const Real *h
);
void FORT_ADOTX(
Real *y , ARLIM_P(y_lo), ARLIM_P(y_hi),
const Real *x, ARLIM_P(x_lo), ARLIM_P(x_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const Real* bZ, ARLIM_P(bZ_lo), ARLIM_P(bZ_hi),
const int *lo, const int *hi, const int *nc,
const Real *h
);
void FORT_NORMA(
Real* res ,
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const Real* bZ, ARLIM_P(bZ_lo), ARLIM_P(bZ_hi),
const int *lo, const int *hi, const int *nc,
const Real *h
);
void FORT_FLUX(
const Real *x, ARLIM_P(x_lo), ARLIM_P(x_hi),
const Real* alpha, const Real* beta,
const Real* a , ARLIM_P(a_lo), ARLIM_P(a_hi),
const Real* bX, ARLIM_P(bX_lo), ARLIM_P(bX_hi),
const Real* bY, ARLIM_P(bY_lo), ARLIM_P(bY_hi),
const Real* bZ, ARLIM_P(bZ_lo), ARLIM_P(bZ_hi),
const int *lo, const int *hi, const int *nc,
const Real *h,
Real* xflux, ARLIM_P(xflux_lo), ARLIM_P(xflux_hi),
Real* yflux, ARLIM_P(yflux_lo), ARLIM_P(yflux_hi),
Real* zflux, ARLIM_P(zflux_lo), ARLIM_P(zflux_hi)
);
#endif
}
#endif
#endif /*_AABBEC_F_H_*/
ccseapps-2.5/CCSEApps/mglib/InterpBndryData.cpp 0000644 0001750 0001750 00000020010 11634153073 022500 0 ustar amckinstry amckinstry /*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy. Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov. NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly. Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/
//
// $Id: InterpBndryData.cpp,v 1.16 2002/11/12 17:08:48 lijewski Exp $
//
#include
#include
#include
#include
#include
static BDInterpFunc* bdfunc[2*BL_SPACEDIM];
static int bdfunc_set = 0;
static
void
bdfunc_init ()
{
Orientation xloface(0,Orientation::low);
Orientation xhiface(0,Orientation::high);
bdfunc[xloface] = FORT_BDINTERPXLO;
bdfunc[xhiface] = FORT_BDINTERPXHI;
#if (BL_SPACEDIM > 1)
Orientation yloface(1,Orientation::low);
Orientation yhiface(1,Orientation::high);
bdfunc[yloface] = FORT_BDINTERPYLO;
bdfunc[yhiface] = FORT_BDINTERPYHI;
#endif
#if (BL_SPACEDIM > 2)
Orientation zloface(2,Orientation::low);
Orientation zhiface(2,Orientation::high);
bdfunc[zloface] = FORT_BDINTERPZLO;
bdfunc[zhiface] = FORT_BDINTERPZHI;
#endif
}
#if (BL_SPACEDIM == 2)
#define NUMDERIV 2
#endif
#if (BL_SPACEDIM == 3)
#define NUMDERIV 5
#endif
#define DEF_LIMITS(fab,fabdat,fablo,fabhi) \
const int* fablo = (fab).loVect(); \
const int* fabhi = (fab).hiVect(); \
Real* fabdat = (fab).dataPtr();
#define DEF_CLIMITS(fab,fabdat,fablo,fabhi) \
const int* fablo = (fab).loVect(); \
const int* fabhi = (fab).hiVect(); \
const Real* fabdat = (fab).dataPtr();
InterpBndryData::InterpBndryData (const BoxArray& _grids,
int _ncomp,
const Geometry& geom)
:
BndryData(_grids,_ncomp,geom)
{}
//
// At the coarsest level the bndry values are taken from adjacent grids.
//
void
InterpBndryData::setBndryValues (const MultiFab& mf,
int mf_start,
int bnd_start,
int num_comp,
const BCRec& bc)
{
//
// Check that boxarrays are identical.
//
BL_ASSERT(grids.size());
BL_ASSERT(grids == mf.boxArray());
IntVect ref_ratio = IntVect::TheUnitVector();
for (int n = bnd_start; n < bnd_start+num_comp; ++n)
setBndryConds(bc, ref_ratio, n);
for (MFIter mfi(mf); mfi.isValid(); ++mfi)
{
BL_ASSERT(grids[mfi.index()] == mfi.validbox());
const Box& bx = grids[mfi.index()];
for (OrientationIter fi; fi; ++fi)
{
Orientation face(fi());
if (bx[face]==geom.Domain()[face] && !geom.isPeriodic(face.coordDir()))
{
//
// Physical bndry, copy from grid.
//
FArrayBox& bnd_fab = bndry[face][mfi.index()];
bnd_fab.copy(mf[mfi.index()],mf_start,bnd_start,num_comp);
}
}
}
}
//
// (1) set bndry type and location of bndry value on each face of
// each grid
// (2) set actual bndry value by:
// (A) Interpolate from crse bndryRegister at crse/fine interface
// (B) Copy from ghost region of MultiFab at physical bndry
//
void
InterpBndryData::setBndryValues (::BndryRegister& crse,
int c_start,
const MultiFab& fine,
int f_start,
int bnd_start,
int num_comp,
IntVect& ratio,
const BCRec& bc)
{
if (!bdfunc_set)
bdfunc_init();
//
// Check that boxarrays are identical.
//
BL_ASSERT(grids.size());
BL_ASSERT(grids == fine.boxArray());
//
// Set bndry types and bclocs.
//
setBndryConds(bc, ratio);
//
// First interpolate from coarse to fine on bndry.
//
const Box& fine_domain = geom.Domain();
//
// Mask turned off if covered by fine grid.
//
Real* derives = 0;
int tmplen = 0;
for (MFIter fine_mfi(fine); fine_mfi.isValid(); ++fine_mfi)
{
BL_ASSERT(grids[fine_mfi.index()] == fine_mfi.validbox());
const Box& fine_bx = fine_mfi.validbox();
Box crse_bx = BoxLib::coarsen(fine_bx,ratio);
const int* cblo = crse_bx.loVect();
const int* cbhi = crse_bx.hiVect();
int mxlen = crse_bx.longside() + 2;
if (pow(float(mxlen), float(BL_SPACEDIM-1)) > tmplen)
{
delete [] derives;
tmplen = mxlen;
#if (BL_SPACEDIM > 2)
tmplen *= mxlen;
#endif
derives = new Real[tmplen*NUMDERIV];
}
const int* lo = fine_bx.loVect();
const int* hi = fine_bx.hiVect();
const FArrayBox &fine_grd = fine[fine_mfi];
for (OrientationIter fi; fi; ++fi)
{
Orientation face(fi());
int dir = face.coordDir();
if (fine_bx[face] != fine_domain[face] || geom.isPeriodic(dir))
{
//
// Internal or periodic edge, interpolate from crse data.
//
const Mask& mask = masks[face][fine_mfi.index()];
const int* mlo = mask.loVect();
const int* mhi = mask.hiVect();
const int* mdat = mask.dataPtr();
const FArrayBox& crse_fab = crse[face][fine_mfi.index()];
const int* clo = crse_fab.loVect();
const int* chi = crse_fab.hiVect();
const Real* cdat = crse_fab.dataPtr(c_start);
FArrayBox& bnd_fab = bndry[face][fine_mfi.index()];
const int* blo = bnd_fab.loVect();
const int* bhi = bnd_fab.hiVect();
Real* bdat = bnd_fab.dataPtr(bnd_start);
int is_not_covered = BndryData::not_covered;
Box crsebnd = BoxLib::adjCell(crse_bx,face,1);
for (int k=0;k