26#if BITPIT_ENABLE_MPI==1
30#include "bitpit_common.hpp"
31#include "bitpit_LA.hpp"
33using namespace bitpit;
85 m_multigrid(multigrid)
90 const static PetscInt GAMG_MAX_LEVELS;
91 const static PetscReal GAMG_THRESHOLD;
92 const static PetscReal GAMG_THRESHOLD_SCALE;
111 KSPGetPC(this->m_KSP, &pc);
112 PCSetType(pc, PCGAMG);
114 std::vector<PetscReal> thresholds(GAMG_MAX_LEVELS);
115 for (
int i = 0; i < GAMG_MAX_LEVELS; ++i) {
116 thresholds[i] = GAMG_THRESHOLD;
119 PCGAMGSetNSmooths(pc, 0);
120#if (PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR <= 17)
121#if BITPIT_ENABLE_MPI == 1
123 PCGAMGSetSymGraph(pc, PETSC_TRUE);
128 PCGAMGSetNlevels(pc, GAMG_MAX_LEVELS);
129#if (PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 16)
130 PCGAMGSetThreshold(pc, thresholds.data(), GAMG_MAX_LEVELS);
131 PCGAMGSetThresholdScale(pc, GAMG_THRESHOLD_SCALE);
133 PCGAMGSetThreshold(pc, GAMG_THRESHOLD);
141 PCMGGetCoarseSolve(pc, &coarseKSP);
143 PC coarsePreconditioner;
144 KSPGetPC(coarseKSP, &coarsePreconditioner);
145 PCSetType(coarsePreconditioner, PCSVD);
149const PetscInt AMGSystemSolver::GAMG_MAX_LEVELS = 10;
150const PetscReal AMGSystemSolver::GAMG_THRESHOLD = 0.02;
151const PetscReal AMGSystemSolver::GAMG_THRESHOLD_SCALE = 1.0;
159int run_dump(
int rank,
int nProcs)
162 log::cout() <<
"Running dump example..." << std::endl;
171 }
else if (nProcs == 2) {
204 log::cout() <<
"Building matrix..." << std::endl;
206 std::vector<long> rowPattern(1);
207 std::vector<double> rowValues(blockSize * blockSize);
209#if BITPIT_ENABLE_MPI==1
210 SparseMatrix matrix(MPI_COMM_WORLD,
true, blockSize, nRows, nCols, nNZ);
212 int rowOffset = matrix.getRowGlobalOffset();
213 int colOffset = matrix.getColGlobalOffset();
221 for (
int i = 0; i < nRows; ++i) {
222 rowPattern[0] = colOffset + i;
223 for (
int k = 0; k < blockSize; ++k) {
226 rowValues[kk] = 1. / (double) (blockSize * (rowOffset + i) + k + 1);
229 matrix.addRow(rowPattern, rowValues);
235 log::cout() <<
"Building solver..." << std::endl;
237 bool multigrid =
true;
242 solver.assembly(matrix);
244 double *rhs = solver.getRHSRawPtr();
245 for (
int i = 0; i < blockSize * nCols; ++i) {
248 solver.restoreRHSRawPtr(rhs);
250 double *initialSolution = solver.getSolutionRawPtr();
251 for (
int i = 0; i < nRows; ++i) {
252 initialSolution[i] = 0;
254 solver.restoreSolutionRawPtr(initialSolution);
257 solver.exportMatrix(
"LA_example_0001_matrix.txt", SystemSolver::FILE_ASCII);
258 solver.exportRHS(
"LA_example_0001_rhs.txt", SystemSolver::FILE_ASCII);
259 solver.exportSolution(
"LA_example_0001_solution.txt", SystemSolver::FILE_ASCII);
262 log::cout() <<
"Dumping initialized linear system..." << std::endl;
264 solver.dumpSystem(
"bitpit linear system",
".",
"LA_example_0001_linear_system_");
268 options.
atol = 1e-50;
274 log::cout() <<
"Solve linear system..." << std::endl;
277 const KSPStatus &status = solver.getKSPStatus();
278 log::cout() <<
"Reason: " << status.convergence <<
" in its: " << status.its << std::endl;
279 log::cout() <<
"Linear system solved." << std::endl;
282 log::cout() <<
"Export solution..." << std::endl;
283 solver.exportSolution(
"LA_example_0001_linear_system_solution.dat", bitpit::SystemSolver::FILE_BINARY);
288 log::cout() <<
"Comparing solutions..." << std::endl;
290 const double TOLERANCE = options.
rtol;
293 std::size_t nRowElements = solver.getRowElementCount();
295 bool isSolutionCorrect =
true;
296 const double *solution = solver.getSolutionRawReadPtr();
297 for (std::size_t i = 0; i < nRowElements; ++i) {
298 std::size_t globalDOF = rowOffset * blockSize + i;
301 double expectedSolution =
static_cast<double>(globalDOF + 1);
303 std::stringstream message;
304 message <<
"Solutions do not match for global DOF #" << globalDOF <<
".";
305 message <<
" Expected solution is " << expectedSolution;
306 message <<
", current solution is " << solution[i] <<
".";
307 log::cout() << message.str() << std::endl;
308 isSolutionCorrect =
false;
311 solver.restoreSolutionRawReadPtr(solution);
312 if (isSolutionCorrect) {
313 log::cout() <<
"Solutions match." << std::endl;
325int run_restore(
int rank,
int nProcs)
331 log::cout() <<
"Running restore example..." << std::endl;
334 log::cout() <<
"Restoring linear system ..." << std::endl;
335 bool multigrid =
true;
340#if BITPIT_ENABLE_MPI==1
341 solver.restoreSystem(MPI_COMM_WORLD,
false,
".",
"LA_example_0001_linear_system_");
343 solver.restoreSystem(
".",
"LA_example_0001_linear_system_");
345 log::cout() <<
"Linear system restored." << std::endl;
348 solver.exportMatrix(
"LA_example_0001_restored_matrix.txt", SystemSolver::FILE_ASCII);
349 solver.exportRHS(
"LA_example_0001_restored_rhs.txt", SystemSolver::FILE_ASCII);
350 solver.exportSolution(
"LA_example_0001_restored_solution.txt", SystemSolver::FILE_ASCII);
354 options.
atol = 1e-50;
360 log::cout() <<
"Solving linear system..." << std::endl;
363 const KSPStatus &status = solver.getKSPStatus();
364 log::cout() <<
"Reason: " << status.convergence <<
" in its: " << status.its << std::endl;
365 log::cout() <<
"Linear system solved." << std::endl;
368 bool compareSolutions =
true;
369 if (compareSolutions) {
371 log::cout() <<
"Storing computed solution for comparison..." << std::endl;
372 std::size_t nRowElements = solver.getRowElementCount();
373 std::vector<double> expectedSolution(nRowElements, 0.0);
374 double *computedSolution = solver.getSolutionRawPtr();
375 for (std::size_t i = 0; i < nRowElements; ++i) {
376 expectedSolution[i] = computedSolution[i];
378 solver.restoreSolutionRawPtr(computedSolution);
381 log::cout() <<
"Restoring solution..." << std::endl;
382 solver.importSolution(
"LA_example_0001_linear_system_solution.dat");
383 log::cout() <<
"Solution restored." << std::endl;
388 log::cout() <<
"Comparing solutions..." << std::endl;
390 const double TOLERANCE = options.
rtol;
393 bool isSolutionCorrect =
true;
394 const double *solution = solver.getSolutionRawReadPtr();
395 for (std::size_t i = 0; i < nRowElements; ++i) {
397 std::stringstream message;
398 message <<
"Solutions do not match for local DOF #" << i <<
".";
399 message <<
" Expected solution is " << expectedSolution[i];
400 message <<
", current solution is " << solution[i] <<
".";
401 log::cout() << message.str() << std::endl;
402 isSolutionCorrect =
false;
405 solver.restoreSolutionRawReadPtr(solution);
406 if (isSolutionCorrect) {
407 log::cout() <<
"Solutions match." << std::endl;
417int main(
int argc,
char *argv[])
419#if BITPIT_ENABLE_MPI==1
420 MPI_Init(&argc, &argv);
429#if BITPIT_ENABLE_MPI==1
430 MPI_Comm_size(MPI_COMM_WORLD, &nProcs);
431 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
440 log::cout() <<
"Build, dump, solve and restore linear system" << std::endl;
444 status = run_dump(rank, nProcs);
449 status = run_restore(rank, nProcs);
453 }
catch (
const std::exception &exception) {
458#if BITPIT_ENABLE_MPI==1
The class AMGSystemSolver is derived form SystemSolver and it allows to solve the linear system using...
AMGSystemSolver(bool transpose, bool multigrid, bool debug)
void setupPreconditioner(PC pc, const KSPOptions &options) const override
void initialize(log::Mode mode, bool reset, int nProcesses, int rank)
void setDefaultVisibility(log::Visibility visibility)
The SystemSolver class provides methods for building and solving large linear systems.
bool isPartitioned() const
virtual void setupPreconditioner()
#define BITPIT_UNUSED(variable)
int linearIndexRowMajor(int row, int col, int nRows, int nCols)
void transpose(std::vector< std::vector< T > > &, std::vector< std::vector< T > > &)
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
Logger & debug(log::Visibility defaultVisibility)
LoggerManager & manager()
PetscInt maxits
Number of iterations at which the GMRES method restarts.
PetscScalar atol
Relative convergence tolerance, relative decrease in the preconditioned residual norm.
PetscScalar rtol
Maximum number of iterations.
PetscBool initial_non_zero
Number of levels of fill used by the preconditioner.