25#include "system_solvers_large.hpp"
27#include "bitpit_common.hpp"
28#include "bitpit_containers.hpp"
29#include "bitpit_IO.hpp"
30#include "bitpit_operators.hpp"
34#include "petscsystypes.h"
41#include <unordered_set>
44#define PETSC_NULLPTR PETSC_NULL
124#if BITPIT_ENABLE_MPI==1
155 options.sorted =
false;
184 if (m_transpose == transpose) {
194 VecDestroy(&m_solution);
200 m_transpose = transpose;
271#if BITPIT_ENABLE_MPI==1
472PetscErrorCode PetscManager::displayLogView()
474 return PetscLogView(PETSC_VIEWER_STDOUT_WORLD);
485 throw std::runtime_error(
"Initialization options can be set only before initializing the solver.");
488 m_options.push_back(option);
508 throw std::runtime_error(
"Initialization options can be set only before initializing the solver.");
511 for (
int i = 1; i < argc; ++i) {
512 m_options.push_back(argv[i]);
524 throw std::runtime_error(
"Initialization options can be set only before initializing the solver.");
527 for (
const std::string &option : options) {
528 m_options.push_back(option);
545void PetscManager::enableLogView()
547 if (m_logViewEnabled) {
551#if (PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 7)
552 PetscLogDefaultBegin();
556 PetscRegisterFinalize(&(PetscManager::displayLogView));
557 m_logViewEnabled =
true;
564 : m_externalMPIInitialization(true), m_externalPETScInitialization(true),
565 m_options(std::vector<std::string>(1,
"bitpit")), m_logViewEnabled(false)
584 PetscBool isPetscInitialized;
585 PetscInitialized(&isPetscInitialized);
587 return (!isPetscInitialized);
595#if BITPIT_ENABLE_MPI==1
612 PetscBool isPetscInitialized;
613 PetscInitialized(&isPetscInitialized);
614 if (isPetscInitialized) {
618#if BITPIT_ENABLE_MPI==1
621 MPI_Finalized(&isMPIFinalized);
622 if (isMPIFinalized) {
623 throw std::runtime_error(
"PETSc finalization cannot be called after MPI finaliation.");
631 std::string help =
"None";
632 std::string programName =
"bitpit_petsc_manager";
634 int argc = 1 + m_options.size();
635 char **argv =
new char*[argc + 1];
636 argv[0] = strdup(programName.data());
637 for (std::size_t i = 0; i < m_options.size(); i++) {
638 argv[1 + i] = strdup(m_options[i].data());
640 argv[argc] =
nullptr;
642#if BITPIT_ENABLE_MPI==1
644 int isMPIInitialized;
645 MPI_Initialized(&isMPIInitialized);
646 if (!isMPIInitialized) {
647 MPI_Init(&argc, &argv);
648 m_externalMPIInitialization =
false;
653 PetscInitialize(&argc, &argv, 0, help.data());
654 m_externalPETScInitialization =
false;
662 for (
int i = 0; i < argc; ++i) {
677#if BITPIT_ENABLE_MPI==1
695#if BITPIT_ENABLE_MPI==1
698 MPI_Finalized(&isMPIFinalized);
699 if (isMPIFinalized) {
705 if (m_externalPETScInitialization) {
710 PetscBool isPetscFinalized;
711 PetscFinalized(&isPetscFinalized);
712 if (!isPetscFinalized) {
716#if BITPIT_ENABLE_MPI==1
718 if (!m_externalMPIInitialization) {
723 return (!isPetscFinalized);
745#if BITPIT_ENABLE_MPI==1
763int SystemSolver::m_nInstances = 0;
840 : m_flatten(flatten), m_transpose(transpose),
841 m_A(PETSC_NULLPTR), m_rhs(PETSC_NULLPTR), m_solution(PETSC_NULLPTR),
842 m_rowReordering(PETSC_NULLPTR), m_colReordering(PETSC_NULLPTR),
843 m_convergenceMonitorEnabled(debug),
844 m_KSP(PETSC_NULLPTR), m_KSPDirty(true),
845 m_prefix(prefix), m_assembled(false),
846#if BITPIT_ENABLE_MPI==1
847 m_communicator(MPI_COMM_SELF), m_partitioned(false),
849 m_forceConsistency(false)
852 if (m_nInstances == 0) {
887#if BITPIT_ENABLE_MPI==1
934 throw std::runtime_error(
"Unable to assembly the system. The matrix is not yet assembled.");
939 assembly<SystemSolver>(
static_cast<const Assembler &
>(assembler), reordering);
964 assembly<SystemSolver>(assembler, reordering);
977void SystemSolver::update(
long nRows,
const long *rows,
const SparseMatrix &elements)
981 throw std::runtime_error(
"Unable to update the system. The element storage is not yet assembled.");
986 update<SystemSolver>(nRows, rows,
static_cast<const Assembler &
>(assembler));
1012void SystemSolver::update(
long nRows,
const long *rows,
const Assembler &assembler)
1014 update<SystemSolver>(nRows, rows, assembler);
1024 if (m_A == PETSC_NULLPTR) {
1029 MatGetBlockSize(m_A, &blockSize);
1045 if (m_A == PETSC_NULLPTR) {
1050 MatGetLocalSize(m_A, &nRows, NULL);
1067 if (m_A == PETSC_NULLPTR) {
1072 MatGetLocalSize(m_A, NULL, &nCols);
1089 if (m_A == PETSC_NULLPTR) {
1094 MatGetLocalSize(m_A, &nRows, NULL);
1110 if (m_A == PETSC_NULLPTR) {
1115 MatGetLocalSize(m_A, NULL, &nCols);
1120#if BITPIT_ENABLE_MPI==1
1132 if (m_A == PETSC_NULLPTR) {
1137 MatGetSize(m_A, &nRows, NULL);
1154 if (m_A == PETSC_NULLPTR) {
1159 MatGetSize(m_A, NULL, &nCols);
1175 if (m_A == PETSC_NULLPTR) {
1180 MatGetSize(m_A, &nRows, NULL);
1195 if (m_A == PETSC_NULLPTR) {
1200 MatGetSize(m_A, NULL, &nCols);
1212 return m_partitioned;
1245 throw std::runtime_error(
"Unable to solve the system. The system is not yet assembled.");
1282 PetscErrorCode solverError;
1284 solverError = KSPSolve(m_KSP, m_rhs, m_solution);
1286 solverError = KSPSolveTranspose(m_KSP, m_rhs, m_solution);
1290 const char *petscMessage =
nullptr;
1291 PetscErrorMessage(solverError, &petscMessage, PETSC_NULLPTR);
1292 std::string message =
"Unable to solver the system. " + std::string(petscMessage);
1293 throw std::runtime_error(message);
1309 if (m_forceConsistency) {
1310 removeNullSpaceFromRHS();
1336 const int DUMP_VERSION = 1;
1338 return DUMP_VERSION;
1348 const PetscInt *rowReordering = PETSC_NULLPTR;
1349 if (m_rowReordering) {
1350 ISGetIndices(m_rowReordering, &rowReordering);
1354 int blockSize = assembler.getBlockSize();
1358 MatGetType(m_A, &matrixType);
1361 long nAssemblerRows = assembler.getRowCount();
1363 long nRowsElements = assembler.getRowElementCount();
1364 long nColsElements = assembler.getColElementCount();
1366 long nGlobalRowsElements;
1367 long nGlobalColsElements;
1368#if BITPIT_ENABLE_MPI == 1
1369 nGlobalRowsElements = assembler.getRowGlobalElementCount();
1370 nGlobalColsElements = assembler.getColGlobalElementCount();
1372 nGlobalRowsElements = nRowsElements;
1373 nGlobalColsElements = nColsElements;
1376 MatSetSizes(m_A, nRowsElements, nColsElements, nGlobalRowsElements, nGlobalColsElements);
1383 int allocationExpansion;
1384 if (strcmp(matrixType, MATSEQAIJ) == 0) {
1385 allocationExpansion = blockSize;
1386#if BITPIT_ENABLE_MPI == 1
1387 }
else if (strcmp(matrixType, MATMPIAIJ) == 0) {
1388 allocationExpansion = blockSize;
1391 allocationExpansion = 1;
1394 long nAllocatedRows = allocationExpansion * nAssemblerRows;
1396 std::vector<int> d_nnz(nAllocatedRows, 0);
1397 for (
long n = 0; n < nAssemblerRows; ++n) {
1399 if (rowReordering) {
1400 matrixRow = rowReordering[matrixRow];
1403 int nAssemblerRowNZ = assembler.getRowNZCount(n);
1405 long matrixRowOffset = matrixRow * allocationExpansion;
1406 for (
int i = 0; i < allocationExpansion; ++i) {
1407 d_nnz[matrixRowOffset + i] = allocationExpansion * nAssemblerRowNZ;
1411#if BITPIT_ENABLE_MPI == 1
1412 std::vector<int> o_nnz(nAllocatedRows, 0);
1413 if (m_partitioned) {
1414 long nAssemblerCols = assembler.getColCount();
1416 long assemblerDiagonalBegin = assembler.getColGlobalOffset();
1417 long assemblerDiagonalEnd = assemblerDiagonalBegin + nAssemblerCols;
1420 for (
long n = 0; n < nAssemblerRows; ++n) {
1422 if (rowReordering) {
1423 matrixRow = rowReordering[matrixRow];
1426 assembler.getRowPattern(n, &assemblerRowPattern);
1427 int nAssemblerRowNZ = assemblerRowPattern.
size();
1429 long matrixRowOffset = matrixRow * allocationExpansion;
1430 for (
int k = 0; k < nAssemblerRowNZ; ++k) {
1431 long id = assemblerRowPattern[k];
1432 if (id < assemblerDiagonalBegin || id >= assemblerDiagonalEnd) {
1433 for (
int i = 0; i < allocationExpansion; ++i) {
1434 o_nnz[matrixRowOffset + i] += allocationExpansion;
1435 d_nnz[matrixRowOffset + i] -= allocationExpansion;
1443 if (strcmp(matrixType, MATSEQAIJ) == 0) {
1444 MatSeqAIJSetPreallocation(m_A, 0, d_nnz.data());
1445 }
else if (strcmp(matrixType, MATSEQBAIJ) == 0) {
1446 MatSeqBAIJSetPreallocation(m_A, blockSize, 0, d_nnz.data());
1447#if BITPIT_ENABLE_MPI == 1
1448 }
else if (strcmp(matrixType, MATMPIAIJ) == 0) {
1449 MatMPIAIJSetPreallocation(m_A, 0, d_nnz.data(), 0, o_nnz.data());
1450 }
else if (strcmp(matrixType, MATMPIBAIJ) == 0) {
1451 MatMPIBAIJSetPreallocation(m_A, blockSize, 0, d_nnz.data(), 0, o_nnz.data());
1454 throw std::runtime_error(
"Matrix format not supported.");
1458 MatSetOption(m_A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE);
1460#if PETSC_VERSION_GE(3, 12, 0)
1464 MatSetOption(m_A, MAT_SUBSET_OFF_PROC_ENTRIES, PETSC_TRUE);
1468 if (m_rowReordering) {
1469 ISRestoreIndices(m_rowReordering, &rowReordering);
1473 matrixUpdate(assembler.getRowCount(),
nullptr, assembler);
1479 MatSetOption(m_A, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
1495 throw std::runtime_error(
"Matrix should be created before filling it.");
1525 if (assembler.getBlockSize() != blockSize) {
1526 std::string message =
"Unable to update the matrix.";
1527 message +=
" The block size of the assembler is not equal to the block size of the system matrix.";
1528 throw std::runtime_error(message);
1532 const PetscInt *rowReordering = PETSC_NULLPTR;
1533 if (m_rowReordering) {
1534 ISGetIndices(m_rowReordering, &rowReordering);
1537 const PetscInt *colReordering = PETSC_NULLPTR;
1538 if (m_colReordering) {
1539 ISGetIndices(m_colReordering, &colReordering);
1543 PetscInt colGlobalBegin;
1544 PetscInt colGlobalEnd;
1545 MatGetOwnershipRangeColumn(m_A, &colGlobalBegin, &colGlobalEnd);
1546 colGlobalBegin /= blockSize;
1547 colGlobalEnd /= blockSize;
1549 PetscInt rowGlobalOffset;
1550 MatGetOwnershipRange(m_A, &rowGlobalOffset, PETSC_NULLPTR);
1551 rowGlobalOffset /= blockSize;
1556#if PETSC_VERSION_GE(3, 12, 0)
1566 PetscBool matrixSortedFull = (assemblyOptions.
full && assemblyOptions.sorted) ? PETSC_TRUE : PETSC_FALSE;
1567 MatSetOption(m_A, MAT_SORTED_FULL, matrixSortedFull);
1586 bool fastUpdate =
isAssembled() && (blockSize == 1) && assemblyOptions.
full && assemblyOptions.sorted;
1593 const long assemblerMaxRowNZ = std::max(assembler.getMaxRowNZCount(), 0L);
1595 bool patternDirectUpdate = !colReordering && (
sizeof(long) ==
sizeof(PetscInt));
1596 bool valuesDirectUpdate = (
sizeof(double) ==
sizeof(PetscScalar));
1599 std::vector<PetscInt> petscRowPatternStorage;
1600 const PetscInt *petscRowPattern;
1601 if (!patternDirectUpdate) {
1603 petscRowPatternStorage.resize(assemblerMaxRowNZ);
1604 petscRowPattern = petscRowPatternStorage.data();
1608 std::vector<PetscScalar> petscRowValuesStorage;
1609 const PetscScalar *petscRowValues;
1610 if (!valuesDirectUpdate) {
1611 long assemblerMaxRowNZElements = blockSize * blockSize * assemblerMaxRowNZ;
1613 petscRowValuesStorage.resize(assemblerMaxRowNZElements);
1614 petscRowValues = petscRowValuesStorage.data();
1617 for (
long n = 0; n < nRows; ++n) {
1626 if (rowReordering) {
1627 row = rowReordering[row];
1630 const PetscInt globalRow = rowGlobalOffset + row;
1634 assembler.getRowValues(n, &rowValues);
1636 assembler.getRowData(n, &rowPattern, &rowValues);
1639 if (rowValues.
size() == 0) {
1644 const std::size_t rowPatternSize = rowPattern.
size();
1646 if (valuesDirectUpdate) {
1647 petscRowValues =
reinterpret_cast<const PetscScalar *
>(rowValues.
data());
1649 std::copy(rowValues.
cbegin(), rowValues.
cend(), petscRowValuesStorage.begin());
1653 MatSetValuesRow(m_A, globalRow, petscRowValues);
1656 if (patternDirectUpdate) {
1657 petscRowPattern =
reinterpret_cast<const PetscInt *
>(rowPattern.
data());
1659 for (std::size_t k = 0; k < rowPatternSize; ++k) {
1660 long globalCol = rowPattern[k];
1661 if (colReordering) {
1662 if (globalCol >= colGlobalBegin && globalCol < colGlobalEnd) {
1663 long col = globalCol - colGlobalBegin;
1664 col = colReordering[col];
1665 globalCol = colGlobalBegin + col;
1669 petscRowPatternStorage[k] = globalCol;
1674 if (blockSize > 1) {
1675 MatSetValuesBlocked(m_A, 1, &globalRow, rowPatternSize, petscRowPattern, petscRowValues, INSERT_VALUES);
1677 MatSetValues(m_A, 1, &globalRow, rowPatternSize, petscRowPattern, petscRowValues, INSERT_VALUES);
1683 MatAssemblyBegin(m_A, MAT_FINAL_ASSEMBLY);
1684 MatAssemblyEnd(m_A, MAT_FINAL_ASSEMBLY);
1687 if (rowReordering) {
1688 ISRestoreIndices(m_rowReordering, &rowReordering);
1691 if (colReordering) {
1692 ISRestoreIndices(m_colReordering, &colReordering);
1704 const std::string &prefix)
const
1718#if BITPIT_ENABLE_MPI==1
1725 const std::string &prefix,
bool redistribute)
1728 const std::string &prefix)
1733#if BITPIT_ENABLE_MPI==1
1734 restoreMatrix(directory, prefix +
"A", redistribute, &m_A);
1736 restoreMatrix(directory, prefix +
"A", &m_A);
1756 MatCreateVecs(m_A, &m_solution, &m_rhs);
1758 MatCreateVecs(m_A, &m_rhs, &m_solution);
1776 if (!solution.empty()) {
1791 if (!rhsFilePath.empty()) {
1795 if (!solutionFilePath.empty()) {
1824 const std::string &prefix)
const
1828 dumpVector(m_rhs, directory, prefix +
"rhs");
1829 dumpVector(m_solution, directory, prefix +
"solution");
1840 const std::string &prefix)
1844 restoreVector(directory, prefix +
"rhs", m_A, VECTOR_SIDE_RIGHT, &m_rhs);
1845 restoreVector(directory, prefix +
"solution", m_A, VECTOR_SIDE_LEFT, &m_solution);
1864 PetscScalar *raw_rhs;
1865 VecGetArray(m_rhs, &raw_rhs);
1887 const PetscScalar *raw_rhs;
1888 VecGetArrayRead(m_rhs, &raw_rhs);
1901 VecRestoreArray(m_rhs, &raw_rhs);
1912 VecRestoreArrayRead(m_rhs, &raw_rhs);
1922 PetscScalar *raw_solution;
1923 VecGetArray(m_solution, &raw_solution);
1925 return raw_solution;
1945 const PetscScalar *raw_solution;
1946 VecGetArrayRead(m_solution, &raw_solution);
1948 return raw_solution;
1959 VecRestoreArray(m_solution, &raw_solution);
1970 VecRestoreArrayRead(m_solution, &raw_solution);
1998 throw std::runtime_error(
"Matrix should be created before filling it.");
2042 throw std::runtime_error(
"The RHS vector can be loaded only after assembling the system.");
2050 VecGetLocalSize(m_rhs, &size);
2052 PetscInt expectedSize;
2060 if (size != expectedSize) {
2061 log::cout() <<
"The imported RHS vector is not compatible with the matrix" << std::endl;
2062 log::cout() <<
"The size of the imported RHS vector is " << size << std::endl;
2063 log::cout() <<
"The expected size of RHS vector is " << expectedSize << std::endl;
2064 throw std::runtime_error(
"The imported RHS vector is not compatible with the matrix");
2095 throw std::runtime_error(
"The solution vector can be loaded only after assembling the system.");
2103 VecGetLocalSize(m_solution, &size);
2105 PetscInt expectedSize;
2113 if (size != expectedSize) {
2114 log::cout() <<
"The imported solution vector is not compatible with the matrix" << std::endl;
2115 log::cout() <<
"The size of the imported solution vector is " << size << std::endl;
2116 log::cout() <<
"The expected size of solution vector is " << expectedSize << std::endl;
2117 throw std::runtime_error(
"The imported solution vector is not compatible with the matrix");
2133 const std::string &prefix)
const
2135 int partitioningBlock = getBinaryArchiveBlock();
2139 if (partitioningBlock <= 0) {
2140 openBinaryArchive(header, directory, prefix +
"info", -1, &systemArchive);
2142 std::ostream &systemStream = systemArchive.
getStream();
2154 closeBinaryArchive(&systemArchive);
2167#if BITPIT_ENABLE_MPI==1
2179#if BITPIT_ENABLE_MPI==1
2181 const std::string &directory,
const std::string &prefix)
2189#if BITPIT_ENABLE_MPI == 1
2191 setCommunicator(communicator);
2196 openBinaryArchive(directory, prefix +
"info", -1, &systemArchive);
2197 std::istream &systemStream = systemArchive.
getStream();
2200 restoreInfo(systemStream);
2203#if BITPIT_ENABLE_MPI==1
2204 matrixRestore(systemStream, directory, prefix, redistribute);
2206 matrixRestore(systemStream, directory, prefix);
2210 vectorsRestore(systemStream, directory, prefix);
2213 closeBinaryArchive(&systemArchive);
2219 initializeKSPOptions();
2222 initializeKSPStatus();
2232 if (systemStream.good()) {
2233#if BITPIT_ENABLE_MPI==1
2247#if BITPIT_ENABLE_MPI == 1
2269#if BITPIT_ENABLE_MPI == 1
2270 MatCreate(m_communicator, matrix);
2272 MatCreate(PETSC_COMM_SELF, matrix);
2276 bool creatBlockMatrix =
false;
2278 creatBlockMatrix =
false;
2280 creatBlockMatrix = (rowBlockSize == colBlockSize) && (rowBlockSize != 1);
2283#if BITPIT_ENABLE_MPI == 1
2284 if (m_partitioned) {
2285 if (creatBlockMatrix) {
2286 MatSetType(*matrix, MATMPIBAIJ);
2288 MatSetType(*matrix, MATMPIAIJ);
2293 if (creatBlockMatrix) {
2294 MatSetType(*matrix, MATSEQBAIJ);
2296 MatSetType(*matrix, MATSEQAIJ);
2301 if (rowBlockSize == colBlockSize) {
2302 MatSetBlockSize(*matrix, rowBlockSize);
2303 }
else if (rowBlockSize != 1 || colBlockSize != 1) {
2304 MatSetBlockSizes(*matrix, rowBlockSize, colBlockSize);
2322 Mat *subMatrices, Mat *matrix)
const
2325#if BITPIT_ENABLE_MPI == 1
2326 MatCreateNest(
getCommunicator(), nNestRows, PETSC_NULLPTR, nNestCols, PETSC_NULLPTR, subMatrices, matrix);
2328 MatCreateNest(PETSC_COMM_SELF, nNestRows, PETSC_NULLPTR, nNestCols, PETSC_NULLPTR, subMatrices, matrix);
2332 if (rowBlockSize == colBlockSize) {
2333 MatSetBlockSize(*matrix, rowBlockSize);
2334 }
else if (rowBlockSize != 1 || colBlockSize != 1) {
2335 MatSetBlockSizes(*matrix, rowBlockSize, colBlockSize);
2351 std::ifstream fileStream(filePath.c_str());
2352 if (!fileStream.good()) {
2353 throw std::runtime_error(
"The PETSc matrix file \"" + filePath +
"\" doesn't exists.");
2359#if BITPIT_ENABLE_MPI==1
2360 PetscViewerCreate(m_communicator, &viewer);
2362 PetscViewerCreate(PETSC_COMM_SELF, &viewer);
2364 PetscViewerSetType(viewer, PETSCVIEWERBINARY);
2365 PetscViewerFileSetMode(viewer, FILE_MODE_READ);
2366 PetscViewerFileSetName(viewer, filePath.c_str());
2367 MatLoad(matrix, viewer);
2368 PetscViewerDestroy(&viewer);
2378#if BITPIT_ENABLE_MPI==1
2392 int partitioningBlock = getBinaryArchiveBlock();
2396 if (partitioningBlock <= 0) {
2397 openBinaryArchive(
"", directory, name +
".info", -1, &infoArchive);
2398 std::ostream &infoStream = infoArchive.
getStream();
2400 bool matrixExists = matrix;
2402 if (!matrixExists) {
2403 closeBinaryArchive(&infoArchive);
2407 PetscInt rowBlockSize;
2408 PetscInt colBlockSize;
2409 MatGetBlockSizes(matrix, &rowBlockSize, &colBlockSize);
2413 closeBinaryArchive(&infoArchive);
2420#if BITPIT_ENABLE_MPI==1
2424 openBinaryArchive(
"", directory, name +
".partitioning", partitioningBlock, &partitioningArchive);
2425 std::ostream &partitioningStream = partitioningArchive.
getStream();
2427 PetscInt nLocalRows;
2428 PetscInt nLocalCols;
2429 MatGetLocalSize(matrix, &nLocalRows, &nLocalCols);
2433 PetscInt nGlobalRows;
2434 PetscInt nGlobalCols;
2435 MatGetSize(matrix, &nGlobalRows, &nGlobalCols);
2439 closeBinaryArchive(&partitioningArchive);
2454#if BITPIT_ENABLE_MPI==1
2464#if BITPIT_ENABLE_MPI==1
2466 bool redistribute, Mat *matrix)
const
2476 openBinaryArchive(directory, name +
".info", -1, &infoArchive);
2477 std::istream &infoStream = infoArchive.
getStream();
2481 if (!matrixExists) {
2482 *matrix = PETSC_NULLPTR;
2483 closeBinaryArchive(&infoArchive);
2493 closeBinaryArchive(&infoArchive);
2495#if BITPIT_ENABLE_MPI==1
2498 int partitioningBlock = getBinaryArchiveBlock();
2501 openBinaryArchive(directory, name +
".partitioning", partitioningBlock, &partitioningArchive);
2502 std::istream &partitioningStream = partitioningArchive.
getStream();
2504 std::size_t nLocalRows;
2505 std::size_t nLocalCols;
2508 std::size_t nGlobalRows;
2509 std::size_t nGlobalCols;
2512 MatSetSizes(*matrix, nLocalRows, nLocalCols, nGlobalRows, nGlobalCols);
2514 closeBinaryArchive(&partitioningArchive);
2534 bool matrixExists = matrix;
2535 if (!matrixExists) {
2536 std::ofstream dataFile(filePath);
2539 std::ofstream infoFile(filePath +
".info");
2546 PetscViewerType viewerType;
2547 PetscViewerFormat viewerFormat;
2548 if (fileFormat == FILE_BINARY) {
2549 viewerType = PETSCVIEWERBINARY;
2550 viewerFormat = PETSC_VIEWER_DEFAULT;
2552 viewerType = PETSCVIEWERASCII;
2553 viewerFormat = PETSC_VIEWER_ASCII_MATLAB;
2556 PetscViewer matViewer;
2557#if BITPIT_ENABLE_MPI==1
2558 PetscViewerCreate(m_communicator, &matViewer);
2560 PetscViewerCreate(PETSC_COMM_SELF, &matViewer);
2562 PetscViewerSetType(matViewer, viewerType);
2563 PetscViewerFileSetMode(matViewer, FILE_MODE_WRITE);
2564 PetscViewerPushFormat(matViewer, viewerFormat);
2565 PetscViewerFileSetName(matViewer, filePath.c_str());
2568 MatView(matrix, matViewer);
2571 PetscViewerDestroy(&matViewer);
2583 *matrix = PETSC_NULLPTR;
2596#if BITPIT_ENABLE_MPI == 1
2597 VecCreate(m_communicator, vector);
2599 VecCreate(PETSC_COMM_SELF, vector);
2603#if BITPIT_ENABLE_MPI == 1
2604 if (m_partitioned) {
2605 VecSetType(*vector, VECMPI);
2609 VecSetType(*vector, VECSEQ);
2613 if (blockSize != 1) {
2614 VecSetBlockSize(*vector, blockSize);
2629#if BITPIT_ENABLE_MPI == 1
2630 VecCreateNest(
getCommunicator(), nestSize, PETSC_NULLPTR, subVectors, vector);
2632 VecCreateNest(PETSC_COMM_SELF, nestSize, PETSC_NULLPTR, subVectors, vector);
2636 if (blockSize != 1) {
2637 VecSetBlockSize(*vector, blockSize);
2653 std::ifstream fileStream(filePath);
2654 if (!fileStream.good()) {
2655 throw std::runtime_error(
"The file \"" + filePath +
"\" cannot be read.");
2661#if BITPIT_ENABLE_MPI==1
2662 PetscViewerCreate(m_communicator, &viewer);
2664 PetscViewerCreate(PETSC_COMM_SELF, &viewer);
2666 PetscViewerSetType(viewer, PETSCVIEWERBINARY);
2667 PetscViewerFileSetMode(viewer, FILE_MODE_READ);
2668 PetscViewerFileSetName(viewer, filePath.c_str());
2669 VecLoad(vector, viewer);
2670 PetscViewerDestroy(&viewer);
2682 VecGetLocalSize(vector, &size);
2684 PetscScalar *petscData;
2685 VecGetArray(vector, &petscData);
2686 for (
int i = 0; i < size; ++i) {
2687 petscData[i] = data[i];
2689 VecRestoreArray(vector, &petscData);
2699#if BITPIT_ENABLE_MPI==1
2713 int partitioningBlock = getBinaryArchiveBlock();
2716 if (partitioningBlock <= 0) {
2718 openBinaryArchive(
"", directory, name +
".info", -1, &infoArchive);
2719 std::ostream &infoStream = infoArchive.
getStream();
2721 bool vectorExists = vector;
2723 if (!vectorExists) {
2724 closeBinaryArchive(&infoArchive);
2729 VecGetBlockSize(vector, &blockSize);
2732 closeBinaryArchive(&infoArchive);
2739#if BITPIT_ENABLE_MPI==1
2742 int partitioningBlock = getBinaryArchiveBlock();
2745 openBinaryArchive(
"", directory, name +
".partitioning", partitioningBlock, &partitioningArchive);
2746 std::ostream &partitioningStream = partitioningArchive.
getStream();
2749 VecGetLocalSize(vector, &localSize);
2752 PetscInt globalSize;
2753 VecGetSize(vector, &globalSize);
2756 closeBinaryArchive(&partitioningArchive);
2776 Mat matrix, VectorSide side, Vec *vector)
const
2779 PetscInt nLocalRows;
2780 PetscInt nLocalCols;
2781 MatGetLocalSize(matrix, &nLocalRows, &nLocalCols);
2783 PetscInt nGlobalRows;
2784 PetscInt nGlobalCols;
2785 MatGetSize(matrix, &nGlobalRows, &nGlobalCols);
2787 std::size_t localSize = std::numeric_limits<std::size_t>::max();
2788 std::size_t globalSize = std::numeric_limits<std::size_t>::max();
2790 if (side == VECTOR_SIDE_RIGHT) {
2791 localSize = nLocalCols;
2792 globalSize = nGlobalCols;
2793 }
else if (side == VECTOR_SIDE_LEFT) {
2794 localSize = nLocalRows;
2795 globalSize = nGlobalRows;
2798 if (side == VECTOR_SIDE_RIGHT) {
2799 localSize = nLocalRows;
2800 globalSize = nGlobalRows;
2801 }
else if (side == VECTOR_SIDE_LEFT) {
2802 localSize = nLocalCols;
2803 globalSize = nGlobalCols;
2808 restoreVector(directory, name, localSize, globalSize, vector);
2817#if BITPIT_ENABLE_MPI==1
2827#if BITPIT_ENABLE_MPI==1
2829 bool redistribute, Vec *vector)
const
2837 std::size_t localSize = std::numeric_limits<std::size_t>::max();
2838 std::size_t globalSize = std::numeric_limits<std::size_t>::max();
2839#if BITPIT_ENABLE_MPI==1
2841 if (!redistribute) {
2842 int partitioningBlock = getBinaryArchiveBlock();
2845 openBinaryArchive(directory, name +
".partitioning", partitioningBlock, &partitioningArchive);
2846 std::istream &partitioningStream = partitioningArchive.
getStream();
2851 closeBinaryArchive(&partitioningArchive);
2856 restoreVector(directory, name, localSize, globalSize, vector);
2869 std::size_t localSize, std::size_t globalSize, Vec *vector)
const
2873 openBinaryArchive(directory, name +
".info", -1, &infoArchive);
2874 std::istream &infoStream = infoArchive.
getStream();
2878 if (!vectorExists) {
2879 *vector = PETSC_NULLPTR;
2880 closeBinaryArchive(&infoArchive);
2888 closeBinaryArchive(&infoArchive);
2891 PetscInt petscLocalSize;
2892 if (localSize != std::numeric_limits<std::size_t>::max()) {
2893 petscLocalSize =
static_cast<PetscInt
>(localSize);
2895 petscLocalSize = PETSC_DECIDE;
2898 PetscInt petscGlobalSize;
2899 if (globalSize != std::numeric_limits<std::size_t>::max()) {
2900 petscGlobalSize =
static_cast<PetscInt
>(globalSize);
2902 petscGlobalSize = PETSC_DETERMINE;
2905 if (petscLocalSize != PETSC_DECIDE || petscGlobalSize != PETSC_DETERMINE) {
2906 VecSetSizes(*vector, petscLocalSize, petscGlobalSize);
2921 if (!permutations) {
2925 PetscBool petscInvert;
2927 petscInvert = PETSC_TRUE;
2929 petscInvert = PETSC_FALSE;
2932 VecPermute(vector, permutations, petscInvert);
2946 bool vectorExists = vector;
2947 if (!vectorExists) {
2948 std::ofstream dataFile(filePath);
2951 std::ofstream infoFile(filePath +
".info");
2958 PetscViewerType viewerType;
2959 PetscViewerFormat viewerFormat;
2960 if (fileFormat == FILE_BINARY) {
2961 viewerType = PETSCVIEWERBINARY;
2962 viewerFormat = PETSC_VIEWER_DEFAULT;
2964 viewerType = PETSCVIEWERASCII;
2965 viewerFormat = PETSC_VIEWER_ASCII_MATLAB;
2969#if BITPIT_ENABLE_MPI==1
2970 PetscViewerCreate(m_communicator, &viewer);
2972 PetscViewerCreate(PETSC_COMM_SELF, &viewer);
2974 PetscViewerSetType(viewer, viewerType);
2975 PetscViewerFileSetMode(viewer, FILE_MODE_WRITE);
2976 PetscViewerPushFormat(viewer, viewerFormat);
2977 PetscViewerFileSetName(viewer, filePath.c_str());
2980 VecView(vector, viewer);
2983 PetscViewerDestroy(&viewer);
2995 VecGetLocalSize(m_solution, &size);
2997 const PetscScalar *vectorData;
2998 VecGetArrayRead(m_solution, &vectorData);
2999 for (
int i = 0; i < size; ++i) {
3000 (*data)[i] = vectorData[i];
3002 VecRestoreArrayRead(vector, &vectorData);
3014 *vector = PETSC_NULLPTR;
3051 std::string path = directory +
"/" + name;
3061 MatNullSpace nullspace;
3062#if BITPIT_ENABLE_MPI==1
3063 MatNullSpaceCreate(m_communicator, PETSC_TRUE, 0, NULL, &nullspace);
3065 MatNullSpaceCreate(PETSC_COMM_SELF, PETSC_TRUE, 0, NULL, &nullspace);
3067 MatSetNullSpace(m_A, nullspace);
3068 MatNullSpaceDestroy(&nullspace);
3076 MatSetNullSpace(m_A, NULL);
3105 }
catch(
const std::bad_cast &exception) {
3112 PetscInt *rowReorderingStorage;
3113 PetscMalloc(nRows *
sizeof(PetscInt), &rowReorderingStorage);
3114 for (
long i = 0; i < nRows; ++i) {
3118#if BITPIT_ENABLE_MPI == 1
3119 ISCreateGeneral(m_communicator, nRows, rowReorderingStorage, PETSC_OWN_POINTER, &m_rowReordering);
3121 ISCreateGeneral(PETSC_COMM_SELF, nRows, rowReorderingStorage, PETSC_OWN_POINTER, &m_rowReordering);
3123 ISSetPermutation(m_rowReordering);
3126 PetscInt *colReorderingStorage;
3127 PetscMalloc(nCols *
sizeof(PetscInt), &colReorderingStorage);
3128 for (
long j = 0; j < nCols; ++j) {
3132#if BITPIT_ENABLE_MPI == 1
3133 ISCreateGeneral(m_communicator, nCols, colReorderingStorage, PETSC_OWN_POINTER, &m_colReordering);
3135 ISCreateGeneral(PETSC_COMM_SELF, nCols, colReorderingStorage, PETSC_OWN_POINTER, &m_colReordering);
3137 ISSetPermutation(m_colReordering);
3148 if (m_rowReordering) {
3149 ISDestroy(&m_rowReordering);
3152 if (m_colReordering) {
3153 ISDestroy(&m_colReordering);
3174 throw std::runtime_error(
"Unable to solve the system. The system is not yet assembled.");
3183 bool setupNeeded =
false;
3190 KSPSetOperators(m_KSP, m_A, m_A);
3199 KSPGetPC(m_KSP, &pc);
3200 PCSetFromOptions(pc);
3212 KSPSetFromOptions(m_KSP);
3242#if BITPIT_ENABLE_MPI==1
3243 KSPCreate(m_communicator, &m_KSP);
3245 KSPCreate(PETSC_COMM_SELF, &m_KSP);
3249 if (!m_prefix.empty()) {
3250 KSPSetOptionsPrefix(m_KSP, m_prefix.c_str());
3261 m_KSP = PETSC_NULLPTR;
3270 KSPGetPC(m_KSP, &pc);
3284#if BITPIT_ENABLE_MPI == 1
3294 PCSetType(pc, pcType);
3297 if (strcmp(pcType, PCASM) == 0) {
3298 if (options.overlap != PETSC_DEFAULT) {
3299 PCASMSetOverlap(pc, options.overlap);
3301 }
else if (strcmp(pcType, PCILU) == 0) {
3302 if (options.
levels != PETSC_DEFAULT) {
3303 PCFactorSetLevels(pc, options.
levels);
3309 if (strcmp(pcType, PCASM) == 0) {
3312 PCASMGetSubKSP(pc, &nSubKSPs, PETSC_NULLPTR, &subKSPs);
3314 for (PetscInt i = 0; i < nSubKSPs; ++i) {
3315 KSP subKSP = subKSPs[i];
3316 KSPSetType(subKSP, KSPPREONLY);
3319 KSPGetPC(subKSP, &subPC);
3320 PCSetType(subPC, PCILU);
3321 if (options.
sublevels != PETSC_DEFAULT) {
3322 log::warning() <<
" Setting ASM ILU levels using the member \"sublevels\" is deprecated."
3323 <<
" ASM ILU levels should be set using the member \"levels\"." << std::endl;
3325 PCFactorSetLevels(subPC, options.
sublevels);
3326 }
else if (options.
levels != PETSC_DEFAULT) {
3327 PCFactorSetLevels(subPC, options.
levels);
3330 if (options.
subrtol != PETSC_DEFAULT) {
3331 log::warning() <<
" The member \"subrtol\" is deprecated. Since ASM is only use a a preconditioner"
3332 <<
" setting the tolerance of the Krylov subspace doens't have any effect on the"
3333 <<
" solution of the system."
3376 KSPSetType(ksp, KSPFGMRES);
3377 if (options.
restart != PETSC_DEFAULT) {
3378 KSPGMRESSetRestart(ksp, options.
restart);
3380 if (options.
rtol != PETSC_DEFAULT || options.
atol != PETSC_DEFAULT || options.
maxits != PETSC_DEFAULT) {
3381 KSPSetTolerances(ksp, options.
rtol, options.
atol, PETSC_DEFAULT, options.
maxits);
3392 if (m_convergenceMonitorEnabled) {
3393#if (PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 7)
3394 PetscOptionsSetValue(PETSC_NULLPTR, (
"-" + m_prefix +
"ksp_monitor_true_residual").c_str(),
"");
3395 PetscOptionsSetValue(PETSC_NULLPTR, (
"-" + m_prefix +
"ksp_monitor_singular_value").c_str(),
"");
3396 PetscOptionsSetValue(PETSC_NULLPTR, (
"-" + m_prefix +
"ksp_converged_reason").c_str(),
"");
3398 PetscOptionsSetValue((
"-" + m_prefix +
"ksp_monitor_true_residual").c_str(),
"");
3399 PetscOptionsSetValue((
"-" + m_prefix +
"ksp_monitor_singular_value").c_str(),
"");
3400 PetscOptionsSetValue((
"-" + m_prefix +
"ksp_converged_reason").c_str(),
"");
3422 throw std::runtime_error(
"The options associated with the Krylov solver can only be accessed after assembling the system.");
3425 return m_KSPOptions;
3438 throw std::runtime_error(
"The options associated with the Krylov solver can only be accessed after assembling the system.");
3441 return m_KSPOptions;
3480 throw std::runtime_error(
"The status of the Krylov solver can only be accessed after assembling the system.");
3511 KSPGetIterationNumber(ksp, &(status->its));
3512 KSPGetConvergedReason(ksp, &(status->convergence));
3532 status->convergence = KSP_CONVERGED_ITERATING;
3543#if BITPIT_ENABLE_MPI==1
3551 return m_communicator;
3560void SystemSolver::setCommunicator(MPI_Comm communicator)
3562 if ((communicator != MPI_COMM_NULL) && (communicator != MPI_COMM_SELF)) {
3563 MPI_Comm_dup(communicator, &m_communicator);
3565 m_communicator = MPI_COMM_SELF;
3572void SystemSolver::freeCommunicator()
3574 if (m_communicator != MPI_COMM_SELF) {
3575 int finalizedCalled;
3576 MPI_Finalized(&finalizedCalled);
3577 if (!finalizedCalled) {
3578 MPI_Comm_free(&m_communicator);
3590void SystemSolver::removeNullSpaceFromRHS()
3593 MatNullSpace nullspace;
3594 MatGetNullSpace(m_A, &nullspace);
3597 MatNullSpaceRemove(nullspace, m_rhs);
3608 return m_forceConsistency;
3619 m_forceConsistency = enable;
3634void SystemSolver::openBinaryArchive(
const std::string &directory,
const std::string &prefix,
3639 std::string path =
getFilePath(directory, prefix);
3640 archive->
open(path,
"dat", block);
3641 bool versionsMatch = archive->
checkVersion(expectedVersion);
3642 if (!versionsMatch) {
3643 std::string message =
"Version stored in binary archive " + path +
" does not match";
3644 message +=
" the expected version " + std::to_string(expectedVersion) +
".";
3646 throw std::runtime_error(message);
3663void SystemSolver::openBinaryArchive(
const std::string &header,
const std::string &directory,
3664 const std::string &prefix,
int block, OBinaryArchive *archive)
const
3667 std::string path =
getFilePath(directory, prefix);
3668 archive->open(path,
"dat", version, header, block);
3676void SystemSolver::closeBinaryArchive(BinaryArchive *archive)
const
3686int SystemSolver::getBinaryArchiveBlock()
const
3688#if BITPIT_ENABLE_MPI == 1
3692 if (nProcesses <= 1) {
3699 return archiveBlock;
bool checkVersion(int version)
void open(const std::string &name, int block=-1)
std::istream & getStream()
The NaturalSystemMatrixOrdering class defines allows to use a matrix natural ordering.
long getColPermutationRank(long col) const override
long getRowPermutationRank(long row) const override
std::ostream & getStream()
The PetscManager class handles the interaction with PETSc library.
bool initialize(bool debug)
bool areOptionsEditable() const
void addInitOptions(int argc, char **args)
void addInitOption(const std::string &option)
Metafunction for generating a list of elements that can be either stored in an external vectror or,...
__PXV_CONST_ITERATOR__ cend()
__PXV_POINTER__ data() noexcept
__PXV_CONST_ITERATOR__ cbegin()
void set(__PXV_POINTER__ data, std::size_t size)
const MPI_Comm & getCommunicator() const
long getColGlobalCount() const
ConstProxyVector< double > getRowValues(long row) const
long getColGlobalOffset() const
bool isPartitioned() const
long getMaxRowNZCount() const
long getRowGlobalCount() const
ConstProxyVector< long > getRowPattern(long row) const
long getRowNZCount(long row) const
long getRowGlobalOffset() const
The SystemMatrixAssembler class provides an interface for defining system matrix assemblers.
The SystemMatrixOrdering class provides an interface for defining classes that allows to reorder the ...
virtual long getColPermutationRank(long col) const =0
virtual long getRowPermutationRank(long row) const =0
The SystemSolver class provides methods for building and solving large linear systems.
void dumpMatrix(Mat matrix, const std::string &directory, const std::string &name) const
virtual void vectorsCreate()
void matrixUpdate(long nRows, const long *rows, const Assembler &assembler)
double * getSolutionRawPtr()
long getRowGlobalElementCount() const
bool isPartitioned() const
virtual int getDumpVersion() const
virtual void exportMatrix(const std::string &filePath, FileFormat exportFormat=FILE_BINARY) const
virtual void matrixFill(const std::string &filePath)
virtual void initializeKSPOptions()
virtual void prePreconditionerSetupActions()
void restoreSolutionRawPtr(double *raw_solution)
virtual void matrixRestore(std::istream &systemStream, const std::string &directory, const std::string &prefix, bool redistribute)
void fillMatrix(Mat matrix, const std::string &filePath) const
void restoreRHSRawReadPtr(const double *raw_rhs) const
void dumpVector(Vec vector, const std::string &directory, const std::string &name) const
virtual void postPreconditionerSetupActions()
virtual void importMatrix(const std::string &filePath)
virtual void initializeKSPStatus()
void reorderVector(Vec vector, IS permutations, bool invert) const
virtual void finalizeKSP()
std::string getInfoFilePath(const std::string &directory, const std::string &name) const
virtual void vectorsDump(std::ostream &systemStream, const std::string &directory, const std::string &prefix) const
virtual void resetKSPOptions(KSPOptions *options) const
void exportVector(Vec vector, const std::string &filePath, FileFormat fileFormat) const
void dumpSystem(const std::string &header, const std::string &directory, const std::string &prefix="") const
virtual void destroyKSPOptions()
virtual void clearWorkspace()
void setReordering(long nRows, long nCols, const SystemMatrixOrdering &reordering)
virtual void prepareKSP()
virtual void restoreInfo(std::istream &stream)
virtual void setNullSpace()
virtual void preKSPSolveActions()
virtual void setupKrylov()
virtual void postKrylovSetupActions()
long getColGlobalCount() const
void restoreSystem(MPI_Comm communicator, bool redistribute, const std::string &directory, const std::string &prefix="")
const double * getSolutionRawReadPtr() const
bool getTranspose() const
virtual void exportRHS(const std::string &filePath, FileFormat exportFormat=FILE_BINARY) const
virtual int getBlockSize() const
void restoreRHSRawPtr(double *raw_rhs)
void setTranspose(bool transpose)
const KSPStatus & getKSPStatus() const
void restoreMatrix(const std::string &directory, const std::string &name, bool redistribute, Mat *matrix) const
void matrixAssembly(const Assembler &assembler)
void createVector(int blockSize, Vec *vector) const
void destroyMatrix(Mat *matrix) const
std::string getFilePath(const std::string &directory, const std::string &name) const
long getColElementCount() const
virtual void matrixDump(std::ostream &systemStream, const std::string &directory, const std::string &prefix) const
virtual void dumpInfo(std::ostream &stream) const
void assembly(const SparseMatrix &matrix)
virtual void destroyKSP()
virtual void postKSPSolveActions()
const MPI_Comm & getCommunicator() const
virtual void fillKSPStatus()
std::string getDataFilePath(const std::string &directory, const std::string &name) const
const double * getRHSRawReadPtr() const
virtual void preKrylovSetupActions()
virtual void importSolution(const std::string &filePath)
virtual void resetKSPStatus()
SystemSolver(bool debug=false)
virtual void importRHS(const std::string &filePath)
void destroyVector(Vec *vector) const
void createMatrix(int rowBlockSize, int colBlockSize, Mat *matrix) const
void fillVector(Vec vector, const std::string &filePath) const
virtual void matrixDestroy()
virtual void destroyKSPStatus()
virtual void vectorsFill(const std::vector< double > &rhs, const std::vector< double > &solution)
virtual void vectorsDestroy()
virtual void setupPreconditioner()
void enableForceConsistency(bool enable)
long getRowGlobalCount() const
void restoreSolutionRawReadPtr(const double *raw_solution) const
bool isForceConsistencyEnabled() const
KSPOptions & getKSPOptions()
long getRowElementCount() const
virtual void vectorsReorder(bool invert)
virtual void vectorsRestore(std::istream &systemStream, const std::string &directory, const std::string &prefix)
long getColGlobalElementCount() const
void restoreVector(const std::string &directory, const std::string &name, Mat matrix, VectorSide side, Vec *vector) const
virtual void exportSolution(const std::string &filePath, FileFormat exportFormat=FILE_BINARY) const
The SystemSparseMatrixAssembler class defines an assembler for building the system matrix form a spar...
long getColGlobalCount() const override
long getRowGlobalCount() const override
void getRowValues(long rowIndex, ConstProxyVector< double > *values) const override
const MPI_Comm & getCommunicator() const override
long getRowElementCount() const override
long getColGlobalElementCount() const override
long getMaxRowNZCount() const override
long getRowGlobalElementCount() const override
void getRowData(long rowIndex, ConstProxyVector< long > *pattern, ConstProxyVector< double > *values) const override
long getRowNZCount(long rowIndex) const override
long getRowGlobalOffset() const override
long getRowCount() const override
bool isPartitioned() const override
AssemblyOptions getOptions() const override
long getColGlobalOffset() const override
long getColGlobalElementOffset() const override
void getRowPattern(long rowIndex, ConstProxyVector< long > *pattern) const override
long getColCount() const override
long getRowGlobalElementOffset() const override
long getColElementCount() const override
int getBlockSize() const override
SystemSparseMatrixAssembler(const SparseMatrix *matrix)
void write(std::ostream &stream, const std::vector< bool > &container)
void read(std::istream &stream, std::vector< bool > &container)
#define BITPIT_UNUSED(variable)
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
Logger & warning(log::Visibility defaultVisibility)
PetscScalar subrtol
Deprecated, ASM ILU levels should be set using the "levels" member.
PetscInt levels
Overlap between a pair of subdomains for the partitioned preconditioner.
PetscInt restart
Tells the iterative solver that the initial guess is nonzero.
PetscInt maxits
Number of iterations at which the GMRES method restarts.
PetscScalar atol
Relative convergence tolerance, relative decrease in the preconditioned residual norm.
PetscInt sublevels
Absolute convergence tolerance, absolute size of the preconditioned residual norm.
PetscScalar rtol
Maximum number of iterations.
PetscBool initial_non_zero
Number of levels of fill used by the preconditioner.
bool full
Controls if the assembler is providing all the non-zero values of a row.