Actual source code: ex312.c

  1: static char help[] = "Tests MatDenseUpdateColumnLayout().\n\n";

  3: #include <petscmat.h>

  5: static PetscErrorCode SetLinearValues(Vec x)
  6: {
  7:   PetscInt rstart, rend;

  9:   PetscFunctionBeginUser;
 10:   PetscCall(VecGetOwnershipRange(x, &rstart, &rend));
 11:   for (PetscInt i = rstart; i < rend; i++) PetscCall(VecSetValue(x, i, (PetscScalar)(i + 1), INSERT_VALUES));
 12:   PetscCall(VecAssemblyBegin(x));
 13:   PetscCall(VecAssemblyEnd(x));
 14:   PetscFunctionReturn(PETSC_SUCCESS);
 15: }

 17: int main(int argc, char **args)
 18: {
 19:   Mat         A, S;
 20:   Vec         x, y, yref;
 21:   PetscLayout clayout, cmap, scmap;
 22:   PetscReal   norm;
 23:   PetscInt    M, N, nloc, rstart, rend, cstart, cend, xstart, xend;
 24:   PetscBool   same;
 25:   PetscMPIInt rank, size;

 27:   PetscFunctionBeginUser;
 28:   PetscCall(PetscInitialize(&argc, &args, NULL, help));
 29:   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
 30:   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
 31:   M    = 2 * size + 1;
 32:   N    = size * (size + 1) / 2;
 33:   nloc = rank + 1;

 35:   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
 36:   PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, M, N));
 37:   PetscCall(MatSetType(A, MATDENSE));
 38:   PetscCall(MatSetFromOptions(A));
 39:   PetscCall(MatSetUp(A));
 40:   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
 41:   for (PetscInt i = rstart; i < rend; i++) {
 42:     for (PetscInt j = 0; j < N; j++) PetscCall(MatSetValue(A, i, j, (PetscScalar)(1 + i + 2 * j), INSERT_VALUES));
 43:   }
 44:   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
 45:   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));

 47:   /* Cache a full-column submatrix using the original column layout. */
 48:   PetscCall(MatDenseGetSubMatrix(A, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, &S));
 49:   PetscCall(MatDenseRestoreSubMatrix(A, &S));

 51:   /* Build the MPI dense matrix-vector scatter for the original column layout. */
 52:   PetscCall(MatCreateVecs(A, &x, &y));
 53:   PetscCall(SetLinearValues(x));
 54:   PetscCall(MatMult(A, x, y));
 55:   PetscCall(VecDuplicate(y, &yref));
 56:   PetscCall(VecCopy(y, yref));
 57:   PetscCall(VecDestroy(&x));

 59:   PetscCall(PetscLayoutCreateFromSizes(PETSC_COMM_WORLD, nloc, N, 1, &clayout));
 60:   PetscCall(PetscLayoutGetRange(clayout, &cstart, &cend));
 61:   PetscCall(MatDenseUpdateColumnLayout(A, clayout));
 62:   PetscCall(MatGetLayouts(A, NULL, &cmap));
 63:   PetscCheck(cmap == clayout, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Matrix did not adopt the new column layout");
 64:   PetscCall(PetscLayoutDestroy(&clayout));

 66:   PetscCall(MatCreateVecs(A, &x, NULL));
 67:   PetscCall(VecGetOwnershipRange(x, &xstart, &xend));
 68:   PetscCheck(xstart == cstart && xend == cend, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Right vector ownership range [%" PetscInt_FMT ",%" PetscInt_FMT ") does not match the new column layout [%" PetscInt_FMT ",%" PetscInt_FMT ")", xstart, xend, cstart, cend);
 69:   PetscCall(SetLinearValues(x));

 71:   PetscCall(MatDenseGetSubMatrix(A, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, &S));
 72:   PetscCall(MatGetLayouts(S, NULL, &scmap));
 73:   PetscCall(PetscLayoutCompare(scmap, cmap, &same));
 74:   PetscCheck(same, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Submatrix did not adopt the new column layout");
 75:   PetscCall(MatMult(S, x, y));
 76:   PetscCall(MatDenseRestoreSubMatrix(A, &S));
 77:   PetscCall(VecAXPY(y, -1.0, yref));
 78:   PetscCall(VecNorm(y, NORM_INFINITY, &norm));
 79:   PetscCheck(norm <= 100.0 * PETSC_MACHINE_EPSILON, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Submatrix MatMult() changed after updating the column layout, error %g", (double)norm);

 81:   PetscCall(MatMult(A, x, y));
 82:   PetscCall(VecAXPY(y, -1.0, yref));
 83:   PetscCall(VecNorm(y, NORM_INFINITY, &norm));
 84:   PetscCheck(norm <= 100.0 * PETSC_MACHINE_EPSILON, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "MatMult() changed after updating the column layout, error %g", (double)norm);

 86:   PetscCall(VecDestroy(&x));
 87:   PetscCall(VecDestroy(&y));
 88:   PetscCall(VecDestroy(&yref));
 89:   PetscCall(MatDestroy(&A));
 90:   PetscCall(PetscFinalize());
 91:   return 0;
 92: }

 94: /*TEST

 96:   testset:
 97:     nsize: {{1 2}}
 98:     output_file: output/empty.out

100:     test:
101:       suffix: cpu

103:     test:
104:       requires: cuda
105:       suffix: cuda
106:       args: -mat_type densecuda

108:     test:
109:       requires: hip
110:       suffix: hip
111:       args: -mat_type densehip

113: TEST*/