Compare commits

...
Author SHA1 Message Date
Ben Southworth 5e2f0439f2 Updated explanation from PR 2021-01-15 08:33:43 -07:00
Ben Southworth 72b042e9a5 Merge remote-tracking branch 'origin' into AAccel 2021-01-15 08:18:29 -07:00
Tzanio Kolev 20f92199d2 Merge pull request #1879 from mfem/chak/hypresmoother-transpose
Action of HypreSmoother::MultTranspose
2021-01-14 16:30:49 -08:00
Tzanio Kolev 841769637b Merge pull request #1901 from mfem/wcdawn/documentation-DGTraceIntegrator
Add documentation for outflow boundary condition in DGTraceIntegrator
2021-01-14 16:05:06 -08:00
wcdawnandVeselin Dobrev ecef55a712 Apply suggestions from code review
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-01-14 13:40:30 -07:00
Tzanio Kolev 759987ef31 Merge pull request #1931 from mfem/test-lin-interp-dev
Broadening support for linear interpolators [test-lin-interp-dev]
2021-01-12 15:58:25 -08:00
Tzanio 316bb189c9 minor 2021-01-12 15:57:50 -08:00
Stowell, Mark L b5682f808f Updating CHANGELOG 2021-01-12 14:12:38 -08:00
Stowell, Mark L a77fb59626 Implementing/testing ProjectCurl_2D for L2 basis with FiniteElement::VALUE 2021-01-12 13:43:13 -08:00
Tzanio 2399f47207 minor 2021-01-10 15:36:32 -08:00
Tzanio Kolev 3f9443d497 Merge pull request #1818 from mfem/ew-newton
Adaptive linear rtol for NewtonSolver
2021-01-08 12:57:22 -08:00
Julian Andrej 9794db95c5 added changelog entry 2021-01-08 12:44:41 -08:00
Tzanio Kolev 928d66caba Merge pull request #1950 from mfem/fix-make-shared-install
Fix the shared installation with CUDA and TPL link flags with CUDA
2021-01-07 08:23:24 -08:00
Tzanio bbe4b002f1 Comments 2021-01-06 15:54:43 -08:00
chakshinglee 718e9b2ce3 better setup 2021-01-05 20:29:00 -08:00
chakshinglee 17a8e525a4 use symmetry of the linear system A to determine the action of HypreSmoother::Transpose 2021-01-05 19:06:54 -08:00
chakshinglee 92a87e1253 use Boolean flag to indicate if a HypreSmoother is symmetric 2021-01-04 10:59:45 -08:00
Stowell, Mark L 9d87c4efcd Expanding product interpolator tests to include 1D and 2D tests 2020-12-31 12:48:10 -08:00
Stowell, Mark L c5ceee3ef5 Collapsing derivative tests into a loop over element types 2020-12-31 12:47:24 -08:00
Stowell, Mark L 388e07a373 Collapsing new 1D, 2D, and 3D unit tests into a loop over element types 2020-12-29 15:32:56 -08:00
Stowell, Mark L 320deb43ec Implementing vector versions of lower dimensional grad and curl test functions 2020-12-29 15:32:14 -08:00
Stowell, Mark L 04444b15d3 Adding comments to the VectorFiniteElement projection methods 2020-12-29 14:38:43 -08:00
Julian Andrej 92748c1c70 remove leftovers 2020-12-28 11:45:08 -08:00
Julian Andrej 7c27b32e90 fix doxygen comment 2020-12-28 11:27:16 -08:00
Julian Andrej f442f6cee1 Merge branch 'master' into ew-newton 2020-12-28 11:07:58 -08:00
Julian Andrej 1342a59943 remove jacobian vector product 2020-12-28 11:04:51 -08:00
Julian Andrej fe23fcd39b remove jacobian vector product 2020-12-28 10:59:55 -08:00
Will Pazner ba69eadeac Reverting addition of new integrators
Those will be added in a more comprehensive way in PR #1965.
2020-12-23 10:01:57 -08:00
Will Pazner aa1da8bee2 Merge remote-tracking branch 'origin/master' into wcdawn/documentation-DGTraceIntegrator 2020-12-22 17:45:24 -08:00
Veselin Dobrev 476e95305d Merge branch 'master' into fix-make-shared-install 2020-12-22 16:40:01 -08:00
Veselin Dobrev 8f010f3c0c In makefile, fix the shared install with CUDA.
In config/defaults.mk, use "$(XLINKER)" instead of "-Wl," in all
library link options.
2020-12-14 18:33:54 -08:00
Vladimir Z Tomov 80ff56cfca Commented out the approximate Jac-vec-product. 2020-12-13 17:31:53 -08:00
Vladimir Z Tomov 58bf8f54e3 Exposed both types in the miniapps. 2020-12-13 15:13:41 -08:00
Vladimir Z Tomov 2552255ffe Updated some sample runs to use the adaptive rtol.
Updated the serial mesh-optimizer version.
2020-12-13 14:44:34 -08:00
Vladimir Z Tomov 8a130243fb Merge branch 'master' into ew-newton 2020-12-13 13:29:34 -08:00
Vladimir Z Tomov 3acc834f1d Minor. 2020-12-13 13:28:52 -08:00
Julian Andrej b796dae62c restore ex10p 2020-12-10 07:36:26 -08:00
Julian Andrej 7bcba91890 address comments and correct dq eps 2020-12-10 07:36:18 -08:00
Stowell, Mark L 04f44f2a50 Expanding linear interpolator unit tests 2020-12-08 15:11:34 -08:00
Stowell, Mark L de36574fa7 Adding Vector FE support in Project_RT and Project_ND 2020-12-08 15:11:09 -08:00
Stowell, Mark L 0e2735128c Adding support for mixed FiniteElement::INTEGRAL/VALUE in NodalFiniteElement::Project 2020-12-08 15:10:26 -08:00
Stowell, Mark L 83c9d7289a Adding FiniteElement::INTEGRAL support to GridFunction::GetVectorValues 2020-12-08 15:08:44 -08:00
Stowell, Mark L 0bbbc43ebf Adding FiniteElement::INTEGRAL support to GridFunction::GetValues 2020-12-08 15:07:45 -08:00
wcdawn aa1127fdf0 Merge pull request #1914 from mfem/convection-documentation
Documentation/convenience changes for upwind advection
2020-12-04 11:59:16 -05:00
Julian Andrej b420256c2f another try to fix doxygen comments 2020-12-02 13:36:29 -08:00
Julian Andrej 9b12b445d5 fix doxygen comment 2020-12-02 13:07:10 -08:00
Julian Andrej b8922a8988 non-messed up merge 2020-12-02 10:52:38 -08:00
Julian Andrej d0fd04c7dd Merge branch 'master' into ew-newton 2020-12-02 10:49:06 -08:00
Will Pazner 08de600931 Modify ex9 and ex9p to use NonconservativeDGTraceIntegrator 2020-12-02 08:33:45 -08:00
Will Pazner 3ac5c3a4b7 Add ConservativeConvectionIntegrator, NonconservativeDGTraceIntegrator, and some comments 2020-12-01 13:18:14 -08:00
William Dawn a74010deb5 add documentation for outflow boundary conditions with DGTraceIntegrator 2020-11-23 11:31:27 -05:00
chakshinglee df6cea3833 add a flag to give flexibility for HypreSmoother::MultTranspose to be defined when the smoother is symmetric 2020-11-15 23:24:26 -08:00
Julian Andrej 0cdbcd647e add matrix free jacobian vector product 2020-10-26 10:55:52 -07:00
Vladimir Z Tomov 45b2f40d98 Added gamma scaling to Option 1. 2020-10-22 11:47:15 -07:00
Vladimir Z Tomov 6994291f15 Added as option in pmesh-optimizer. 2020-10-21 15:00:23 -07:00
Julian Andrej 749f3da7cc make style 2020-10-20 09:28:43 -07:00
Julian Andrej 1f1b545ec0 rework interface 2020-10-19 11:21:20 -07:00
Julian Andrej b3b63da0c2 eisenstat-walker adaptive linear rtol 2020-10-16 16:15:18 -07:00
Ben Southworth 05ee77fd58 Improve explanation of picard 2020-07-02 16:14:58 -07:00
Ben Southworth b1ab80e455 Added Picard iteraiton to ex16p 2020-07-02 16:03:32 -07:00
Ben Southworth f4ef09f446 Updated ex16p, test Anderson on ex1p 2020-07-02 15:59:54 -07:00
ben-s-southworth 94dd61de84 Added nonlinear iteration to time stepping 2020-07-02 16:13:35 -06:00
Ben Southworth 96f0b99526 Compiling and running on linear problems 2020-07-01 12:38:29 -07:00
Ben Southworth 3e9a2de39c Compiling 2020-07-01 09:23:48 -07:00
ben-s-southworth 610ea8dddb Initial implementation of Anderson Acceleration 2020-07-01 08:55:02 -06:00
19 changed files with 1762 additions and 196 deletions
+6
View File
@@ -49,6 +49,12 @@ Version 4.2.1 (development)
deprecated EvalSymmetric in MatrixCoefficient. Added DiagonalMatrixCoefficient
for clarity, which is a typedef of VectorCoefficient.
- Implemented an adaptive linear solver tolerance option for NewtonSolver based
on the algorithm of Eisenstat and Walker.
- Extending support for L2 basis functions using MapTypes VALUE and INTEGRAL in
linear interpolators and GridFunction "GetValue" methods.
Version 4.2, released on October 30, 2020
=========================================
+27 -23
View File
@@ -161,7 +161,7 @@ endif
ZLIB_DIR =
ZLIB_OPT = $(if $(ZLIB_DIR),-I$(ZLIB_DIR)/include)
ZLIB_LIB = $(if $(ZLIB_DIR),$(ZLIB_RPATH) -L$(ZLIB_DIR)/lib ,)-lz
ZLIB_RPATH = -Wl,-rpath,$(ZLIB_DIR)/lib
ZLIB_RPATH = $(XLINKER)-rpath,$(ZLIB_DIR)/lib
LIBUNWIND_OPT = -g
LIBUNWIND_LIB = $(if $(NOTMAC),-lunwind -ldl,)
@@ -231,19 +231,21 @@ MESQUITE_LIB = -L$(MESQUITE_DIR)/lib -lmesquite
LIB_RT = $(if $(NOTMAC),-lrt,)
SUITESPARSE_DIR = @MFEM_DIR@/../SuiteSparse
SUITESPARSE_OPT = -I$(SUITESPARSE_DIR)/include
SUITESPARSE_LIB = -Wl,-rpath,$(SUITESPARSE_DIR)/lib -L$(SUITESPARSE_DIR)/lib\
-lklu -lbtf -lumfpack -lcholmod -lcolamd -lamd -lcamd -lccolamd\
-lsuitesparseconfig $(LIB_RT) $(METIS_LIB) $(LAPACK_LIB)
SUITESPARSE_LIB = $(XLINKER)-rpath,$(SUITESPARSE_DIR)/lib\
-L$(SUITESPARSE_DIR)/lib -lklu -lbtf -lumfpack -lcholmod -lcolamd -lamd -lcamd\
-lccolamd -lsuitesparseconfig $(LIB_RT) $(METIS_LIB) $(LAPACK_LIB)
# SuperLU library configuration
ifeq ($(MFEM_USE_SUPERLU5),YES)
SUPERLU_DIR = @MFEM_DIR@/../SuperLU_DIST_5.1.0
SUPERLU_OPT = -I$(SUPERLU_DIR)/include
SUPERLU_LIB = -Wl,-rpath,$(SUPERLU_DIR)/lib -L$(SUPERLU_DIR)/lib -lsuperlu_dist_5.1.0
SUPERLU_LIB = $(XLINKER)-rpath,$(SUPERLU_DIR)/lib -L$(SUPERLU_DIR)/lib\
-lsuperlu_dist_5.1.0
else
SUPERLU_DIR = @MFEM_DIR@/../SuperLU_DIST_6.3.1
SUPERLU_OPT = -I$(SUPERLU_DIR)/include
SUPERLU_LIB = -Wl,-rpath,$(SUPERLU_DIR)/lib64 -L$(SUPERLU_DIR)/lib64 -lsuperlu_dist -lblas
SUPERLU_LIB = $(XLINKER)-rpath,$(SUPERLU_DIR)/lib64 -L$(SUPERLU_DIR)/lib64\
-lsuperlu_dist -lblas
endif
# SCOTCH library configuration (required by STRUMPACK <= v2.1.0, optional in
@@ -269,7 +271,7 @@ MPI_FORTRAN_LIB = -lmpifort
# MUMPS library configuration
MUMPS_DIR = @MFEM_DIR@/../MUMPS_5.2.0
MUMPS_OPT = -I$(MUMPS_DIR)/include
MUMPS_LIB = -Wl,-rpath,$(MUMPS_DIR)/lib -L$(MUMPS_DIR)/lib -ldmumps\
MUMPS_LIB = $(XLINKER)-rpath,$(MUMPS_DIR)/lib -L$(MUMPS_DIR)/lib -ldmumps\
-lmumps_common -lpord $(SCALAPACK_LIB) $(LAPACK_LIB) $(MPI_FORTRAN_LIB)
# STRUMPACK library configuration
@@ -299,8 +301,8 @@ GNUTLS_LIB = -lgnutls
NETCDF_DIR = $(HOME)/local
HDF5_DIR = $(HOME)/local
NETCDF_OPT = -I$(NETCDF_DIR)/include -I$(HDF5_DIR)/include $(ZLIB_OPT)
NETCDF_LIB = -Wl,-rpath,$(NETCDF_DIR)/lib -L$(NETCDF_DIR)/lib\
-Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib\
NETCDF_LIB = $(XLINKER)-rpath,$(NETCDF_DIR)/lib -L$(NETCDF_DIR)/lib\
$(XLINKER)-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib\
-lnetcdf -lhdf5_hl -lhdf5 $(ZLIB_LIB)
# PETSc library configuration (version greater or equal to 3.8 or the dev branch)
@@ -312,9 +314,10 @@ PETSC_INC_VAR = PETSC_CC_INCLUDES
PETSC_LIB_VAR = PETSC_EXTERNAL_LIB_BASIC
ifeq ($(PETSC_FOUND),YES)
PETSC_OPT := $(shell sed -n "s/$(PETSC_INC_VAR) = *//p" $(PETSC_VARS))
PETSC_LIB := $(shell sed -n "s/$(PETSC_LIB_VAR) = *//p" $(PETSC_VARS))
PETSC_LIB := -Wl,-rpath,$(abspath $(PETSC_DIR))/lib\
-L$(abspath $(PETSC_DIR))/lib -lpetsc $(PETSC_LIB)
PETSC_DEP := $(shell sed -n "s/$(PETSC_LIB_VAR) = *//p" $(PETSC_VARS))
PETSC_LIB = $(XLINKER)-rpath,$(abspath $(PETSC_DIR))/lib\
-L$(abspath $(PETSC_DIR))/lib -lpetsc\
$(subst $(CXX_XLINKER),$(XLINKER),$(PETSC_DEP))
endif
SLEPC_DIR := $(MFEM_DIR)/../slepc
@@ -326,9 +329,10 @@ ifeq ($(SLEPC_FOUND),YES)
SLEPC_OPT := $(shell sed -n "s/$(SLEPC_INC_VAR) *= *//p" $(SLEPC_VARS))
# Some additional external libraries might be defined in this file
-include ${SLEPC_DIR}/${PETSC_ARCH}/lib/slepc/conf/slepcvariables
SLEPC_LIB := $(shell sed -n "s/$(SLEPC_LIB_VAR) *= *//p" $(SLEPC_VARS))
SLEPC_LIB := -Wl,-rpath,$(abspath $(SLEPC_DIR))/$(PETSC_ARCH)/lib\
-L$(abspath $(SLEPC_DIR))/$(PETSC_ARCH)/lib -lslepc $(SLEPC_LIB)
SLEPC_DEP := $(shell sed -n "s/$(SLEPC_LIB_VAR) *= *//p" $(SLEPC_VARS))
SLEPC_LIB = $(XLINKER)-rpath,$(abspath $(SLEPC_DIR))/$(PETSC_ARCH)/lib\
-L$(abspath $(SLEPC_DIR))/$(PETSC_ARCH)/lib -lslepc\
$(subst $(CXX_XLINKER),$(XLINKER),$(SLEPC_DEP))
endif
# MPFR library configuration
@@ -339,7 +343,7 @@ MPFR_LIB = -lmpfr
CONDUIT_DIR = @MFEM_DIR@/../conduit
CONDUIT_OPT = -I$(CONDUIT_DIR)/include/conduit
CONDUIT_LIB = \
-Wl,-rpath,$(CONDUIT_DIR)/lib -L$(CONDUIT_DIR)/lib \
$(XLINKER)-rpath,$(CONDUIT_DIR)/lib -L$(CONDUIT_DIR)/lib \
-lconduit -lconduit_relay -lconduit_blueprint -ldl
# Check if Conduit was built with hdf5 support, by looking
@@ -347,7 +351,7 @@ CONDUIT_LIB = \
CONDUIT_HDF5_HEADER=$(CONDUIT_DIR)/include/conduit/conduit_relay_hdf5.hpp
ifneq (,$(wildcard $(CONDUIT_HDF5_HEADER)))
CONDUIT_OPT += -I$(HDF5_DIR)/include
CONDUIT_LIB += -Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
CONDUIT_LIB += $(XLINKER)-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
-lhdf5 $(ZLIB_LIB)
endif
@@ -357,9 +361,9 @@ SIDRE_DIR = @MFEM_DIR@/../axom
SIDRE_OPT = -I$(SIDRE_DIR)/include -I$(CONDUIT_DIR)/include/conduit\
-I$(HDF5_DIR)/include
SIDRE_LIB = \
-Wl,-rpath,$(SIDRE_DIR)/lib -L$(SIDRE_DIR)/lib \
-Wl,-rpath,$(CONDUIT_DIR)/lib -L$(CONDUIT_DIR)/lib \
-Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
$(XLINKER)-rpath,$(SIDRE_DIR)/lib -L$(SIDRE_DIR)/lib \
$(XLINKER)-rpath,$(CONDUIT_DIR)/lib -L$(CONDUIT_DIR)/lib \
$(XLINKER)-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
-laxom -lconduit -lconduit_relay -lconduit_blueprint -lhdf5 $(ZLIB_LIB) -ldl
# PUMI
@@ -415,9 +419,9 @@ MKL_CPARDISO_DIR ?=
MKL_MPI_WRAPPER ?= mkl_blacs_mpich_lp64
MKL_LIBRARY_SUBDIR ?= lib
MKL_CPARDISO_OPT = -I$(MKL_CPARDISO_DIR)/include
MKL_CPARDISO_LIB = -Wl,-rpath,$(MKL_CPARDISO_DIR)/$(MKL_LIBRARY_SUBDIR)\
-L$(MKL_CPARDISO_DIR)/$(MKL_LIBRARY_SUBDIR) -l$(MKL_MPI_WRAPPER)\
-lmkl_intel_lp64 -lmkl_sequential -lmkl_core
MKL_CPARDISO_LIB = $(XLINKER)-rpath,$(MKL_CPARDISO_DIR)/$(MKL_LIBRARY_SUBDIR)\
-L$(MKL_CPARDISO_DIR)/$(MKL_LIBRARY_SUBDIR) -l$(MKL_MPI_WRAPPER)\
-lmkl_intel_lp64 -lmkl_sequential -lmkl_core
# If YES, enable some informational messages
VERBOSE = NO
+5
View File
@@ -178,6 +178,7 @@ int main(int argc, char *argv[])
double visc = 1e-2;
double mu = 0.25;
double K = 5.0;
bool adaptive_lin_rtol = true;
bool visualization = true;
int vis_steps = 1;
@@ -206,6 +207,9 @@ int main(int argc, char *argv[])
"Shear modulus in the Neo-Hookean hyperelastic model.");
args.AddOption(&K, "-K", "--bulk-modulus",
"Bulk modulus in the Neo-Hookean hyperelastic model.");
args.AddOption(&adaptive_lin_rtol, "-alrtol", "--adaptive-lin-rtol",
"-no-alrtol", "--no-adaptive-lin-rtol",
"Enable or disable adaptive linear solver rtol.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
@@ -574,6 +578,7 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
newton_solver.SetPrintLevel(1); // print Newton iterations
newton_solver.SetRelTol(rel_tol);
newton_solver.SetAbsTol(0.0);
newton_solver.SetAdaptiveLinRtol(2, 0.5, 0.9);
newton_solver.SetMaxIter(10);
}
+48 -14
View File
@@ -65,7 +65,7 @@ protected:
HypreSmoother M_prec; // Preconditioner for the mass matrix M
CGSolver T_solver; // Implicit solver for T = M + dt K
HypreSmoother T_prec; // Preconditioner for the implicit solver
HypreBoomerAMG T_prec; // Preconditioner for the implicit solver
double alpha, kappa;
@@ -353,7 +353,6 @@ int main(int argc, char *argv[])
}
#endif
}
oper.SetParameters(u);
}
#ifdef MFEM_USE_ADIOS2
@@ -414,6 +413,7 @@ ConductionOperator::ConductionOperator(ParFiniteElementSpace &f, double al,
T_solver.SetPrintLevel(0);
T_solver.SetPreconditioner(T_prec);
T_prec.SetPrintLevel(0);
SetParameters(u);
}
@@ -430,19 +430,53 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
void ConductionOperator::ImplicitSolve(const double dt,
const Vector &u, Vector &du_dt)
{
// Solve the equation:
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
// for du_dt
if (!T)
{
T = Add(1.0, Mmat, dt, Kmat);
current_dt = dt;
// Here we use Picard iterations to solve a nonlinear equation
// for the Runge-Kutta stage vector k,
//
// M*k = N(u+dt*k) (1)
//
// for nonlinear operator N. We assume N can be written as
//
// N(u+dt*k) := L[u+dt*k](u+dt*k) + f(t)
//
// where L is a matrix-valued operator evaluated at u+dt*k and f(t)
// a (potentially zero) time-dependent forcing vector. (1) can be
// rewritten as a fixed-point equation
//
// x = (M - dt*L[x])^{-1} (Mu + f) (2)
//
// where x := u + dt*k, which can be solved using a Picard iteration,
// where a function G(x) = x is solved via iteraitons x_{k+1} = G(x_k).
double tol = 1e-6;
int maxiter = 100;
// Right-hand side for nonlinear iteration
Mmat.Mult(u, z); // Add forcing function if one exists
du_dt = u; // Set u as initial guess for x (2)
Vector temp(u); // Vector to measure error
temp = u;
double error = 1;
int iter = 0;
while (error > tol) {
iter ++;
this->SetParameters(du_dt); // Update nonlinear operator L[x]
T = Add(1.0, Mmat, dt, Kmat); // Form matrix (M - dt*L[x])
T_solver.SetOperator(*T);
T_solver.Mult(z, du_dt); // Apply (M - dt*L[x])^{-1}
temp -= du_dt; // Measure error
error = std::sqrt(InnerProduct(MPI_COMM_WORLD, temp, temp));
temp = du_dt;
if (iter >= maxiter) {
mfem_warning("Nonlinear iteration did not converge!");
break;
}
}
MFEM_VERIFY(dt == current_dt, ""); // SDIRK methods use the same dt
Kmat.Mult(u, z);
z.Neg();
T_solver.Mult(z, du_dt);
// Above we solved for x = u + dt*k, where k is the desired update
// Map du_dt -> k.
du_dt -= u;
du_dt /= dt;
}
void ConductionOperator::SetParameters(const Vector &u)
@@ -483,4 +517,4 @@ double InitialTemperature(const Vector &x)
{
return 1.0;
}
}
}
+9 -2
View File
@@ -231,10 +231,17 @@ int main(int argc, char *argv[])
else
{
prec = new HypreBoomerAMG;
prec->SetOperator(*A);
}
CGSolver cg(MPI_COMM_WORLD);
// CGSolver cg(MPI_COMM_WORLD);
AndersonAcceleration cg(MPI_COMM_WORLD);
cg.SetKDim(10);
cg.SetRestart(true); // WORKS
cg.SetAAStart(0); // WORKS
cg.SetWeight(1.0); // Not robust but seems to work
cg.SetRelTol(1e-12);
cg.SetMaxIter(2000);
cg.SetMaxIter(50);
cg.SetPrintLevel(1);
if (prec) { cg.SetPreconditioner(*prec); }
cg.SetOperator(*A);
+41
View File
@@ -3515,6 +3515,47 @@ VectorScalarProductInterpolator::AssembleElementMatrix2(
}
void
ScalarCrossProductInterpolator::AssembleElementMatrix2(
const FiniteElement &dom_fe,
const FiniteElement &ran_fe,
ElementTransformation &Trans,
DenseMatrix &elmat)
{
// Vector coefficient product with vector shape functions
struct VCrossVShapeCoefficient : public VectorCoefficient
{
VectorCoefficient &VQ;
const FiniteElement &fe;
DenseMatrix vshape;
Vector vc;
VCrossVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
: VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
V.SetSize(vdim);
VQ.Eval(vc, T, ip);
fe.CalcPhysVShape(T, vshape);
for (int k = 0; k < vdim; k++)
{
V(k) = vc(0) * vshape(k,1) - vc(1) * vshape(k,0);
}
}
};
VCrossVShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
Vector elmat_as_vec(elmat.Data(), elmat.Height()*elmat.Width());
ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
}
void
VectorCrossProductInterpolator::AssembleElementMatrix2(
const FiniteElement &dom_fe,
+38 -5
View File
@@ -2671,11 +2671,28 @@ public:
/** Integrator for the DG form:
alpha < rho_u (u.n) {v},[w] > + beta < rho_u |u.n| [v],[w] >,
where v and w are the trial and test variables, respectively, and rho/u are
given scalar/vector coefficients. The vector coefficient, u, is assumed to
be continuous across the faces and when given the scalar coefficient, rho,
is assumed to be discontinuous. The integrator uses the upwind value of rho,
rho_u, which is value from the side into which the vector coefficient, u,
points. */
given scalar/vector coefficients. {v} represents the average value of v on
the face and [v] is the jump such that {v}=(v1+v2)/2 and [v]=(v1-v2) for the
face between elements 1 and 2. For boundary elements, v2=0. The vector
coefficient, u, is assumed to be continuous across the faces and when given
the scalar coefficient, rho, is assumed to be discontinuous. The integrator
uses the upwind value of rho, rho_u, which is value from the side into which
the vector coefficient, u, points.
One use case for this integrator is to discretize the operator -u.grad(v)
with a DG formulation. The resulting formulation uses the
ConvectionIntegrator (with coefficient u, and parameter alpha = -1) and the
transpose of the DGTraceIntegrator (with coefficient u, and parameters
alpha = 1, beta = -1/2 to use the upwind face flux). This discretization and
the handling of the inflow and outflow boundaries is illustrated in Example
9/9p.
Another use case for this integrator is to discretize the operator -div(u v)
with a DG formulation. The resulting formulation is conservative and
consists of the transpose of the ConvectionIntegrator (with coefficient u,
and parameter alpha = 1) plus the DGTraceIntegrator (with coefficient u, and
parameters alpha = -1, beta = -1/2 to use the upwind face flux).
*/
class DGTraceIntegrator : public BilinearFormIntegrator
{
protected:
@@ -3090,6 +3107,22 @@ protected:
VectorCoefficient *VQ;
};
/** Interpolator of the 2D cross product between a vector coefficient and an
H(curl)-conforming field onto an L2-conforming field. */
class ScalarCrossProductInterpolator : public DiscreteInterpolator
{
public:
ScalarCrossProductInterpolator(VectorCoefficient & vc)
: VQ(&vc) { }
virtual void AssembleElementMatrix2(const FiniteElement &nd_fe,
const FiniteElement &l2_fe,
ElementTransformation &Trans,
DenseMatrix &elmat);
protected:
VectorCoefficient *VQ;
};
/** Interpolator of the cross product between a vector coefficient and an
H(curl)-conforming field onto an H(div)-conforming field. The range space
can also be vector L2. */
+87 -11
View File
@@ -596,17 +596,22 @@ void NodalFiniteElement::ProjectCurl_2D(
const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &curl) const
{
MFEM_ASSERT(GetMapType() == FiniteElement::INTEGRAL, "");
DenseMatrix curl_shape(fe.GetDof(), 1);
curl.SetSize(dof, fe.GetDof());
for (int i = 0; i < dof; i++)
{
fe.CalcCurlShape(Nodes.IntPoint(i), curl_shape);
double w = 1.0;
if (GetMapType() == FiniteElement::VALUE)
{
Trans.SetIntPoint(&Nodes.IntPoint(i));
w /= Trans.Weight();
}
for (int j = 0; j < fe.GetDof(); j++)
{
curl(i,j) = curl_shape(j,0);
curl(i,j) = w * curl_shape(j,0);
}
}
}
@@ -722,17 +727,34 @@ void NodalFiniteElement::Project(
{
if (fe.GetRangeType() == SCALAR)
{
MFEM_ASSERT(map_type == fe.GetMapType(), "");
Vector shape(fe.GetDof());
I.SetSize(dof, fe.GetDof());
for (int k = 0; k < dof; k++)
if (map_type == fe.GetMapType())
{
fe.CalcShape(Nodes.IntPoint(k), shape);
for (int j = 0; j < shape.Size(); j++)
for (int k = 0; k < dof; k++)
{
I(k,j) = (fabs(shape(j)) < 1e-12) ? 0.0 : shape(j);
fe.CalcShape(Nodes.IntPoint(k), shape);
for (int j = 0; j < shape.Size(); j++)
{
I(k,j) = (fabs(shape(j)) < 1e-12) ? 0.0 : shape(j);
}
}
}
else
{
for (int k = 0; k < dof; k++)
{
Trans.SetIntPoint(&Nodes.IntPoint(k));
fe.CalcPhysShape(Trans, shape);
if (map_type == INTEGRAL)
{
shape *= Trans.Weight();
}
for (int j = 0; j < shape.Size(); j++)
{
I(k,j) = (fabs(shape(j)) < 1e-12) ? 0.0 : shape(j);
}
}
}
}
@@ -1031,6 +1053,8 @@ void VectorFiniteElement::Project_RT(
fe.CalcShape(ip, shape);
Trans.SetIntPoint(&ip);
// Transform RT face normals from reference to physical space
// vk = adj(J)^T nk
Trans.AdjugateJacobian().MultTranspose(nk + d2n[k]*dim, vk);
if (fe.GetMapType() == INTEGRAL)
{
@@ -1048,6 +1072,8 @@ void VectorFiniteElement::Project_RT(
{
s = 0.0;
}
// Project scalar basis function multiplied by each coordinate
// direction onto the transformed face normals
for (int d = 0; d < sdim; d++)
{
I(k,j+d*shape.Size()) = s*vk[d];
@@ -1057,7 +1083,31 @@ void VectorFiniteElement::Project_RT(
}
else
{
mfem_error("VectorFiniteElement::Project_RT (fe version)");
int sdim = Trans.GetSpaceDim();
double vk[Geometry::MaxDim];
DenseMatrix vshape(fe.GetDof(), sdim);
Vector vshapenk(fe.GetDof());
const bool square_J = (dim == sdim);
I.SetSize(dof, fe.GetDof());
for (int k = 0; k < dof; k++)
{
const IntegrationPoint &ip = Nodes.IntPoint(k);
Trans.SetIntPoint(&ip);
// Transform RT face normals from reference to physical space
// vk = adj(J)^T nk
Trans.AdjugateJacobian().MultTranspose(nk + d2n[k]*dim, vk);
// Compute fe basis functions in physical space
fe.CalcVShape(Trans, vshape);
// Project fe basis functions onto transformed face normals
vshape.Mult(vk, vshapenk);
if (!square_J) { vshapenk /= Trans.Weight(); }
for (int j=0; j<vshapenk.Size(); j++)
{
I(k,j) = vshapenk(j);
}
}
}
}
@@ -1218,6 +1268,8 @@ void VectorFiniteElement::Project_ND(
fe.CalcShape(ip, shape);
Trans.SetIntPoint(&ip);
// Transform ND edge tengents from reference to physical space
// vk = J tk
Trans.Jacobian().Mult(tk + d2t[k]*dim, vk);
if (fe.GetMapType() == INTEGRAL)
{
@@ -1235,6 +1287,8 @@ void VectorFiniteElement::Project_ND(
{
s = 0.0;
}
// Project scalar basis function multiplied by each coordinate
// direction onto the transformed edge tangents
for (int d = 0; d < sdim; d++)
{
I(k, j + d*shape.Size()) = s*vk[d];
@@ -1244,7 +1298,29 @@ void VectorFiniteElement::Project_ND(
}
else
{
mfem_error("VectorFiniteElement::Project_ND (fe version)");
int sdim = Trans.GetSpaceDim();
double vk[Geometry::MaxDim];
DenseMatrix vshape(fe.GetDof(), sdim);
Vector vshapetk(fe.GetDof());
I.SetSize(dof, fe.GetDof());
for (int k = 0; k < dof; k++)
{
const IntegrationPoint &ip = Nodes.IntPoint(k);
Trans.SetIntPoint(&ip);
// Transform ND edge tangents from reference to physical space
// vk = J tk
Trans.Jacobian().Mult(tk + d2t[k]*dim, vk);
// Compute fe basis functions in physical space
fe.CalcVShape(Trans, vshape);
// Project fe basis functions onto transformed edge tangents
vshape.Mult(vk, vshapetk);
for (int j=0; j<vshapetk.Size(); j++)
{
I(k, j) = vshapetk(j);
}
}
}
}
+54
View File
@@ -819,11 +819,25 @@ protected:
void CalcVShape_ND(ElementTransformation &Trans,
DenseMatrix &shape) const;
/** @brief Project a vector coefficient onto the RT basis functions
@param nk Face normal vectors for this element type
@param d2n Offset into nk for each degree of freedom
@param vc Vector coefficient to be projected
@param Trans Transformation from reference to physical coordinates
@param dofs Expansion coefficients for the approximation of vc
*/
void Project_RT(const double *nk, const Array<int> &d2n,
VectorCoefficient &vc, ElementTransformation &Trans,
Vector &dofs) const;
/// Projects the vector of values given at FE nodes to RT space
/** Project vector values onto the RT basis functions
@param nk Face normal vectors for this element type
@param d2n Offset into nk for each degree of freedom
@param vc Vector values at each interpolation point
@param Trans Transformation from reference to physical coordinates
@param dofs Expansion coefficients for the approximation of vc
*/
void Project_RT(const double *nk, const Array<int> &d2n,
Vector &vc, ElementTransformation &Trans,
Vector &dofs) const;
@@ -833,6 +847,19 @@ protected:
const double *nk, const Array<int> &d2n,
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const;
/** @brief Project vector-valued basis functions onto the RT basis functions
@param nk Face normal vectors for this element type
@param d2n Offset into nk for each degree of freedom
@param fe Vector-valued finite element basis
@param Trans Transformation from reference to physical coordinates
@param I Expansion coefficients for the approximation of each basis
function
Note: If the FiniteElement, fe, is scalar-valued the projection will
assume that a FiniteElementSpace is being used to define a vector
field using the scalar basis functions for each component of the
vector field.
*/
void Project_RT(const double *nk, const Array<int> &d2n,
const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
@@ -852,11 +879,25 @@ protected:
const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &curl) const;
/** @brief Project a vector coefficient onto the ND basis functions
@param tk Edge tangent vectors for this element type
@param d2t Offset into tk for each degree of freedom
@param vc Vector coefficient to be projected
@param Trans Transformation from reference to physical coordinates
@param dofs Expansion coefficients for the approximation of vc
*/
void Project_ND(const double *tk, const Array<int> &d2t,
VectorCoefficient &vc, ElementTransformation &Trans,
Vector &dofs) const;
/// Projects the vector of values given at FE nodes to ND space
/** Project vector values onto the ND basis functions
@param tk Edge tangent vectors for this element type
@param d2t Offset into tk for each degree of freedom
@param vc Vector values at each interpolation point
@param Trans Transformation from reference to physical coordinates
@param dofs Expansion coefficients for the approximation of vc
*/
void Project_ND(const double *tk, const Array<int> &d2t,
Vector &vc, ElementTransformation &Trans,
Vector &dofs) const;
@@ -866,6 +907,19 @@ protected:
const double *tk, const Array<int> &d2t,
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const;
/** @brief Project vector-valued basis functions onto the ND basis functions
@param tk Edge tangent vectors for this element type
@param d2t Offset into tk for each degree of freedom
@param fe Vector-valued finite element basis
@param Trans Transformation from reference to physical coordinates
@param I Expansion coefficients for the approximation of each basis
function
Note: If the FiniteElement, fe, is scalar-valued the projection will
assume that a FiniteElementSpace is being used to define a vector
field using the scalar basis functions for each component of the
vector field.
*/
void Project_ND(const double *tk, const Array<int> &d2t,
const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
+18 -8
View File
@@ -467,15 +467,26 @@ const
fes->GetElementDofs(i, dofs);
fes->DofsToVDofs(vdim-1, dofs);
const FiniteElement *FElem = fes->GetFE(i);
MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
int dof = FElem->GetDof();
Vector DofVal(dof), loc_data(dof);
GetSubVector(dofs, loc_data);
for (int k = 0; k < n; k++)
if (FElem->GetMapType() == FiniteElement::VALUE)
{
FElem->CalcShape(ir.IntPoint(k), DofVal);
vals(k) = DofVal * loc_data;
for (int k = 0; k < n; k++)
{
FElem->CalcShape(ir.IntPoint(k), DofVal);
vals(k) = DofVal * loc_data;
}
}
else
{
ElementTransformation *Tr = fes->GetElementTransformation(i);
for (int k = 0; k < n; k++)
{
Tr->SetIntPoint(&ir.IntPoint(k));
FElem->CalcPhysShape(*Tr, DofVal);
vals(k) = DofVal * loc_data;
}
}
}
@@ -989,15 +1000,14 @@ void GridFunction::GetVectorValues(ElementTransformation &T,
if (FElem->GetRangeType() == FiniteElement::SCALAR)
{
MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
Vector shape(dof);
int vdim = fes->GetVDim();
vals.SetSize(vdim, nip);
for (int j = 0; j < nip; j++)
{
const IntegrationPoint &ip = ir.IntPoint(j);
FElem->CalcShape(ip, shape);
T.SetIntPoint(&ip);
FElem->CalcPhysShape(T, shape);
for (int k = 0; k < vdim; k++)
{
+12
View File
@@ -2164,6 +2164,7 @@ HypreSmoother::HypreSmoother() : Solver()
B = X = V = Z = NULL;
X0 = X1 = NULL;
fir_coeffs = NULL;
A_is_symmetric = false;
}
HypreSmoother::HypreSmoother(HypreParMatrix &_A, int _type,
@@ -2183,6 +2184,7 @@ HypreSmoother::HypreSmoother(HypreParMatrix &_A, int _type,
B = X = V = Z = NULL;
X0 = X1 = NULL;
fir_coeffs = NULL;
A_is_symmetric = false;
SetOperator(_A);
}
@@ -2470,6 +2472,16 @@ void HypreSmoother::Mult(const Vector &b, Vector &x) const
Mult(*B, *X);
}
void HypreSmoother::MultTranspose(const Vector &b, Vector &x) const
{
if (A_is_symmetric || type == 0 || type == 1 || type == 5)
{
Mult(b, x);
return;
}
mfem_error("HypreSmoother::MultTranspose (...) : undefined!\n");
}
HypreSmoother::~HypreSmoother()
{
if (B) { delete B; }
+12
View File
@@ -638,6 +638,9 @@ protected:
/// Combined coefficients for windowing and Chebyshev polynomials.
double* fir_coeffs;
/// A flag that indicates whether the linear system matrix A is symmetric
bool A_is_symmetric;
public:
/** Hypre smoother types:
0 = Jacobi
@@ -684,6 +687,12 @@ public:
entries in the associated matrix. */
void SetPositiveDiagonal(bool pos = true) { pos_l1_norms = pos; }
/** Explicitly indicate whether the linear system matrix A is symmetric. If A
is symmetric, the smoother will also be symmetric. In this case, calling
MultTranspose will be redirected to Mult. (This is also done if the
smoother is diagonal.) By default, A is assumed to be nonsymmetric. */
void SetOperatorSymmetry(bool is_sym) { A_is_symmetric = is_sym; }
/** Set/update the associated operator. Must be called after setting the
HypreSmoother type and options. */
virtual void SetOperator(const Operator &op);
@@ -692,6 +701,9 @@ public:
virtual void Mult(const HypreParVector &b, HypreParVector &x) const;
virtual void Mult(const Vector &b, Vector &x) const;
/// Apply transpose of the smoother to relax the linear system Ax=b
virtual void MultTranspose(const Vector &b, Vector &x) const;
virtual ~HypreSmoother();
};
-1
View File
@@ -651,7 +651,6 @@ public:
virtual void SetOperator(const Operator &op) = 0;
};
/// Identity Operator I: x -> x.
class IdentityOperator : public Operator
{
+411 -2
View File
@@ -1556,6 +1556,7 @@ void NewtonSolver::SetOperator(const Operator &op)
width = op.Width();
MFEM_ASSERT(height == width, "square Operator is required.");
xcur.SetSize(width);
r.SetSize(width);
c.SetSize(width);
}
@@ -1615,9 +1616,20 @@ void NewtonSolver::Mult(const Vector &b, Vector &x) const
break;
}
prec->SetOperator(oper->GetGradient(x));
grad = &oper->GetGradient(x);
prec->SetOperator(*grad);
prec->Mult(r, c); // c = [DF(x_i)]^{-1} [F(x_i)-b]
if (lin_rtol_type)
{
AdaptiveLinRtolPreSolve(x, it, norm);
}
prec->Mult(r, c); // c = [DF(x_i)]^{-1} [F(x_i)-b]
if (lin_rtol_type)
{
AdaptiveLinRtolPostSolve(c, r, it, norm);
}
const double c_scale = ComputeScalingFactor(x, b);
if (c_scale == 0.0)
@@ -1641,6 +1653,403 @@ void NewtonSolver::Mult(const Vector &b, Vector &x) const
final_norm = norm;
}
void NewtonSolver::SetAdaptiveLinRtol(const int type,
const double rtol0,
const double rtol_max,
const double alpha,
const double gamma)
{
lin_rtol_type = type;
lin_rtol0 = rtol0;
lin_rtol_max = rtol_max;
this->alpha = alpha;
this->gamma = gamma;
}
void NewtonSolver::AdaptiveLinRtolPreSolve(const Vector &x,
const int it,
const double fnorm) const
{
// Assume that when adaptive linear solver relative tolerance is activated,
// we are working with an iterative solver.
auto iterative_solver = static_cast<IterativeSolver *>(prec);
// Adaptive linear solver relative tolerance
double eta;
// Safeguard threshold
double sg_threshold = 0.1;
if (it == 0)
{
eta = lin_rtol0;
}
else
{
if (lin_rtol_type == 1)
{
// eta = gamma * abs(||F(x1)|| - ||F(x0) + DF(x0) s0||) / ||F(x0)||
eta = gamma * abs(fnorm - lnorm_last) / fnorm_last;
}
else if (lin_rtol_type == 2)
{
// eta = gamma * (||F(x1)|| / ||F(x0)||)^alpha
eta = gamma * pow(fnorm / fnorm_last, alpha);
}
else
{
MFEM_ABORT("Unknown adaptive linear solver rtol version");
}
// Safeguard rtol from "oversolving" ?!
const double sg_eta = gamma * pow(eta_last, alpha);
if (sg_eta > sg_threshold) { eta = std::max(eta, sg_eta); }
}
eta = std::min(eta, lin_rtol_max);
iterative_solver->SetRelTol(eta);
eta_last = eta;
if (print_level >= 0)
{
mfem::out << "Eisenstat-Walker rtol = " << eta << "\n";
}
}
void NewtonSolver::AdaptiveLinRtolPostSolve(const Vector &x,
const Vector &b,
const int it,
const double fnorm) const
{
fnorm_last = fnorm;
// If version 1 is chosen, the true linear residual norm has to be computed
// and in most cases we can only retrieve the preconditioned linear residual
// norm.
if (lin_rtol_type == 1)
{
// lnorm_last = ||F(x0) + DF(x0) s0||
Vector linres(x.Size());
grad->Mult(x, linres);
linres -= b;
lnorm_last = Norm(linres);
}
}
void AndersonAcceleration::QRdelete(std::deque<Vector *> &Q, DenseMatrix &R) const
{
Vector temp(Q[0]->Size());
for (int i=0; i<(maxVecs-1); i++) {
double d = sqrt( R(i,i+1)*R(i,i+1) + R(i+1,i+1)*R(i+1,i+1) );
double c = R(i,i+1) / d;
double s = R(i+1,i+1) / d;
R(i,i+1) = d;
R(i+1,i+1) = 0;
if (i < (maxVecs-2)) {
for (int j=(i+2); j<maxVecs; j++) {
d = c*R(i,j) + s*R(i+1,j);
R(i+1,j) = -s*R(i,j) + c*R(i+1,j);
R(i,j) = d;
}
}
// temp = c*Q[i] + s*Q[i+1];
add(c, *(Q[i]), s, *(Q[i+1]), temp);
// Q[i+1] = -s*Q[i] + c*Q[i+1];
*(Q[i+1]) *= c;
Q[i+1] -> Add(-s, *(Q[i]));
*(Q[i]) = temp;
}
// Shift Q <- Q[:,0:(m-2)], i.e., delete last column of Q
delete Q.back();
Q.pop_back();
// Shift columns of R to the left by one, R = R[0:(m2), 1:(m-1)]
for (int j=1; j<maxVecs; j++) {
for (int i=0; i<maxVecs; i++) {
R(i,j-1) = R(i,j);
}
}
}
void AndersonAcceleration::SetOperator(const Operator &op)
{
oper = &op;
height = op.Height();
width = op.Width();
MFEM_ASSERT(height == width, "square Operator is required.");
}
void AndersonAcceleration::FixedPointMult(const Vector &b,
const Vector &x, Vector &y, Vector &r) const
{
// Assume Operator represents a fixed-point operator *with
// right-hand side*, so we iterate x_{k+1} = M^{-1}G(x_k)
if (isFixedPointOp) {
oper->Mult(x, y);
if (prec) {
prec->Mult(y,r);
y = r;
r -= x;
}
else {
r = y;
r -= x;
}
}
// Otherwise add x to y and not to residual r = y - x
else {
oper->Mult(x, r);
r *= -1;
r += b;
if (prec) {
prec->Mult(r,y);
r = y;
y += x;
}
else {
y = r;
y += x;
}
}
}
void AndersonAcceleration::Mult(const Vector &b, Vector &x) const
{
MFEM_ASSERT(oper != NULL, "the Operator is not set (use SetOperator).");
int n = width;
int numVecs = 0;
double resid, norm_df;
double min_diag = 1e-13;
final_norm = -1;
// Check vector is initialized, set to zero for
// iterative_mode = false
if (x.Size() != n) {
x.SetSize(n);
x = 0.0;
}
else if (!iterative_mode) {
x = 0.0;
}
// Storage containers for acceleration
std::deque<Vector *> G;
std::deque<Vector *> Q;
DenseMatrix R(maxVecs);
R = 0.0;
Vector g_old(n);
Vector g_current(n);
Vector f_old(n);
Vector f_current(n);
Vector gamma(maxVecs);
Vector rhs(maxVecs);
Vector correction;
if (omega > 0 && std::abs(omega - 1) > 1e-14) {
correction.SetSize(n);
}
Vector *dg;
Vector *df;
// Loop over AA iterations
int k;
for (k=0; k<max_iter; k++) {
// Compute g_current = G(x), f_current = G(x) - x
this->FixedPointMult(b, x, g_current, f_current);
// Check norm of current approximation to fixed point G(u) = u
resid = Norm(f_current);
MFEM_ASSERT(IsFinite(resid), "||G(u) - u|| = " << resid);
if (print_level == 1)
{
mfem::out << " Iteration : " << setw(3) << k
<< " ||G(u) - u|| = " << resid << endl;
}
// Set stopping tolerance on first iteration.
if (final_norm < 0) {
final_norm = std::max(rel_tol*resid, abs_tol);
}
// Check for convergence
if (resid <= final_norm)
{
final_norm = resid;
final_iter = k;
converged = 1;
goto finish;
}
// Start Anderson Acceleration after AAstart FP iterations
if (k > AAstart) {
// df = f_current - f_old;
df = new Vector(n);
add(1.0, f_current, -1.0, f_old, *df);
// dg = g_current - g_old;
dg = new Vector(n);
add(1.0, g_current, -1.0, g_old, *dg);
if (numVecs < maxVecs) {
G.push_back(dg);
}
else {
delete G[0];
G.pop_front();
G.push_back(dg);
}
numVecs++;
dg = NULL;
}
f_old = f_current;
g_old = g_current;
// First iteration or initial fixed-point iterations
if (numVecs == 0) {
x = g_current;
continue;
}
// All later iterations: orthogonalize and find best approximation
if (numVecs == 1) {
norm_df = Norm(*df);
MFEM_ASSERT(IsFinite(norm_df), "norm_df = " << norm_df);
(*df) /= norm_df;
Q.push_back(df);
R(0,0) = norm_df;
df = NULL;
}
else {
// Remove first column in basis F and R, reorthogonalize
if (numVecs > maxVecs) {
this->QRdelete(Q, R);
numVecs--;
}
// Compute last column of R
for (int i=0; i<(numVecs-1); i++) {
R(i,numVecs-1) = Dot(*(Q[i]), *df);
// df -= R(i,numVecs-1) * Q[i]
df -> Add(-R(i,numVecs-1), *(Q[i]));
}
norm_df = Norm(*df);
MFEM_ASSERT(IsFinite(norm_df), "norm_df = " << norm_df);
(*df) /= norm_df;
Q.push_back(df);
R(numVecs-1, numVecs-1) = norm_df;
df = NULL;
}
// Back solve for new weights, R\gamma = Q^T * f_current
rhs = 0.0;
gamma = 0.0;
for (int i=0; i<numVecs; i++) {
rhs(i) = Dot(*(Q[i]), f_current); // Form right hand side
}
for (int i=(numVecs-1); i>=0; i--) {
double temp = rhs(i);
for (int j=(i+1); j<numVecs; j++) {
temp -= R(i,j)*gamma(j);
}
if (std::abs(R(i,i)) < min_diag) {
gamma(i) = 0.0;
std::cout << "Diagonal of R -- " << R(i,i) << " ~ 0.\n";
}
else {
gamma(i) = temp / R(i,i);
}
}
/// DEBUG --> test backsolve
Vector test(numVecs);
for (int i=0; i<numVecs; i++) {
test(i) = 0;
for (int j=i; j<numVecs; j++) {
test(i) += R(i,j) * gamma(j);
}
if (std::abs(rhs(i) - test(i)) > 1e-10) {
std::cout << "Bad solve! Err = " << rhs(i) - test(i) << "\n";
}
}
// Compute updated solution x = g_current G*\gamma
x = g_current;
for (int i=0; i<numVecs; i++) {
// x -= gamma(i)*G[i]
x.Add(-gamma(i), *(G[i]));
}
// Apply damped iteration for \omega \in (0,1),
// x -= (1omega) * (f_current Q*R*gamma);
if (omega > 0 && std::abs(omega - 1) > 1e-14) {
// Redefine rhs = R*gamma
for(int i=0; i<numVecs; i++) {
rhs(i) = 0;
for (int j=i; j<numVecs; j++) {
rhs(i) += R(i,j)*gamma(j);
}
}
correction = f_current;
for (int i=0; i<numVecs; i++) {
// correction -= rhs(i)*Q[i]
correction.Add(-rhs(i), *(Q[i]));
}
// x -= (1 - omega) * correction;
x.Add( -(1 - omega), correction);
}
// Restart AA minimization by eliminating all vectors but the most recent
if (restart && (numVecs == maxVecs)) {
for (int i=0; i<(maxVecs-1); i++) {
delete G[0];
G.pop_front();
delete Q[0];
Q.pop_front();
}
R = 0.0;
R(0,0) = norm_df;
numVecs = 1;
if (print_level == 1)
{
mfem::out << "Restarting..." << '\n';
}
}
}
// Compute final residual, save counts for solve
this->FixedPointMult(b, x, g_current, f_current);
resid = Norm(f_current);
MFEM_ASSERT(IsFinite(resid), "||G(u) - u|| = " << resid);
final_norm = resid;
final_iter = max_iter;
if (resid <= final_norm) converged = 1;
else converged = 0;
finish:
if (print_level == 3)
{
mfem::out << " Iteration : " << setw(3) << k
<< " ||G(u) - u|| = " << resid << endl;
}
else if (print_level == 2)
{
mfem::out << "Anderson Acceleration: Number of iterations: " << final_iter << '\n';
}
if (print_level >= 0 && !converged)
{
mfem::out << "Anderson Acceleration: No convergence!\n";
}
// Cleanup pointers
for (int i=0; i<numVecs; i++) {
delete G[0];
G.pop_front();
delete Q[0];
Q.pop_front();
}
delete dg;
delete df;
}
void LBFGSSolver::Mult(const Vector &b, Vector &x) const
{
MFEM_VERIFY(oper != NULL, "the Operator is not set (use SetOperator).");
+113 -1
View File
@@ -14,6 +14,7 @@
#include "../config/config.hpp"
#include "densemat.hpp"
#include <deque>
#ifdef MFEM_USE_MPI
#include <mpi.h>
@@ -406,7 +407,40 @@ void MINRES(const Operator &A, Solver &B, const Vector &b, Vector &x,
class NewtonSolver : public IterativeSolver
{
protected:
mutable Vector r, c;
mutable Vector xcur, r, c;
mutable Operator *grad;
// Adaptive linear solver rtol variables
// Method to determine rtol, 0 means the adaptive algorithm is deactivated.
int lin_rtol_type = 0;
// rtol to use in first iteration
double lin_rtol0;
// Maximum rtol
double lin_rtol_max;
// Function norm ||F(x)|| of the previous iterate
mutable double fnorm_last = 0.0;
// Linear residual norm of the previous iterate
mutable double lnorm_last = 0.0;
// Forcing term (linear residual rtol) from the previous iterate
mutable double eta_last = 0.0;
// Eisenstat-Walker factor gamma
double gamma;
// Eisenstat-Walker factor alpha
double alpha;
/** @brief Method for the adaptive linear solver rtol invoked before the
linear solve. */
void AdaptiveLinRtolPreSolve(const Vector &x,
const int it,
const double fnorm) const;
/** @brief Method for the adaptive linear solver rtol invoked after the
linear solve. */
void AdaptiveLinRtolPostSolve(const Vector &x,
const Vector &b,
const int it,
const double fnorm) const;
public:
NewtonSolver() { }
@@ -434,8 +468,86 @@ public:
/** @brief This method can be overloaded in derived classes to perform
computations that need knowledge of the newest Newton state. */
virtual void ProcessNewState(const Vector &x) const { }
const Vector &GetCurrentResidual() const { return r; }
const Vector &GetCurrentIterate() const { return xcur; }
/// Enable adaptive linear solver relative tolerance algorithm.
/** Compute a relative tolerance for the Krylov method after each nonlinear
iteration, based on the algorithm presented in [1].
The maximum linear solver relative tolerance @a rtol_max should be < 1. For
@a type 1 the parameters @a alpha and @a gamma are ignored. For @a type 2
@a alpha has to be between 0 and 1 and @a gamma between 1 and 2.
[1] Eisenstat, Stanley C., and Homer F. Walker. "Choosing the forcing terms
in an inexact Newton method."
*/
void SetAdaptiveLinRtol(const int type = 2,
const double rtol0 = 0.5,
const double rtol_max = 0.9,
const double alpha = 0.5 * (1.0 + sqrt(5.0)),
const double gamma = 1.0);
};
/// Nonlinear Anderson Acceleration
class AndersonAcceleration : public IterativeSolver
{
protected:
int maxVecs; // see SetKDim()
int AAstart;
bool restart;
bool isFixedPointOp;
double omega;
/// Apply fixed-point Mult and compute residual.
// For !isFixedPointOp:
// y <-- G(x) = x + A(x) - b and r <-- G(x) - x = A(x) - b
// For isFixedPointOp:
// y <-- G(x) = A(x) - b and r <-- G(x) - x = A(x) - b - x
void FixedPointMult(const Vector &b, const Vector &x, Vector &y, Vector &r) const;
// Helper function for Anderson Acceleration
void QRdelete(std::deque<Vector *> &Q, DenseMatrix &R) const;
public:
AndersonAcceleration() : maxVecs(25), AAstart(0), omega(1),
restart(false), isFixedPointOp(false) { }
#ifdef MFEM_USE_MPI
AndersonAcceleration(MPI_Comm _comm) : IterativeSolver(_comm),
maxVecs(25), AAstart(0), omega(1), restart(false),
isFixedPointOp(false) { }
#endif
/// Boolean describing whether the action of the operator is such
// that we want to solve G(x) = x (true) or G(x) = 0 (false) for
// zero right-hand side vector b passed into Mult(). Default is
// false in construction of class.
void IsFixedPointOperator(bool isFixedPointOp_)
{ isFixedPointOp = isFixedPointOp_; }
/// Maximum number of vectors to store in Krylov-like space
void SetKDim(int dim) { maxVecs = dim; }
/// Number of fixed-point iterations to do before starting AA
void SetAAStart(int start_) { AAstart = start_; }
/// Boolean to restart, that is, erase entire space after maxVecs
// are stored (AAstart=true) or use a sliding space (AAstart=false)
// where one vector is deleted to make room for a new one.
void SetRestart(bool restart_) { restart = restart_; }
/// Set relaxation weight
void SetWeight(double omega_) { omega = omega_; }
virtual void SetOperator(const Operator &op);
virtual void Mult(const Vector &b, Vector &x) const;
};
/** L-BFGS method for solving F(x)=b for a given operator F, by minimizing
the norm of F(x) - b. Requires only the action of the operator F. */
class LBFGSSolver : public NewtonSolver
+1 -1
View File
@@ -536,7 +536,7 @@ clean: $(addsuffix /clean,$(EM_DIRS) $(TEST_DIRS))
distclean: clean config/clean doc/clean
rm -rf mfem/
INSTALL_SHARED_LIB = $(MFEM_CXX) $(MFEM_BUILD_FLAGS) $(INSTALL_SOFLAGS)\
INSTALL_SHARED_LIB = $(MFEM_CXX) $(MFEM_LINK_FLAGS) $(INSTALL_SOFLAGS)\
$(OBJECT_FILES) $(EXT_LIBS) -o $(PREFIX_LIB)/libmfem.$(SO_VER) && \
cd $(PREFIX_LIB) && ln -sf libmfem.$(SO_VER) libmfem.$(SO_EXT)
+17 -7
View File
@@ -61,15 +61,15 @@
// * mesh-optimizer -m stretched2D.mesh -o 2 -mid 2 -tid 1 -ni 50 -qo 5 -nor -vl 1 -alc 0.5 -fd -ae 1
//
// Blade shape:
// mesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 200 -bnd -qt 1 -qo 8
// mesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 30 -ls 3 -art 1 -bnd -qt 1 -qo 8
// Blade shape with FD-based solver:
// mesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 200 -bnd -qt 1 -qo 8 -fd
// mesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 30 -ls 4 -bnd -qt 1 -qo 8 -fd
// Blade limited shape:
// mesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 200 -bnd -qt 1 -qo 8 -lc 5000
// mesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -bnd -qt 1 -qo 8 -lc 5000
// ICF shape and equal size:
// mesh-optimizer -o 3 -mid 9 -tid 2 -ni 25 -ls 3 -qo 5
// mesh-optimizer -o 3 -mid 9 -tid 2 -ni 25 -ls 3 -art 2 -qo 5
// ICF shape and initial size:
// mesh-optimizer -o 3 -mid 9 -tid 3 -ni 100 -bnd -qt 1 -qo 8
// mesh-optimizer -o 3 -mid 9 -tid 3 -ni 30 -ls 3 -bnd -qt 1 -qo 8
// ICF shape:
// mesh-optimizer -o 3 -mid 1 -tid 1 -ni 100 -bnd -qt 1 -qo 8
// ICF limited shape:
@@ -114,6 +114,7 @@ int main(int argc, char *argv[])
int solver_type = 0;
int solver_iter = 20;
double solver_rtol = 1e-10;
int solver_art_type = 0;
int lin_solver = 2;
int max_lin_iter = 100;
bool move_bnd = true;
@@ -192,12 +193,17 @@ int main(int argc, char *argv[])
"Maximum number of Newton iterations.");
args.AddOption(&solver_rtol, "-rtol", "--newton-rel-tolerance",
"Relative tolerance for the Newton solver.");
args.AddOption(&solver_art_type, "-art", "--adaptive-rel-tol",
"Type of adaptive relative linear solver tolerance:\n\t"
"0: None (default)\n\t"
"1: Eisenstat-Walker type 1\n\t"
"2: Eisenstat-Walker type 2");
args.AddOption(&lin_solver, "-ls", "--lin-solver",
"Linear solver:\n\t"
"0: l1-Jacobi\n\t"
"1: CG\n\t"
"2: MINRES\n\t"
"3: MINRES + Jacobi preconditioner"
"3: MINRES + Jacobi preconditioner\n\t"
"4: MINRES + l1-Jacobi preconditioner");
args.AddOption(&max_lin_iter, "-li", "--lin-iter",
"Maximum number of iterations in the linear solve.");
@@ -205,7 +211,7 @@ int main(int argc, char *argv[])
"--fix-boundary",
"Enable motion along horizontal and vertical boundaries.");
args.AddOption(&combomet, "-cmb", "--combo-type",
"Combination of metrics options:"
"Combination of metrics options:\n\t"
"0: Use single metric\n\t"
"1: Shape + space-dependent size given analytically\n\t"
"2: Shape + adapted size given discretely; shared target");
@@ -845,6 +851,10 @@ int main(int argc, char *argv[])
solver.SetMaxIter(solver_iter);
solver.SetRelTol(solver_rtol);
solver.SetAbsTol(0.0);
if (solver_art_type > 0)
{
solver.SetAdaptiveLinRtol(solver_art_type, 0.5, 0.9);
}
solver.SetPrintLevel(verbosity_level >= 1 ? 1 : -1);
solver.SetOperator(a);
solver.Mult(b, x.GetTrueVector());
+17 -7
View File
@@ -61,15 +61,15 @@
// * mpirun -np 4 pmesh-optimizer -m stretched2D.mesh -o 2 -mid 2 -tid 1 -ni 50 -qo 5 -nor -vl 1 -alc 0.5 -fd -ae 1
//
// Blade shape:
// mpirun -np 4 pmesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 200 -bnd -qt 1 -qo 8
// mpirun -np 4 pmesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 30 -ls 3 -art 1 -bnd -qt 1 -qo 8
// Blade shape with FD-based solver:
// mpirun -np 4 pmesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 200 -bnd -qt 1 -qo 8 -fd
// mpirun -np 4 pmesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 30 -ls 4 -bnd -qt 1 -qo 8 -fd
// Blade limited shape:
// mpirun -np 4 pmesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -ni 200 -bnd -qt 1 -qo 8 -lc 5000
// mpirun -np 4 pmesh-optimizer -m blade.mesh -o 4 -mid 2 -tid 1 -bnd -qt 1 -qo 8 -lc 5000
// ICF shape and equal size:
// mpirun -np 4 pmesh-optimizer -o 3 -mid 9 -tid 2 -ni 25 -ls 3 -qo 5
// mpirun -np 4 pmesh-optimizer -o 3 -mid 9 -tid 2 -ni 25 -ls 3 -art 2 -qo 5
// ICF shape and initial size:
// mpirun -np 4 pmesh-optimizer -o 3 -mid 9 -tid 3 -ni 100 -bnd -qt 1 -qo 8
// mpirun -np 4 pmesh-optimizer -o 3 -mid 9 -tid 3 -ni 30 -ls 3 -bnd -qt 1 -qo 8
// ICF shape:
// mpirun -np 4 pmesh-optimizer -o 3 -mid 1 -tid 1 -ni 100 -bnd -qt 1 -qo 8
// ICF limited shape:
@@ -121,6 +121,7 @@ int main (int argc, char *argv[])
int solver_type = 0;
int solver_iter = 20;
double solver_rtol = 1e-10;
int solver_art_type = 0;
int lin_solver = 2;
int max_lin_iter = 100;
bool move_bnd = true;
@@ -201,12 +202,17 @@ int main (int argc, char *argv[])
"Maximum number of Newton iterations.");
args.AddOption(&solver_rtol, "-rtol", "--newton-rel-tolerance",
"Relative tolerance for the Newton solver.");
args.AddOption(&solver_art_type, "-art", "--adaptive-rel-tol",
"Type of adaptive relative linear solver tolerance:\n\t"
"0: None (default)\n\t"
"1: Eisenstat-Walker type 1\n\t"
"2: Eisenstat-Walker type 2");
args.AddOption(&lin_solver, "-ls", "--lin-solver",
"Linear solver:\n\t"
"0: l1-Jacobi\n\t"
"1: CG\n\t"
"2: MINRES\n\t"
"3: MINRES + Jacobi preconditioner"
"3: MINRES + Jacobi preconditioner\n\t"
"4: MINRES + l1-Jacobi preconditioner");
args.AddOption(&max_lin_iter, "-li", "--lin-iter",
"Maximum number of iterations in the linear solve.");
@@ -214,7 +220,7 @@ int main (int argc, char *argv[])
"--fix-boundary",
"Enable motion along horizontal and vertical boundaries.");
args.AddOption(&combomet, "-cmb", "--combo-type",
"Combination of metrics options:"
"Combination of metrics options:\n\t"
"0: Use single metric\n\t"
"1: Shape + space-dependent size given analytically\n\t"
"2: Shape + adapted size given discretely; shared target");
@@ -895,6 +901,10 @@ int main (int argc, char *argv[])
solver.SetMaxIter(solver_iter);
solver.SetRelTol(solver_rtol);
solver.SetAbsTol(0.0);
if (solver_art_type > 0)
{
solver.SetAdaptiveLinRtol(solver_art_type, 0.5, 0.9);
}
solver.SetPrintLevel(verbosity_level >= 1 ? 1 : -1);
solver.SetOperator(a);
solver.Mult(b, x.GetTrueVector());
File diff suppressed because it is too large Load Diff