diff --git a/CMake/FindAMGCL.cmake b/CMake/FindAMGCL.cmake new file mode 100644 index 0000000000000000000000000000000000000000..0099bad4c8c3b34266ff164c3cd28ab3512aafaa --- /dev/null +++ b/CMake/FindAMGCL.cmake @@ -0,0 +1,38 @@ +# Copyright 2020 University of Liège +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# FindAMGC.cmake - try to find AMGCL headers +# ---------------------------------------------------------------------------- +# output: +# AMGCL_FOUND : TRUE/FALSE +# AMGCL_INCLUDE_DIRS : where the amgcl/*.h are [cached] +# ---------------------------------------------------------------------------- +# autodetection: +# utiliser "CMAKE_PREFIX_PATH=c:\local" +# ou "CMAKE_INCLUDE_PATH=c:\local\include" +# ou "INCLUDE=c:\local\include" +# ---------------------------------------------------------------------------- + +# Find the header and check the version +find_path(AMGCL_INCLUDE_DIRS "amgcl/amg.hpp") +if (NOT AMGCL_INCLUDE_DIRS) + message(FATAL_ERROR "AMGCL headers not found! Define the path in the INCLUDE environment variable.") +endif() + +# handle the QUIETLY and REQUIRED arguments and set AMGCL_FOUND to TRUE +# if all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(AMGCL + FOUND_VAR AMGCL_FOUND + REQUIRED_VARS AMGCL_INCLUDE_DIRS) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dc6b95b7a92588820b3aec97234b10022358ce9..14c07d129263891979a580f7b6f8b72810ed3727 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ # Copyright 2020 University of Liège -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -31,7 +31,7 @@ MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) # Build type IF(NOT CMAKE_BUILD_TYPE) - SET( CMAKE_BUILD_TYPE "Release" CACHE STRING + SET( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) @@ -63,6 +63,7 @@ ENDIF() OPTION(USE_VTK "Compile with VTK" ON) OPTION(USE_MKL "Compile with Intel MKL" ON) OPTION(USE_MUMPS "Compile with MUMPS" ON) +OPTION(USE_AMGCL "Compile with AMGCL" ON) # -- DEPENDENCIES # Python @@ -74,8 +75,8 @@ ELSE() # use Python3_ROOT_DIR if wrong python found (e.g. anaconda) SET(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) SET(PYTHON_LIBRARIES ${Python3_LIBRARIES}) - SET(PYTHON_INCLUDE_PATH ${Python3_INCLUDE_DIRS}) - SET(PYTHONLIBS_VERSION_STRING ${Python3_VERSION}) + SET(PYTHON_INCLUDE_PATH ${Python3_INCLUDE_DIRS}) + SET(PYTHONLIBS_VERSION_STRING ${Python3_VERSION}) ENDIF() MESSAGE(STATUS "PYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}") MESSAGE(STATUS "PYTHON_LIBRARIES:FILEPATH=${PYTHON_LIBRARIES}") diff --git a/tbox/_src/tboxw.h b/tbox/_src/tboxw.h index 3da0640093557e341d636782a8ea0c232b2ca019..c1f489961462bd1f16bf7255526fac124f5a4eb1 100644 --- a/tbox/_src/tboxw.h +++ b/tbox/_src/tboxw.h @@ -36,6 +36,7 @@ #include "wGaussTetra4.h" #include "wGaussTri3.h" #include "wGmres.h" +#include "wGmresAmg.h" #include "wGmshExport.h" #include "wGmshImport.h" #include "wGroup.h" diff --git a/tbox/_src/tboxw.i b/tbox/_src/tboxw.i index 8f2c75bb2992ad3b81321d6c894916e5f138aab4..eb39b000a4bedd8d6291fb0b22adeafc3fe5b009 100644 --- a/tbox/_src/tboxw.i +++ b/tbox/_src/tboxw.i @@ -163,6 +163,8 @@ namespace std { %include "wSparseLu.h" %shared_ptr(tbox::Gmres); %include "wGmres.h" +%shared_ptr(tbox::GmresAmg); +%include "wGmresAmg.h" %include "wUnitTest.h" diff --git a/tbox/src/CMakeLists.txt b/tbox/src/CMakeLists.txt index 9947874da344934afabcce422f054ec571be3bfc..c23ee3cf9e011b9be7d95b5cad8ee9eb1d7e2e3f 100644 --- a/tbox/src/CMakeLists.txt +++ b/tbox/src/CMakeLists.txt @@ -1,11 +1,11 @@ # Copyright 2020 University of Liège -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -57,6 +57,14 @@ FIND_PACKAGE(EIGEN 3.3.4 REQUIRED) TARGET_INCLUDE_DIRECTORIES(tbox PUBLIC ${EIGEN_INCLUDE_DIRS}) TARGET_COMPILE_DEFINITIONS(tbox PUBLIC EIGEN_DONT_PARALLELIZE) +# -- AMGCL -- +IF(USE_AMGCL) + FIND_PACKAGE(OpenMP) + TARGET_LINK_LIBRARIES(tbox OpenMP::OpenMP_CXX) + FIND_PACKAGE(AMGCL REQUIRED) + TARGET_INCLUDE_DIRECTORIES(tbox PUBLIC ${AMGCL_INCLUDE_DIRS}) +ENDIF() + # -- MUMPS -- IF (USE_MUMPS) FIND_PACKAGE(MUMPS REQUIRED) diff --git a/tbox/src/wGmresAmg.cpp b/tbox/src/wGmresAmg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2ecf87181111e6784332211d1c8b38071799fa7 --- /dev/null +++ b/tbox/src/wGmresAmg.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2020 University of Liège + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wGmresAmg.h" +#include <amgcl/amg.hpp> +#include <amgcl/make_solver.hpp> +#include <amgcl/solver/gmres.hpp> +#include <amgcl/coarsening/smoothed_aggregation.hpp> +#include <amgcl/relaxation/ilut.hpp> +#include <amgcl/adapter/eigen.hpp> +#include <amgcl/backend/eigen.hpp> +using namespace tbox; + +void GmresAmg::analyze(Eigen::SparseMatrix<double> const &A) +{ + throw std::runtime_error("tbox::GmresAmg::analyze not implemented!\n"); +} +void GmresAmg::factorize(Eigen::SparseMatrix<double> const &A) +{ + throw std::runtime_error("tbox::GmresAmg::factorize not implemented!\n"); +} +void GmresAmg::solve(Eigen::Map<Eigen::VectorXd> const &b, Eigen::Map<Eigen::VectorXd> &x) +{ + throw std::runtime_error("tbox::GmresAmg::solve not implemented!\n"); +} +void GmresAmg::compute(Eigen::SparseMatrix<double> const &A, Eigen::Map<Eigen::VectorXd> const &b, Eigen::Map<Eigen::VectorXd> &x) +{ + // GMRES with AMG (smoothed agreg + ILUT) + typedef amgcl::backend::eigen<double> Backend; + typedef amgcl::make_solver<amgcl::amg<Backend, amgcl::coarsening::smoothed_aggregation, amgcl::relaxation::ilut>, amgcl::solver::gmres<Backend>> Solver; + + // Parameters + Solver::params p; + p.solver.M = 50; // restart + p.solver.tol = 1e-5; // relative tolerance + p.solver.maxiter = 1000; // max. n. iterations + p.precond.relax.p = 1; // fill-in + p.precond.relax.tau = 1e-6; // threshold + p.precond.ncycle = 2; // cycle shape (W) + p.precond.pre_cycles = 3; // number of cycles + p.precond.coarsening.aggr.eps_strong = 0.5; // AMG coupling + + // Convert to CRS and solve + Eigen::SparseMatrix<double, Eigen::RowMajor> AA = A; + Solver sol(AA, p); + std::tie(it, err) = sol(AA, b, x); +} + +void GmresAmg::write(std::ostream &out) const +{ + out << "GMRES-AMG (AMGCL)" << std::endl; +} diff --git a/tbox/src/wGmresAmg.h b/tbox/src/wGmresAmg.h new file mode 100644 index 0000000000000000000000000000000000000000..711acb83164053fcd4ce11b716c5d2e4699bd04c --- /dev/null +++ b/tbox/src/wGmresAmg.h @@ -0,0 +1,56 @@ +/* + * Copyright 2020 University of Liège + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WGMRESAMG_H +#define WGMRESAMG_H + +#include "tbox.h" +#include "wLinearSolver.h" +#include <Eigen/Sparse> + +namespace tbox +{ + +/** + * @brief GMRES with AMG preconditioner interface + * @authors Adrien Crovato + * @todo Configure solver in constructor and public methods + * @todo Find optimal or good-enough parameters + */ +class TBOX_API GmresAmg : public LinearSolver +{ + int it; ///< number of iterations + double err; ///< relative error +public: + GmresAmg() : LinearSolver() {} + virtual ~GmresAmg() {} + +#ifndef SWIG + virtual void analyze(Eigen::SparseMatrix<double> const &A) override; + virtual void factorize(Eigen::SparseMatrix<double> const &A) override; + virtual void solve(Eigen::Map<Eigen::VectorXd> const &b, Eigen::Map<Eigen::VectorXd> &x) override; + virtual void compute(Eigen::SparseMatrix<double> const &A, Eigen::Map<Eigen::VectorXd> const &b, Eigen::Map<Eigen::VectorXd> &x) override; + + virtual double getError() override { return err; } + virtual int getIterations() override { return it; } + + virtual void write(std::ostream &out) const override; +#endif +}; + +} // namespace tbox + +#endif // WGMRESAMG_H