26#if BITPIT_ENABLE_MPI==1
30#include "bitpit_common.hpp"
31#include "bitpit_LA.hpp"
33using namespace bitpit;
35const double SOLVER_RTOL = 1e-7;
36const double SOLVER_ATOL = 1e-50;
37const int SOLVER_MAXITS = 100;
89 m_multigrid(multigrid)
94 const static PetscInt GAMG_MAX_LEVELS;
95 const static PetscReal GAMG_THRESHOLD;
96 const static PetscReal GAMG_THRESHOLD_SCALE;
115 KSPGetPC(this->m_KSP, &pc);
116 PCSetType(pc, PCGAMG);
118 std::vector<PetscReal> thresholds(GAMG_MAX_LEVELS);
119 for (
int i = 0; i < GAMG_MAX_LEVELS; ++i) {
120 thresholds[i] = GAMG_THRESHOLD;
123 PCGAMGSetNSmooths(pc, 0);
124#if (PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR <= 17)
125#if BITPIT_ENABLE_MPI == 1
127 PCGAMGSetSymGraph(pc, PETSC_TRUE);
132 PCGAMGSetNlevels(pc, GAMG_MAX_LEVELS);
133#if (PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 16)
134 PCGAMGSetThreshold(pc, thresholds.data(), GAMG_MAX_LEVELS);
135 PCGAMGSetThresholdScale(pc, GAMG_THRESHOLD_SCALE);
137 PCGAMGSetThreshold(pc, GAMG_THRESHOLD);
145 PCMGGetCoarseSolve(pc, &coarseKSP);
147 PC coarsePreconditioner;
148 KSPGetPC(coarseKSP, &coarsePreconditioner);
149 PCSetType(coarsePreconditioner, PCSVD);
153const PetscInt AMGSplitSystemSolver::GAMG_MAX_LEVELS = 10;
154const PetscReal AMGSplitSystemSolver::GAMG_THRESHOLD = 0.02;
155const PetscReal AMGSplitSystemSolver::GAMG_THRESHOLD_SCALE = 1.0;
163int run_dump(
int rank,
int nProcs)
166 log::cout() <<
"Running dump example..." << std::endl;
175 }
else if (nProcs == 2) {
208 log::cout() <<
"Building matrix..." << std::endl;
210 std::vector<long> rowPattern(1);
211 std::vector<double> rowValues(blockSize * blockSize);
213#if BITPIT_ENABLE_MPI==1
214 SparseMatrix matrix(MPI_COMM_WORLD,
true, blockSize, nRows, nCols, nNZ);
216 int rowOffset = matrix.getRowGlobalOffset();
217 int colOffset = matrix.getColGlobalOffset();
225 for (
int i = 0; i < nRows; ++i) {
226 rowPattern[0] = colOffset + i;
227 for (
int k = 0; k < blockSize; ++k) {
230 rowValues[kk] = 1. / (double) (blockSize * (rowOffset + i) + k + 1);
233 matrix.addRow(rowPattern, rowValues);
239 log::cout() <<
"Building solver..." << std::endl;
241 bool multigrid =
false;
246 std::vector<int> splitSizes(2);
248 splitSizes[1] = blockSize - splitSizes[0];
250 solver.assembly(matrix, SystemSplitStrategy::SYSTEM_SPLIT_STRATEGY_FULL, splitSizes);
252 double *rhs = solver.getRHSRawPtr();
253 for (
int i = 0; i < nCols; ++i) {
255 for (std::size_t split = 0; split < splitSizes.size(); ++split) {
256 for (
int k = 0; k < splitSizes[split]; ++k) {
257 rhs[blockSize * i + field] = std::pow(10, split);
263 solver.restoreRHSRawPtr(rhs);
265 double *initialSolution = solver.getSolutionRawPtr();
266 for (
int i = 0; i < nRows; ++i) {
267 initialSolution[i] = 0;
269 solver.restoreSolutionRawPtr(initialSolution);
272 solver.exportMatrix(
"LA_example_0002_matrix.txt", SystemSolver::FILE_ASCII);
273 solver.exportRHS(
"LA_example_0002_rhs.txt", SystemSolver::FILE_ASCII);
274 solver.exportSolution(
"LA_example_0002_solution.txt", SystemSolver::FILE_ASCII);
277 log::cout() <<
"Dumping initialized linear system..." << std::endl;
279 solver.dumpSystem(
"bitpit linear system",
".",
"LA_example_0002_linear_system_");
283 options.
atol = SOLVER_ATOL;
284 options.
rtol = SOLVER_RTOL;
285 options.
maxits = SOLVER_MAXITS;
288 KSPOptions &externalOptions = solver.getKSPOptions();
289 externalOptions = options;
291 for (
int i = 0; i < solver.getSplitCount(); ++i) {
292 KSPOptions &splitOptions = solver.getSplitKSPOptions(i);
293 splitOptions = options;
297 log::cout() <<
"Solve linear system..." << std::endl;
300 const KSPStatus &externalStatus = solver.getKSPStatus();
301 log::cout() <<
" External convergence reason: " << externalStatus.convergence <<
" in its: " << externalStatus.its << std::endl;
303 for (
int split = 0; split < solver.getSplitCount(); ++split) {
304 const KSPStatus &splitStatus = solver.getSplitKSPStatus(split);
305 log::cout() <<
" Split #" << split <<
" convergence reason: " << splitStatus.convergence <<
" in its: " << splitStatus.its << std::endl;
307 log::cout() <<
"Linear system solved." << std::endl;
310 log::cout() <<
"Export solution..." << std::endl;
311 solver.exportSolution(
"LA_example_0002_linear_system_solution.dat", bitpit::SystemSolver::FILE_BINARY);
316 log::cout() <<
"Comparing solutions..." << std::endl;
318 log::cout() <<
" Tolerance = " << SOLVER_RTOL << std::endl;
320 std::size_t nRowElements = solver.getRowElementCount();
322 bool isSolutionCorrect =
true;
323 const double *solution = solver.getSolutionRawReadPtr();
324 for (std::size_t i = 0; i < nRowElements; ++i) {
325 std::size_t globalDOF = rowOffset * blockSize + i;
328 double expectedSolution;
329 if (globalDOF == 0) {
330 expectedSolution = 1;
331 }
else if ((globalDOF == 1) || ((globalDOF + 1) % blockSize) != 0) {
332 expectedSolution =
static_cast<double>(globalDOF + 1);
334 expectedSolution =
static_cast<double>(10 * (globalDOF + 1));
338 std::stringstream message;
339 message <<
"Solutions do not match for global DOF #" << globalDOF <<
".";
340 message <<
" Expected solution is " << expectedSolution;
341 message <<
", current solution is " << solution[i] <<
".";
342 log::cout() << message.str() << std::endl;
343 isSolutionCorrect =
false;
346 solver.restoreSolutionRawReadPtr(solution);
347 if (isSolutionCorrect) {
348 log::cout() <<
"Solutions match." << std::endl;
360int run_restore(
int rank,
int nProcs)
366 log::cout() <<
"Running restore example..." << std::endl;
369 log::cout() <<
"Restoring linear system ..." << std::endl;
370 bool multigrid =
false;
375#if BITPIT_ENABLE_MPI==1
376 solver.restoreSystem(MPI_COMM_WORLD,
false,
".",
"LA_example_0002_linear_system_");
378 solver.restoreSystem(
".",
"LA_example_0002_linear_system_");
380 log::cout() <<
"Linear system restored." << std::endl;
383 solver.exportMatrix(
"LA_example_0002_restored_matrix.txt", SystemSolver::FILE_ASCII);
384 solver.exportRHS(
"LA_example_0002_restored_rhs.txt", SystemSolver::FILE_ASCII);
385 solver.exportSolution(
"LA_example_0002_restored_solution.txt", SystemSolver::FILE_ASCII);
389 options.
atol = SOLVER_ATOL;
390 options.
rtol = SOLVER_RTOL;
391 options.
maxits = SOLVER_MAXITS;
394 KSPOptions &externalOptions = solver.getKSPOptions();
395 externalOptions = options;
397 for (
int i = 0; i < solver.getSplitCount(); ++i) {
398 KSPOptions &splitOptions = solver.getSplitKSPOptions(i);
399 splitOptions = options;
403 log::cout() <<
"Solving linear system..." << std::endl;
406 const KSPStatus &externalStatus = solver.getKSPStatus();
407 log::cout() <<
" External convergence reason: " << externalStatus.convergence <<
" in its: " << externalStatus.its << std::endl;
409 for (
int split = 0; split < solver.getSplitCount(); ++split) {
410 const KSPStatus &splitStatus = solver.getSplitKSPStatus(split);
411 log::cout() <<
" Split #" << split <<
" convergence reason: " << splitStatus.convergence <<
" in its: " << splitStatus.its << std::endl;
413 log::cout() <<
"Linear system solved." << std::endl;
416 bool compareSolutions =
true;
417 if (compareSolutions) {
419 log::cout() <<
"Storing computed solution for comparison..." << std::endl;
420 std::size_t nRowElements = solver.getRowElementCount();
421 std::vector<double> expectedSolution(nRowElements, 0.0);
422 double *computedSolution = solver.getSolutionRawPtr();
423 for (std::size_t i = 0; i < nRowElements; ++i) {
424 expectedSolution[i] = computedSolution[i];
426 solver.restoreSolutionRawPtr(computedSolution);
429 log::cout() <<
"Restoring solution..." << std::endl;
430 solver.importSolution(
"LA_example_0002_linear_system_solution.dat");
431 log::cout() <<
"Solution restored." << std::endl;
436 log::cout() <<
"Comparing solutions..." << std::endl;
438 log::cout() <<
" Tolerance = " << SOLVER_RTOL << std::endl;
440 bool isSolutionCorrect =
true;
441 const double *solution = solver.getSolutionRawReadPtr();
442 for (std::size_t i = 0; i < nRowElements; ++i) {
444 std::stringstream message;
445 message <<
"Solutions do not match for local DOF #" << i <<
".";
446 message <<
" Expected solution is " << expectedSolution[i];
447 message <<
", current solution is " << solution[i] <<
".";
448 log::cout() << message.str() << std::endl;
449 isSolutionCorrect =
false;
452 solver.restoreSolutionRawReadPtr(solution);
453 if (isSolutionCorrect) {
454 log::cout() <<
"Solutions match." << std::endl;
464int main(
int argc,
char *argv[])
466#if BITPIT_ENABLE_MPI==1
467 MPI_Init(&argc, &argv);
476#if BITPIT_ENABLE_MPI==1
477 MPI_Comm_size(MPI_COMM_WORLD, &nProcs);
478 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
487 log::cout() <<
"Build, dump, solve and restore split linear system" << std::endl;
491 status = run_dump(rank, nProcs);
496 status = run_restore(rank, nProcs);
500 }
catch (
const std::exception &exception) {
505#if BITPIT_ENABLE_MPI==1
The class AMGSplitSystemSolver is derived form SplitSystemSolver and it allows to solve the linear sy...
AMGSplitSystemSolver(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 SplitSystemSolver class allows to solve a split linear system.
void setupPreconditioner() override
bool isPartitioned() const
#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.