820 const PetscInt *rowReordering = PETSC_NULLPTR;
821 if (m_rowReordering) {
822 ISGetIndices(m_rowReordering, &rowReordering);
826 long nRows = assembler.getRowCount();
831 const std::vector<int> &splitBlockSizes = assembler.
getSplitSizes();
832 int nSplits = splitBlockSizes.size();
835 m_splitAs.assign(nSplits * nSplits, PETSC_NULLPTR);
836 for (
int splitRow = 0; splitRow < nSplits; ++splitRow) {
837 for (
int splitCol = 0; splitCol < nSplits; ++splitCol) {
843 if (m_splitStrategy == SystemSplitStrategy::SYSTEM_SPLIT_STRATEGY_LOWER) {
844 if (splitCol > splitRow) {
847 }
else if (m_splitStrategy == SystemSplitStrategy::SYSTEM_SPLIT_STRATEGY_DIAGONAL) {
848 if (splitCol != splitRow) {
853 int splitIndex = getBlockSplitLinearIndex(splitRow, splitCol, nSplits);
854 Mat *splitMatrix = m_splitAs.data() + splitIndex;
855 createMatrix(splitBlockSizes[splitRow], splitBlockSizes[splitCol], splitMatrix);
857 MatType splitMatrixType;
858 MatGetType(*splitMatrix, &splitMatrixType);
861 long nSplitRowsElements = assembler.getRowCount() * splitBlockSizes[splitRow];
862 long nSplitColsElements = assembler.getColCount() * splitBlockSizes[splitCol];
864 long nGlobalSplitRowsElements;
865 long nGlobalSplitColsElements;
866#if BITPIT_ENABLE_MPI == 1
867 nGlobalSplitRowsElements = assembler.getRowGlobalCount() * splitBlockSizes[splitRow];
868 nGlobalSplitColsElements = assembler.getColGlobalCount() * splitBlockSizes[splitCol];
870 nGlobalSplitRowsElements = nSplitRowsElements;
871 nGlobalSplitColsElements = nSplitColsElements;
874 MatSetSizes(*splitMatrix, nSplitRowsElements, nSplitColsElements, nGlobalSplitRowsElements, nGlobalSplitColsElements);
881 int rowAllocationExpansion;
882 int colAllocationExpansion;
883 if (strcmp(splitMatrixType, MATSEQAIJ) == 0) {
884 rowAllocationExpansion = splitBlockSizes[splitRow];
885 colAllocationExpansion = splitBlockSizes[splitCol];
886#if BITPIT_ENABLE_MPI == 1
887 }
else if (strcmp(splitMatrixType, MATMPIAIJ) == 0) {
888 rowAllocationExpansion = splitBlockSizes[splitRow];
889 colAllocationExpansion = splitBlockSizes[splitCol];
892 rowAllocationExpansion = 1;
893 colAllocationExpansion = 1;
896 long nAllocatedRowElements = rowAllocationExpansion * nRows;
898 std::vector<int> d_nnz(nAllocatedRowElements, 0);
899 for (
long n = 0; n < nRows; ++n) {
902 matrixRow = rowReordering[matrixRow];
905 int nAssemblerRowNZ = assembler.getRowNZCount(n);
907 long matrixRowOffset = matrixRow * rowAllocationExpansion;
908 for (
int n = 0; n < rowAllocationExpansion; ++n) {
909 d_nnz[matrixRowOffset + n] = colAllocationExpansion * nAssemblerRowNZ;
913#if BITPIT_ENABLE_MPI == 1
914 std::vector<int> o_nnz(nAllocatedRowElements, 0);
916 long nAssemblerCols = assembler.getColCount();
918 long assemblerDiagonalBegin = assembler.getColGlobalOffset();
919 long assemblerDiagonalEnd = assemblerDiagonalBegin + nAssemblerCols;
922 for (
long n = 0; n < nRows; ++n) {
925 matrixRow = rowReordering[matrixRow];
928 assembler.getRowPattern(n, &assemblerRowPattern);
929 int nAssemblerRowNZ = assemblerRowPattern.
size();
931 long matrixRowOffset = matrixRow * rowAllocationExpansion;
932 for (
int k = 0; k < nAssemblerRowNZ; ++k) {
933 long id = assemblerRowPattern[k];
934 if (id < assemblerDiagonalBegin || id >= assemblerDiagonalEnd) {
935 for (
int n = 0; n < rowAllocationExpansion; ++n) {
936 o_nnz[matrixRowOffset + n] += colAllocationExpansion;
937 d_nnz[matrixRowOffset + n] -= colAllocationExpansion;
945 if (strcmp(splitMatrixType, MATSEQAIJ) == 0) {
946 MatSeqAIJSetPreallocation(*splitMatrix, 0, d_nnz.data());
947 }
else if (strcmp(splitMatrixType, MATSEQBAIJ) == 0) {
948 MatSeqBAIJSetPreallocation(*splitMatrix, splitBlockSizes[splitRow], 0, d_nnz.data());
949#if BITPIT_ENABLE_MPI == 1
950 }
else if (strcmp(splitMatrixType, MATMPIAIJ) == 0) {
951 MatMPIAIJSetPreallocation(*splitMatrix, 0, d_nnz.data(), 0, o_nnz.data());
952 }
else if (strcmp(splitMatrixType, MATMPIBAIJ) == 0) {
953 MatMPIBAIJSetPreallocation(*splitMatrix, splitBlockSizes[splitRow], 0, d_nnz.data(), 0, o_nnz.data());
956 throw std::runtime_error(
"Matrix format not supported.");
960 MatSetOption(*splitMatrix, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE);
962#if PETSC_VERSION_GE(3, 12, 0)
966 MatSetOption(*splitMatrix, MAT_SUBSET_OFF_PROC_ENTRIES, PETSC_TRUE);
972 createMatrix(1, 1, nSplits, nSplits, m_splitAs.data(), &m_A);
975 if (m_rowReordering) {
976 ISRestoreIndices(m_rowReordering, &rowReordering);
980 matrixUpdate(assembler.getRowCount(),
nullptr, assembler);
986 for (Mat splitMatrix : m_splitAs) {
991 MatSetOption(splitMatrix, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
993 MatSetOption(m_A, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
1047 int nSplits = splitBlockSizes.size();
1052 std::vector<int> blockSplitRows(blockSize);
1053 for (
int i = 0; i < nSplits; ++i) {
1054 for (
int k = 0; k < splitBlockSizes[i]; ++k) {
1055 blockSplitRows[splitBlockOffsets[i] + k] = i;
1060 int assemblerBlockSize = assembler.getBlockSize();
1061 if (assemblerBlockSize != blockSize) {
1062 std::string message =
"Unable to update the matrix.";
1063 message +=
" The block size of the assembler is not equal to the block size of the system matrix.";
1064 throw std::runtime_error(message);
1067 const long assemblerMaxRowNZ = assembler.getMaxRowNZCount();
1069 PetscInt colGlobalBegin;
1070 PetscInt colGlobalEnd;
1071 MatGetOwnershipRangeColumn(m_A, &colGlobalBegin, &colGlobalEnd);
1072 colGlobalBegin /= assemblerBlockSize;
1073 colGlobalEnd /= assemblerBlockSize;
1075 PetscInt rowGlobalOffset;
1076 MatGetOwnershipRange(m_A, &rowGlobalOffset, PETSC_NULLPTR);
1077 rowGlobalOffset /= assemblerBlockSize;
1080 const PetscInt *rowReordering = PETSC_NULLPTR;
1081 if (m_rowReordering) {
1082 ISGetIndices(m_rowReordering, &rowReordering);
1085 const PetscInt *colReordering = PETSC_NULLPTR;
1086 if (m_colReordering) {
1087 ISGetIndices(m_colReordering, &colReordering);
1091 std::vector<std::vector<std::size_t>> scatterIndexes(nSplits);
1092 for (
int split = 0; split < nSplits; ++split) {
1099#if PETSC_VERSION_GE(3, 12, 0)
1109 PetscBool matrixSortedFull = (assemblyOptions.
full && assemblyOptions.sorted) ? PETSC_TRUE : PETSC_FALSE;
1110 MatSetOption(m_A, MAT_SORTED_FULL, matrixSortedFull);
1118 bool patternDirectUpdate = !colReordering && (
sizeof(long) ==
sizeof(PetscInt));
1121 std::vector<PetscInt> petscRowPatternStorage;
1122 const PetscInt *petscRowPattern;
1123 if (!patternDirectUpdate) {
1125 petscRowPatternStorage.resize(assemblerMaxRowNZ);
1126 petscRowPattern = petscRowPatternStorage.data();
1130 std::vector<std::vector<PetscScalar>> petscSplitRowValues(m_splitAs.size());
1131 for (PetscInt splitRow = 0; splitRow < nSplits; ++splitRow) {
1132 for (PetscInt splitCol = 0; splitCol < nSplits; ++splitCol) {
1133 int splitIndex = getBlockSplitLinearIndex(splitRow, splitCol, nSplits);
1134 if (!m_splitAs[splitIndex]) {
1138 int splitMatriBlockSize = splitBlockSizes[splitRow] * splitBlockSizes[splitCol];
1139 petscSplitRowValues[splitIndex].resize(splitMatriBlockSize * assemblerMaxRowNZ);
1143 for (
long n = 0; n < nRows; ++n) {
1152 if (rowReordering) {
1153 row = rowReordering[row];
1156 const PetscInt globalRow = rowGlobalOffset + row;
1159 assembler.getRowData(n, &rowPattern, &rowValues);
1160 if (rowValues.
size() == 0) {
1165 const std::size_t rowPatternSize = rowPattern.size();
1166 if (patternDirectUpdate) {
1167 petscRowPattern =
reinterpret_cast<const PetscInt *
>(rowPattern.data());
1169 for (std::size_t k = 0; k < rowPatternSize; ++k) {
1170 long globalCol = rowPattern[k];
1171 if (colReordering) {
1172 if (globalCol >= colGlobalBegin && globalCol < colGlobalEnd) {
1173 long col = globalCol - colGlobalBegin;
1174 col = colReordering[col];
1175 globalCol = colGlobalBegin + col;
1179 petscRowPatternStorage[k] = globalCol;
1188 for (
int blockRow = 0; blockRow < blockSize; ++blockRow) {
1189 int splitRow = blockSplitRows[blockRow];
1190 int splitBlockRow = blockRow - splitBlockOffsets[splitRow];
1192 std::size_t nRowElements = blockSize * rowPatternSize;
1193 std::size_t blockRowValuesOffset = nRowElements * blockRow;
1194 const double *blockRowValues = rowValues.
data() + blockRowValuesOffset;
1196 for (
int splitCol = 0; splitCol < nSplits; ++splitCol) {
1197 int splitIndex = getBlockSplitLinearIndex(splitRow, splitCol, nSplits);
1198 if (!m_splitAs[splitIndex]) {
1202 const std::vector<std::size_t> &splitScatterIndexes = scatterIndexes[splitCol];
1203 std::size_t nSplitRowElements = splitBlockSizes[splitCol] * rowPatternSize;
1204 std::size_t splitBlockRowValuesOffset = nSplitRowElements * splitBlockRow;
1205 double *splitBlockRowValues = petscSplitRowValues[splitIndex].data() + splitBlockRowValuesOffset;
1206 for (std::size_t k = 0; k < nSplitRowElements; ++k) {
1207 splitBlockRowValues[k] = blockRowValues[splitScatterIndexes[k]];
1213 for (std::size_t k = 0; k < m_splitAs.size(); ++k) {
1214 if (!m_splitAs[k]) {
1218 MatSetValuesBlocked(m_splitAs[k], 1, &globalRow, rowPatternSize, petscRowPattern,
1219 petscSplitRowValues[k].data(), INSERT_VALUES);
1224 for (Mat splitMatrix : m_splitAs) {
1229 MatAssemblyBegin(splitMatrix, MAT_FINAL_ASSEMBLY);
1232 for (Mat splitMatrix : m_splitAs) {
1237 MatAssemblyEnd(splitMatrix, MAT_FINAL_ASSEMBLY);
1240 MatAssemblyBegin(m_A, MAT_FINAL_ASSEMBLY);
1241 MatAssemblyEnd(m_A, MAT_FINAL_ASSEMBLY);
1244 if (rowReordering) {
1245 ISRestoreIndices(m_rowReordering, &rowReordering);
1248 if (colReordering) {
1249 ISRestoreIndices(m_colReordering, &colReordering);
1301 const std::string &prefix,
bool redistribute)
1304 const std::string &prefix)
1311 m_splitAs.assign(nSplits * nSplits, PETSC_NULLPTR);
1312 for (PetscInt splitRow = 0; splitRow < nSplits; ++splitRow) {
1313 for (PetscInt splitCol = 0; splitCol < nSplits; ++splitCol) {
1314 int splitIndex = getBlockSplitLinearIndex(splitRow, splitCol, nSplits);
1315 std::string splitMatrixName = generateSplitPath(prefix +
"A", splitRow, splitCol);
1316#if BITPIT_ENABLE_MPI==1
1317 restoreMatrix(directory, splitMatrixName, redistribute, m_splitAs.data() + splitIndex);
1319 restoreMatrix(directory, splitMatrixName, m_splitAs.data() + splitIndex);
1330 createMatrix(rowBlockSize, colBlockSize, nSplits, nSplits, m_splitAs.data(), &m_A);
1402#if BITPIT_ENABLE_MPI == 1
1403 PetscInt rhsGlobalBegin;
1404 PetscInt rhsGlobalEnd;
1405 VecGetOwnershipRange(m_rhs, &rhsGlobalBegin, &rhsGlobalEnd);
1406 rhsGlobalBegin /= blockSize;
1407 rhsGlobalEnd /= blockSize;
1408 PetscInt rhsSize = rhsGlobalEnd - rhsGlobalBegin;
1410 PetscInt solutionGlobalBegin;
1411 PetscInt solutionGlobalEnd;
1412 VecGetOwnershipRange(m_solution, &solutionGlobalBegin, &solutionGlobalEnd);
1413 solutionGlobalBegin /= blockSize;
1414 solutionGlobalEnd /= blockSize;
1415 PetscInt solutionSize = solutionGlobalEnd - solutionGlobalBegin;
1421 VecGetSize(m_rhs, &rhsSize);
1422 rhsSize /= blockSize;
1424 PetscInt solutionSize;
1425 VecGetSize(m_solution, &solutionSize);
1426 solutionSize /= blockSize;
1625 std::vector<std::size_t> workspace;
1628 std::vector<int> splitBlockSizes = getSplitSizes();
1629 std::vector<int> splitBlockOffsets = getSplitOffsets();
1630 int nSplits = splitBlockSizes.size();
1633 int blockSize = getBlockSize();
1634 std::size_t nElements = blockSize * nItems;
1637 PetscInt elementsGlobalOffset;
1638#if BITPIT_ENABLE_MPI == 1
1639 elementsGlobalOffset =
static_cast<PetscInt
>(blockSize * itemsGlobalOffset);
1641 elementsGlobalOffset = 0;
1644 PetscInt *permutationStorage;
1645 PetscMalloc(nElements *
sizeof(PetscInt), &permutationStorage);
1647 PetscInt *splitPermutationStorage = permutationStorage;
1648 for (
int split = 0; split < nSplits; ++split) {
1649 int splitBlockSize = splitBlockSizes[split];
1650 std::size_t nSplitElements = splitBlockSize * nItems;
1652 workspace.resize(nSplitElements);
1653 generateSplitIndexes(split, nItems, &workspace);
1654 for (std::size_t k = 0; k < nSplitElements; ++k) {
1655 splitPermutationStorage[k] = elementsGlobalOffset +
static_cast<PetscInt
>(workspace[k]);
1658 splitPermutationStorage += nSplitElements;
1661#if BITPIT_ENABLE_MPI == 1
1662 ISCreateGeneral(getCommunicator(), nItems, permutationStorage, PETSC_OWN_POINTER, permutation);
1664 ISCreateGeneral(PETSC_COMM_SELF, nItems, permutationStorage, PETSC_OWN_POINTER, permutation);
1666 ISSetPermutation(*permutation);