1 #include <petscmat.h> 2 3 static char help[] = "Tests MatMat operations with MAT_REUSE_MATRIX and already allocated dense result.\n\n"; 4 5 static PetscScalar MAGIC_NUMBER = 12345; 6 7 static PetscErrorCode CheckLocal(Mat A, Mat B, PetscScalar *a, PetscScalar *b) 8 { 9 PetscBool wA = PETSC_FALSE, wB = PETSC_FALSE; 10 PetscBool wAv = PETSC_FALSE, wBv = PETSC_FALSE; 11 PetscInt lda, i, j, m, n; 12 13 PetscFunctionBegin; 14 if (a) { 15 const PetscScalar *Aa; 16 PetscCall(MatDenseGetArrayRead(A, &Aa)); 17 wA = (PetscBool)(a != Aa); 18 PetscCall(MatDenseGetLDA(A, &lda)); 19 PetscCall(MatGetLocalSize(A, &m, &n)); 20 for (j = 0; j < n; j++) { 21 for (i = m; i < lda; i++) { 22 if (Aa[j * lda + i] != MAGIC_NUMBER) wAv = PETSC_TRUE; 23 } 24 } 25 PetscCall(MatDenseRestoreArrayRead(A, &Aa)); 26 } 27 if (b) { 28 const PetscScalar *Bb; 29 PetscCall(MatDenseGetArrayRead(B, &Bb)); 30 wB = (PetscBool)(b != Bb); 31 PetscCall(MatDenseGetLDA(B, &lda)); 32 PetscCall(MatGetLocalSize(B, &m, &n)); 33 for (j = 0; j < n; j++) { 34 for (i = m; i < lda; i++) { 35 if (Bb[j * lda + i] != MAGIC_NUMBER) wBv = PETSC_TRUE; 36 } 37 } 38 PetscCall(MatDenseRestoreArrayRead(B, &Bb)); 39 } 40 PetscCheck(!wA && !wB, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong array in first Mat? %d, Wrong array in second Mat? %d", wA, wB); 41 PetscCheck(!wAv && !wBv, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong data in first Mat? %d, Wrong data in second Mat? %d", wAv, wBv); 42 PetscFunctionReturn(PETSC_SUCCESS); 43 } 44 45 typedef struct { 46 Mat A; 47 Mat P; 48 Mat R; 49 } proj_data; 50 51 PetscErrorCode proj_destroy(void *ctx) 52 { 53 proj_data *userdata = (proj_data *)ctx; 54 55 PetscFunctionBegin; 56 PetscCheck(userdata, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing userdata"); 57 PetscCall(MatDestroy(&userdata->A)); 58 PetscCall(MatDestroy(&userdata->P)); 59 PetscCall(MatDestroy(&userdata->R)); 60 PetscCall(PetscFree(userdata)); 61 PetscFunctionReturn(PETSC_SUCCESS); 62 } 63 64 PetscErrorCode proj_mult(Mat S, Vec X, Vec Y) 65 { 66 Mat A, R, P; 67 Vec Ax, Ay; 68 Vec Px, Py; 69 proj_data *userdata; 70 71 PetscFunctionBegin; 72 PetscCall(MatShellGetContext(S, &userdata)); 73 PetscCheck(userdata, PetscObjectComm((PetscObject)S), PETSC_ERR_PLIB, "Missing userdata"); 74 A = userdata->A; 75 R = userdata->R; 76 P = userdata->P; 77 PetscCheck(A, PetscObjectComm((PetscObject)S), PETSC_ERR_PLIB, "Missing matrix"); 78 PetscCheck(R || P, PetscObjectComm((PetscObject)S), PETSC_ERR_PLIB, "Missing projectors"); 79 PetscCheck(!R || !P, PetscObjectComm((PetscObject)S), PETSC_ERR_PLIB, "Both projectors"); 80 PetscCall(MatCreateVecs(A, &Ax, &Ay)); 81 if (R) { 82 PetscCall(MatCreateVecs(R, &Py, &Px)); 83 } else { 84 PetscCall(MatCreateVecs(P, &Px, &Py)); 85 } 86 PetscCall(VecCopy(X, Px)); 87 if (P) { 88 PetscCall(MatMult(P, Px, Py)); 89 } else { 90 PetscCall(MatMultTranspose(R, Px, Py)); 91 } 92 PetscCall(VecCopy(Py, Ax)); 93 PetscCall(MatMult(A, Ax, Ay)); 94 PetscCall(VecCopy(Ay, Py)); 95 if (P) { 96 PetscCall(MatMultTranspose(P, Py, Px)); 97 } else { 98 PetscCall(MatMult(R, Py, Px)); 99 } 100 PetscCall(VecCopy(Px, Y)); 101 PetscCall(VecDestroy(&Px)); 102 PetscCall(VecDestroy(&Py)); 103 PetscCall(VecDestroy(&Ax)); 104 PetscCall(VecDestroy(&Ay)); 105 PetscFunctionReturn(PETSC_SUCCESS); 106 } 107 108 PetscErrorCode MyPtShellPMultSymbolic(Mat S, Mat P, Mat PtAP, void **ctx) 109 { 110 proj_data *userdata; 111 112 PetscFunctionBegin; 113 PetscCall(PetscNew(&userdata)); 114 PetscCall(MatShellSetContext(PtAP, userdata)); 115 *ctx = (void *)userdata; 116 PetscFunctionReturn(PETSC_SUCCESS); 117 } 118 119 PetscErrorCode MyPtShellPMultNumeric(Mat S, Mat P, Mat PtAP, void *ctx) 120 { 121 Mat A; 122 proj_data *userdata = (proj_data *)ctx; 123 124 PetscFunctionBegin; 125 PetscCall(MatShellGetContext(S, &A)); 126 PetscCall(PetscObjectReference((PetscObject)A)); 127 PetscCall(PetscObjectReference((PetscObject)P)); 128 PetscCall(MatDestroy(&userdata->A)); 129 PetscCall(MatDestroy(&userdata->P)); 130 PetscCall(MatDestroy(&userdata->R)); 131 userdata->A = A; 132 userdata->P = P; 133 PetscCall(MatShellSetOperation(PtAP, MATOP_MULT, (void (*)(void))proj_mult)); 134 PetscCall(MatSetUp(PtAP)); 135 PetscCall(MatAssemblyBegin(PtAP, MAT_FINAL_ASSEMBLY)); 136 PetscCall(MatAssemblyEnd(PtAP, MAT_FINAL_ASSEMBLY)); 137 PetscFunctionReturn(PETSC_SUCCESS); 138 } 139 140 PetscErrorCode MyRShellRtMultSymbolic(Mat S, Mat R, Mat RARt, void **ctx) 141 { 142 proj_data *userdata; 143 144 PetscFunctionBegin; 145 PetscCall(PetscNew(&userdata)); 146 PetscCall(MatShellSetContext(RARt, userdata)); 147 *ctx = (void *)userdata; 148 PetscFunctionReturn(PETSC_SUCCESS); 149 } 150 151 PetscErrorCode MyRShellRtMultNumeric(Mat S, Mat R, Mat RARt, void *ctx) 152 { 153 Mat A; 154 proj_data *userdata = (proj_data *)ctx; 155 156 PetscFunctionBegin; 157 PetscCall(MatShellGetContext(S, &A)); 158 PetscCall(PetscObjectReference((PetscObject)A)); 159 PetscCall(PetscObjectReference((PetscObject)R)); 160 PetscCall(MatDestroy(&userdata->A)); 161 PetscCall(MatDestroy(&userdata->P)); 162 PetscCall(MatDestroy(&userdata->R)); 163 userdata->A = A; 164 userdata->R = R; 165 PetscCall(MatShellSetOperation(RARt, MATOP_MULT, (void (*)(void))proj_mult)); 166 PetscCall(MatSetUp(RARt)); 167 PetscCall(MatAssemblyBegin(RARt, MAT_FINAL_ASSEMBLY)); 168 PetscCall(MatAssemblyEnd(RARt, MAT_FINAL_ASSEMBLY)); 169 PetscFunctionReturn(PETSC_SUCCESS); 170 } 171 172 PetscErrorCode MyMatShellMatMultNumeric(Mat S, Mat B, Mat C, void *ctx) 173 { 174 Mat A; 175 176 PetscFunctionBegin; 177 PetscCall(MatShellGetContext(S, &A)); 178 PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C)); 179 PetscFunctionReturn(PETSC_SUCCESS); 180 } 181 182 PetscErrorCode MyMatTransposeShellMatMultNumeric(Mat S, Mat B, Mat C, void *ctx) 183 { 184 Mat A; 185 186 PetscFunctionBegin; 187 PetscCall(MatShellGetContext(S, &A)); 188 PetscCall(MatTransposeMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C)); 189 PetscFunctionReturn(PETSC_SUCCESS); 190 } 191 192 PetscErrorCode MyMatShellMatTransposeMultNumeric(Mat S, Mat B, Mat C, void *ctx) 193 { 194 Mat A; 195 196 PetscFunctionBegin; 197 PetscCall(MatShellGetContext(S, &A)); 198 PetscCall(MatMatTransposeMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &C)); 199 PetscFunctionReturn(PETSC_SUCCESS); 200 } 201 202 int main(int argc, char **args) 203 { 204 Mat X, B, A, Bt, T, T2, PtAP = NULL, RARt = NULL, R = NULL; 205 Vec r, l, rs, ls; 206 PetscInt m, n, k, M = 10, N = 10, K = 5, ldx = 3, ldb = 5, ldr = 4; 207 const char *deft = MATAIJ; 208 char mattype[256]; 209 PetscBool flg, symm = PETSC_FALSE, testtt = PETSC_TRUE, testnest = PETSC_TRUE, testtranspose = PETSC_TRUE, testcircular = PETSC_FALSE, local = PETSC_TRUE; 210 PetscBool testhtranspose = PETSC_FALSE; /* Hermitian transpose is not handled correctly and generates an error */ 211 PetscBool xgpu = PETSC_FALSE, bgpu = PETSC_FALSE, testshellops = PETSC_FALSE, testproj = PETSC_TRUE, testrart = PETSC_TRUE, testmatmatt = PETSC_TRUE, testmattmat = PETSC_TRUE; 212 PetscScalar *dataX = NULL, *dataB = NULL, *dataR = NULL, *dataBt = NULL; 213 PetscScalar *aX, *aB, *aBt; 214 PetscReal err; 215 216 PetscFunctionBeginUser; 217 PetscCall(PetscInitialize(&argc, &args, NULL, help)); 218 PetscCall(PetscOptionsGetInt(NULL, NULL, "-N", &N, NULL)); 219 PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL)); 220 PetscCall(PetscOptionsGetInt(NULL, NULL, "-K", &K, NULL)); 221 PetscCall(PetscOptionsGetBool(NULL, NULL, "-symm", &symm, NULL)); 222 PetscCall(PetscOptionsGetBool(NULL, NULL, "-local", &local, NULL)); 223 PetscCall(PetscOptionsGetInt(NULL, NULL, "-ldx", &ldx, NULL)); 224 PetscCall(PetscOptionsGetInt(NULL, NULL, "-ldb", &ldb, NULL)); 225 PetscCall(PetscOptionsGetInt(NULL, NULL, "-ldr", &ldr, NULL)); 226 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testtranspose", &testtranspose, NULL)); 227 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testnest", &testnest, NULL)); 228 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testtt", &testtt, NULL)); 229 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testcircular", &testcircular, NULL)); 230 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testshellops", &testshellops, NULL)); 231 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testproj", &testproj, NULL)); 232 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testrart", &testrart, NULL)); 233 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testmatmatt", &testmatmatt, NULL)); 234 PetscCall(PetscOptionsGetBool(NULL, NULL, "-testmattmat", &testmattmat, NULL)); 235 PetscCall(PetscOptionsGetBool(NULL, NULL, "-xgpu", &xgpu, NULL)); 236 PetscCall(PetscOptionsGetBool(NULL, NULL, "-bgpu", &bgpu, NULL)); 237 PetscCall(PetscOptionsGetScalar(NULL, NULL, "-magic_number", &MAGIC_NUMBER, NULL)); 238 if (M != N) testproj = PETSC_FALSE; 239 240 PetscCall(MatCreate(PETSC_COMM_WORLD, &A)); 241 PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, M, N)); 242 PetscCall(MatSetType(A, MATAIJ)); 243 PetscCall(MatSeqAIJSetPreallocation(A, PETSC_DEFAULT, NULL)); 244 PetscCall(MatMPIAIJSetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 245 PetscCall(MatSetUp(A)); 246 PetscCall(MatSetRandom(A, NULL)); 247 if (M == N && symm) { 248 Mat AT; 249 250 PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT)); 251 PetscCall(MatAXPY(A, 1.0, AT, DIFFERENT_NONZERO_PATTERN)); 252 PetscCall(MatDestroy(&AT)); 253 PetscCall(MatSetOption(A, MAT_SYMMETRIC, PETSC_TRUE)); 254 } 255 PetscCall(MatViewFromOptions(A, NULL, "-A_init_view")); 256 PetscOptionsBegin(PETSC_COMM_WORLD, "", "", ""); 257 PetscCall(PetscOptionsFList("-A_mat_type", "Matrix type", "MatSetType", MatList, deft, mattype, 256, &flg)); 258 PetscOptionsEnd(); 259 if (flg) { 260 Mat A2; 261 262 PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &A2)); 263 PetscCall(MatConvert(A, mattype, MAT_INPLACE_MATRIX, &A)); 264 PetscCall(MatMultEqual(A, A2, 10, &flg)); 265 if (!flg) { 266 Mat AE, A2E; 267 268 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with convert\n")); 269 PetscCall(MatComputeOperator(A, MATDENSE, &AE)); 270 PetscCall(MatComputeOperator(A2, MATDENSE, &A2E)); 271 PetscCall(MatView(AE, NULL)); 272 PetscCall(MatView(A2E, NULL)); 273 PetscCall(MatAXPY(A2E, -1.0, A, SAME_NONZERO_PATTERN)); 274 PetscCall(MatView(A2E, NULL)); 275 PetscCall(MatDestroy(&A2E)); 276 PetscCall(MatDestroy(&AE)); 277 } 278 PetscCall(MatDestroy(&A2)); 279 } 280 PetscCall(MatViewFromOptions(A, NULL, "-A_view")); 281 282 PetscCall(MatGetLocalSize(A, &m, &n)); 283 if (local) { 284 PetscInt i; 285 286 PetscCall(PetscMalloc1((m + ldx) * K, &dataX)); 287 PetscCall(PetscMalloc1((n + ldb) * K, &dataB)); 288 for (i = 0; i < (m + ldx) * K; i++) dataX[i] = MAGIC_NUMBER; 289 for (i = 0; i < (n + ldb) * K; i++) dataB[i] = MAGIC_NUMBER; 290 } 291 PetscCall(MatCreateDense(PETSC_COMM_WORLD, n, PETSC_DECIDE, N, K, dataB, &B)); 292 PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, M, K, dataX, &X)); 293 if (local) { 294 PetscCall(MatDenseSetLDA(X, m + ldx)); 295 PetscCall(MatDenseSetLDA(B, n + ldb)); 296 } 297 PetscCall(MatGetLocalSize(B, NULL, &k)); 298 if (local) { 299 PetscInt i; 300 301 PetscCall(PetscMalloc1((k + ldr) * N, &dataBt)); 302 for (i = 0; i < (k + ldr) * N; i++) dataBt[i] = MAGIC_NUMBER; 303 } 304 PetscCall(MatCreateDense(PETSC_COMM_WORLD, k, n, K, N, dataBt, &Bt)); 305 if (local) PetscCall(MatDenseSetLDA(Bt, k + ldr)); 306 307 /* store pointer to dense data for testing */ 308 PetscCall(MatDenseGetArrayRead(B, (const PetscScalar **)&dataB)); 309 PetscCall(MatDenseGetArrayRead(X, (const PetscScalar **)&dataX)); 310 PetscCall(MatDenseGetArrayRead(Bt, (const PetscScalar **)&dataBt)); 311 aX = dataX; 312 aB = dataB; 313 aBt = dataBt; 314 PetscCall(MatDenseRestoreArrayRead(Bt, (const PetscScalar **)&dataBt)); 315 PetscCall(MatDenseRestoreArrayRead(B, (const PetscScalar **)&dataB)); 316 PetscCall(MatDenseRestoreArrayRead(X, (const PetscScalar **)&dataX)); 317 if (local) { 318 dataX = aX; 319 dataB = aB; 320 dataBt = aBt; 321 } 322 323 PetscCall(MatSetRandom(X, NULL)); 324 PetscCall(MatSetRandom(B, NULL)); 325 PetscCall(MatSetRandom(Bt, NULL)); 326 PetscCall(CheckLocal(X, NULL, aX, NULL)); 327 PetscCall(CheckLocal(Bt, B, aBt, aB)); 328 329 /* convert to CUDA if needed */ 330 if (bgpu) { 331 PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 332 PetscCall(MatConvert(Bt, MATDENSECUDA, MAT_INPLACE_MATRIX, &Bt)); 333 } 334 if (xgpu) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 335 PetscCall(CheckLocal(B, X, aB, aX)); 336 337 /* Test MatDenseGetSubMatrix */ 338 { 339 Mat B2, T3, T4; 340 341 PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2)); 342 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &T4)); 343 PetscCall(MatSetRandom(T4, NULL)); 344 PetscCall(MatAXPY(B2, 1.0, T4, SAME_NONZERO_PATTERN)); 345 PetscCall(MatDenseGetSubMatrix(B, PETSC_DECIDE, PETSC_DECIDE, PetscMin(1, K - 1), PetscMin(2, K), &T)); 346 PetscCall(MatDenseGetSubMatrix(T4, PETSC_DECIDE, PETSC_DECIDE, PetscMin(1, K - 1), PetscMin(2, K), &T2)); 347 PetscCall(MatDenseGetSubMatrix(B2, PETSC_DECIDE, PETSC_DECIDE, PetscMin(1, K - 1), PetscMin(2, K), &T3)); 348 PetscCall(MatAXPY(T, 1.0, T2, SAME_NONZERO_PATTERN)); 349 PetscCall(MatAXPY(T3, -1.0, T, SAME_NONZERO_PATTERN)); 350 PetscCall(MatNorm(T3, NORM_FROBENIUS, &err)); 351 if (err > PETSC_SMALL) { 352 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with MatDenseGetSubMatrix\n")); 353 PetscCall(MatView(T3, NULL)); 354 } 355 PetscCall(MatDenseRestoreSubMatrix(B, &T)); 356 PetscCall(MatDenseRestoreSubMatrix(T4, &T2)); 357 PetscCall(MatDenseRestoreSubMatrix(B2, &T3)); 358 PetscCall(CheckLocal(B, NULL, aB, NULL)); 359 PetscCall(MatDestroy(&B2)); 360 PetscCall(MatDestroy(&T4)); 361 if (N >= 2) { 362 PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2)); 363 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &T4)); 364 PetscCall(MatSetRandom(T4, NULL)); 365 PetscCall(MatAXPY(B2, 1.0, T4, SAME_NONZERO_PATTERN)); 366 PetscCall(MatDenseGetSubMatrix(B, N - 2, PETSC_DECIDE, PetscMin(1, K - 1), PetscMin(2, K), &T)); 367 PetscCall(MatDenseGetSubMatrix(T4, N - 2, PETSC_DECIDE, PetscMin(1, K - 1), PetscMin(2, K), &T2)); 368 PetscCall(MatDenseGetSubMatrix(B2, N - 2, PETSC_DECIDE, PetscMin(1, K - 1), PetscMin(2, K), &T3)); 369 PetscCall(MatAXPY(T, 1.0, T2, SAME_NONZERO_PATTERN)); 370 PetscCall(MatAXPY(T3, -1.0, T, SAME_NONZERO_PATTERN)); 371 PetscCall(MatNorm(T3, NORM_FROBENIUS, &err)); 372 if (err > PETSC_SMALL) { 373 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with MatDenseGetSubMatrix\n")); 374 PetscCall(MatView(T3, NULL)); 375 } 376 PetscCall(MatDenseRestoreSubMatrix(B, &T)); 377 PetscCall(MatDenseRestoreSubMatrix(T4, &T2)); 378 PetscCall(MatDenseRestoreSubMatrix(B2, &T3)); 379 PetscCall(CheckLocal(B, NULL, aB, NULL)); 380 PetscCall(MatDestroy(&B2)); 381 PetscCall(MatDestroy(&T4)); 382 PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &B2)); 383 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &T4)); 384 PetscCall(MatSetRandom(T4, NULL)); 385 PetscCall(MatAXPY(B2, 1.0, T4, SAME_NONZERO_PATTERN)); 386 PetscCall(MatDenseGetSubMatrix(B, PETSC_DECIDE, 2, PetscMin(1, K - 1), PetscMin(2, K), &T)); 387 PetscCall(MatDenseGetSubMatrix(T4, PETSC_DECIDE, 2, PetscMin(1, K - 1), PetscMin(2, K), &T2)); 388 PetscCall(MatDenseGetSubMatrix(B2, PETSC_DECIDE, 2, PetscMin(1, K - 1), PetscMin(2, K), &T3)); 389 PetscCall(MatAXPY(T, 1.0, T2, SAME_NONZERO_PATTERN)); 390 PetscCall(MatAXPY(T3, -1.0, T, SAME_NONZERO_PATTERN)); 391 PetscCall(MatNorm(T3, NORM_FROBENIUS, &err)); 392 if (err > PETSC_SMALL) { 393 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with MatDenseGetSubMatrix\n")); 394 PetscCall(MatView(T3, NULL)); 395 } 396 PetscCall(MatDenseRestoreSubMatrix(B, &T)); 397 PetscCall(MatDenseRestoreSubMatrix(T4, &T2)); 398 PetscCall(MatDenseRestoreSubMatrix(B2, &T3)); 399 PetscCall(CheckLocal(B, NULL, aB, NULL)); 400 PetscCall(MatDestroy(&B2)); 401 PetscCall(MatDestroy(&T4)); 402 } 403 } 404 405 /* Test reusing a previously allocated dense buffer */ 406 PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 407 PetscCall(CheckLocal(B, X, aB, aX)); 408 PetscCall(MatMatMultEqual(A, B, X, 10, &flg)); 409 if (!flg) { 410 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with reusage\n")); 411 PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 412 PetscCall(MatAXPY(T, -1.0, X, SAME_NONZERO_PATTERN)); 413 PetscCall(MatView(T, NULL)); 414 PetscCall(MatDestroy(&T)); 415 } 416 417 /* Test MatTransposeMat and MatMatTranspose */ 418 if (testmattmat) { 419 PetscCall(MatTransposeMatMult(A, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &B)); 420 PetscCall(CheckLocal(B, X, aB, aX)); 421 PetscCall(MatTransposeMatMultEqual(A, X, B, 10, &flg)); 422 if (!flg) { 423 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with reusage (MatTransposeMat)\n")); 424 PetscCall(MatTransposeMatMult(A, X, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &B)); 425 PetscCall(MatAXPY(T, -1.0, B, SAME_NONZERO_PATTERN)); 426 PetscCall(MatView(T, NULL)); 427 PetscCall(MatDestroy(&T)); 428 } 429 } 430 if (testmatmatt) { 431 PetscCall(MatMatTransposeMult(A, Bt, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 432 PetscCall(CheckLocal(Bt, X, aBt, aX)); 433 PetscCall(MatMatTransposeMultEqual(A, Bt, X, 10, &flg)); 434 if (!flg) { 435 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with reusage (MatMatTranspose)\n")); 436 PetscCall(MatMatTransposeMult(A, Bt, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 437 PetscCall(MatAXPY(T, -1.0, X, SAME_NONZERO_PATTERN)); 438 PetscCall(MatView(T, NULL)); 439 PetscCall(MatDestroy(&T)); 440 } 441 } 442 443 /* Test projection operations (PtAP and RARt) */ 444 if (testproj) { 445 PetscCall(MatPtAP(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &PtAP)); 446 PetscCall(MatPtAPMultEqual(A, B, PtAP, 10, &flg)); 447 if (!flg) { 448 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with PtAP\n")); 449 PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 450 PetscCall(MatTransposeMatMult(B, T, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T2)); 451 PetscCall(MatAXPY(T2, -1.0, PtAP, SAME_NONZERO_PATTERN)); 452 PetscCall(MatView(T2, NULL)); 453 PetscCall(MatDestroy(&T2)); 454 PetscCall(MatDestroy(&T)); 455 } 456 PetscCall(PetscMalloc1((k + ldr) * M, &dataR)); 457 PetscCall(MatCreateDense(PETSC_COMM_WORLD, PETSC_DECIDE, m, K, M, dataR, &R)); 458 PetscCall(MatDenseSetLDA(R, k + ldr)); 459 PetscCall(MatSetRandom(R, NULL)); 460 if (testrart) { /* fails for AIJCUSPARSE because RA operation is not defined */ 461 PetscCall(MatRARt(A, R, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &RARt)); 462 PetscCall(MatRARtMultEqual(A, R, RARt, 10, &flg)); 463 if (!flg) { 464 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with RARt\n")); 465 PetscCall(MatMatTransposeMult(A, R, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 466 PetscCall(MatMatMult(R, T, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T2)); 467 PetscCall(MatAXPY(T2, -1.0, RARt, SAME_NONZERO_PATTERN)); 468 PetscCall(MatView(T2, NULL)); 469 PetscCall(MatDestroy(&T2)); 470 PetscCall(MatDestroy(&T)); 471 } 472 } 473 } 474 475 /* Test MatDenseGetColumnVec and friends */ 476 PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 477 PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 478 PetscCall(MatDuplicate(T, MAT_DO_NOT_COPY_VALUES, &T2)); 479 for (k = 0; k < K; k++) { 480 Vec Xv, Tv, T2v; 481 482 PetscCall(MatDenseGetColumnVecRead(X, k, &Xv)); 483 PetscCall(MatDenseGetColumnVec(T, k, &Tv)); 484 PetscCall(MatDenseGetColumnVecWrite(T2, k, &T2v)); 485 PetscCall(VecCopy(Xv, T2v)); 486 PetscCall(VecAXPY(Tv, -1., Xv)); 487 PetscCall(MatDenseRestoreColumnVecRead(X, k, &Xv)); 488 PetscCall(MatDenseRestoreColumnVec(T, k, &Tv)); 489 PetscCall(MatDenseRestoreColumnVecWrite(T2, k, &T2v)); 490 } 491 PetscCall(MatNorm(T, NORM_FROBENIUS, &err)); 492 if (err > PETSC_SMALL) { 493 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with MatDenseGetColumnVec\n")); 494 PetscCall(MatView(T, NULL)); 495 } 496 PetscCall(MatAXPY(T2, -1., X, SAME_NONZERO_PATTERN)); 497 PetscCall(MatNorm(T2, NORM_FROBENIUS, &err)); 498 if (err > PETSC_SMALL) { 499 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with MatDenseGetColumnVecWrite\n")); 500 PetscCall(MatView(T2, NULL)); 501 } 502 PetscCall(MatDestroy(&T)); 503 PetscCall(MatDestroy(&T2)); 504 505 /* Test with MatShell */ 506 PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &T)); 507 PetscCall(MatConvert(T, MATSHELL, MAT_INITIAL_MATRIX, &T2)); 508 PetscCall(MatDestroy(&T)); 509 510 /* scale matrix */ 511 PetscCall(MatScale(A, 2.0)); 512 PetscCall(MatScale(T2, 2.0)); 513 PetscCall(MatCreateVecs(A, &r, &l)); 514 PetscCall(VecSetRandom(r, NULL)); 515 PetscCall(VecSetRandom(l, NULL)); 516 PetscCall(MatCreateVecs(T2, &rs, &ls)); 517 PetscCall(VecCopy(r, rs)); 518 PetscCall(VecCopy(l, ls)); 519 if (testproj) { 520 PetscCall(MatDiagonalScale(A, r, r)); 521 PetscCall(MatDiagonalScale(T2, rs, rs)); 522 } else { 523 PetscCall(MatDiagonalScale(A, l, r)); 524 PetscCall(MatDiagonalScale(T2, ls, rs)); 525 } 526 PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &T)); 527 PetscCall(MatAXPY(A, 4.5, T, SAME_NONZERO_PATTERN)); 528 PetscCall(MatAXPY(T2, 4.5, T, DIFFERENT_NONZERO_PATTERN)); 529 PetscCall(MatMultEqual(T2, A, 10, &flg)); 530 if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with MATSHELL (MatMult)\n")); 531 PetscCall(MatMultTransposeEqual(T2, A, 10, &flg)); 532 if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with MATSHELL (MatMultTranspose)\n")); 533 PetscCall(MatDestroy(&T)); 534 PetscCall(VecDestroy(&ls)); 535 PetscCall(VecDestroy(&rs)); 536 PetscCall(VecDestroy(&l)); 537 PetscCall(VecDestroy(&r)); 538 539 /* recompute projections, test reusage */ 540 if (PtAP) PetscCall(MatPtAP(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &PtAP)); 541 if (RARt) PetscCall(MatRARt(A, R, MAT_REUSE_MATRIX, PETSC_DEFAULT, &RARt)); 542 if (testshellops) { /* test callbacks for user defined MatProducts */ 543 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_AB, NULL, MyMatShellMatMultNumeric, NULL, MATDENSE, MATDENSE)); 544 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_AB, NULL, MyMatShellMatMultNumeric, NULL, MATDENSECUDA, MATDENSECUDA)); 545 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_AtB, NULL, MyMatTransposeShellMatMultNumeric, NULL, MATDENSE, MATDENSE)); 546 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_AtB, NULL, MyMatTransposeShellMatMultNumeric, NULL, MATDENSECUDA, MATDENSECUDA)); 547 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_ABt, NULL, MyMatShellMatTransposeMultNumeric, NULL, MATDENSE, MATDENSE)); 548 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_ABt, NULL, MyMatShellMatTransposeMultNumeric, NULL, MATDENSECUDA, MATDENSECUDA)); 549 if (testproj) { 550 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_PtAP, MyPtShellPMultSymbolic, MyPtShellPMultNumeric, proj_destroy, MATDENSE, MATSHELL)); 551 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_PtAP, MyPtShellPMultSymbolic, MyPtShellPMultNumeric, proj_destroy, MATDENSECUDA, MATSHELL)); 552 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_RARt, MyRShellRtMultSymbolic, MyRShellRtMultNumeric, proj_destroy, MATDENSE, MATSHELL)); 553 PetscCall(MatShellSetMatProductOperation(T2, MATPRODUCT_RARt, MyRShellRtMultSymbolic, MyRShellRtMultNumeric, proj_destroy, MATDENSECUDA, MATSHELL)); 554 } 555 } 556 PetscCall(CheckLocal(B, X, aB, aX)); 557 /* we either use the shell operations or the loop over columns code, applying the operator */ 558 PetscCall(MatMatMult(T2, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 559 PetscCall(CheckLocal(B, X, aB, aX)); 560 PetscCall(MatMatMultEqual(T2, B, X, 10, &flg)); 561 if (!flg) { 562 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with reusage (MATSHELL)\n")); 563 PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 564 PetscCall(MatAXPY(T, -1.0, X, SAME_NONZERO_PATTERN)); 565 PetscCall(MatView(T, NULL)); 566 PetscCall(MatDestroy(&T)); 567 } 568 if (testproj) { 569 PetscCall(MatPtAPMultEqual(T2, B, PtAP, 10, &flg)); 570 if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with PtAP (MATSHELL)\n")); 571 if (testshellops) { /* projections fail if the product operations are not specified */ 572 PetscCall(MatPtAP(T2, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 573 PetscCall(MatPtAP(T2, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &T)); 574 PetscCall(MatPtAPMultEqual(T2, B, T, 10, &flg)); 575 if (!flg) { 576 Mat TE; 577 578 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with PtAP (MATSHELL user defined)\n")); 579 PetscCall(MatComputeOperator(T, MATDENSE, &TE)); 580 PetscCall(MatView(TE, NULL)); 581 PetscCall(MatView(PtAP, NULL)); 582 PetscCall(MatAXPY(TE, -1.0, PtAP, SAME_NONZERO_PATTERN)); 583 PetscCall(MatView(TE, NULL)); 584 PetscCall(MatDestroy(&TE)); 585 } 586 PetscCall(MatDestroy(&T)); 587 } 588 if (RARt) { 589 PetscCall(MatRARtMultEqual(T2, R, RARt, 10, &flg)); 590 if (!flg) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with RARt (MATSHELL)\n")); 591 } 592 if (testshellops) { 593 PetscCall(MatRARt(T2, R, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 594 PetscCall(MatRARt(T2, R, MAT_REUSE_MATRIX, PETSC_DEFAULT, &T)); 595 PetscCall(MatRARtMultEqual(T2, R, T, 10, &flg)); 596 if (!flg) { 597 Mat TE; 598 599 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with RARt (MATSHELL user defined)\n")); 600 PetscCall(MatComputeOperator(T, MATDENSE, &TE)); 601 PetscCall(MatView(TE, NULL)); 602 if (RARt) { 603 PetscCall(MatView(RARt, NULL)); 604 PetscCall(MatAXPY(TE, -1.0, RARt, SAME_NONZERO_PATTERN)); 605 PetscCall(MatView(TE, NULL)); 606 } 607 PetscCall(MatDestroy(&TE)); 608 } 609 PetscCall(MatDestroy(&T)); 610 } 611 } 612 613 if (testmattmat) { /* we either use the shell operations or the loop over columns code applying the transposed operator */ 614 PetscCall(MatTransposeMatMult(T2, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &B)); 615 PetscCall(CheckLocal(B, X, aB, aX)); 616 PetscCall(MatTransposeMatMultEqual(T2, X, B, 10, &flg)); 617 if (!flg) { 618 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with reusage (MatTranspose, MATSHELL)\n")); 619 PetscCall(MatTransposeMatMult(A, X, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 620 PetscCall(MatAXPY(T, -1.0, B, SAME_NONZERO_PATTERN)); 621 PetscCall(MatView(T, NULL)); 622 PetscCall(MatDestroy(&T)); 623 } 624 } 625 if (testmatmatt && testshellops) { /* only when shell operations are set */ 626 PetscCall(MatMatTransposeMult(T2, Bt, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 627 PetscCall(CheckLocal(Bt, X, aBt, aX)); 628 PetscCall(MatMatTransposeMultEqual(T2, Bt, X, 10, &flg)); 629 if (!flg) { 630 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with reusage (MatMatTranspose, MATSHELL)\n")); 631 PetscCall(MatMatTransposeMult(A, Bt, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 632 PetscCall(MatAXPY(T, -1.0, X, SAME_NONZERO_PATTERN)); 633 PetscCall(MatView(T, NULL)); 634 PetscCall(MatDestroy(&T)); 635 } 636 } 637 PetscCall(MatDestroy(&T2)); 638 639 if (testnest) { /* test with MatNest */ 640 Mat NA; 641 642 PetscCall(MatCreateNest(PETSC_COMM_WORLD, 1, NULL, 1, NULL, &A, &NA)); 643 PetscCall(MatViewFromOptions(NA, NULL, "-NA_view")); 644 PetscCall(MatMatMult(NA, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 645 PetscCall(CheckLocal(B, X, aB, aX)); 646 PetscCall(MatMatMultEqual(NA, B, X, 10, &flg)); 647 if (!flg) { 648 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with Nest\n")); 649 PetscCall(MatMatMult(NA, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 650 PetscCall(MatAXPY(T, -1.0, X, SAME_NONZERO_PATTERN)); 651 PetscCall(MatView(T, NULL)); 652 PetscCall(MatDestroy(&T)); 653 } 654 PetscCall(MatDestroy(&NA)); 655 } 656 657 if (testtranspose) { /* test with Transpose */ 658 Mat TA; 659 660 PetscCall(MatCreateTranspose(A, &TA)); 661 PetscCall(MatMatMult(TA, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &B)); 662 PetscCall(CheckLocal(B, X, aB, aX)); 663 PetscCall(MatMatMultEqual(TA, X, B, 10, &flg)); 664 if (!flg) { 665 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with Transpose\n")); 666 PetscCall(MatMatMult(TA, X, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 667 PetscCall(MatAXPY(T, -1.0, B, SAME_NONZERO_PATTERN)); 668 PetscCall(MatView(T, NULL)); 669 PetscCall(MatDestroy(&T)); 670 } 671 PetscCall(MatDestroy(&TA)); 672 } 673 674 if (testhtranspose) { /* test with Hermitian Transpose */ 675 Mat TA; 676 677 PetscCall(MatCreateHermitianTranspose(A, &TA)); 678 PetscCall(MatMatMult(TA, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &B)); 679 PetscCall(CheckLocal(B, X, aB, aX)); 680 PetscCall(MatMatMultEqual(TA, X, B, 10, &flg)); 681 if (!flg) { 682 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with Transpose\n")); 683 PetscCall(MatMatMult(TA, X, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 684 PetscCall(MatAXPY(T, -1.0, B, SAME_NONZERO_PATTERN)); 685 PetscCall(MatView(T, NULL)); 686 PetscCall(MatDestroy(&T)); 687 } 688 PetscCall(MatDestroy(&TA)); 689 } 690 691 if (testtt) { /* test with Transpose(Transpose) */ 692 Mat TA, TTA; 693 694 PetscCall(MatCreateTranspose(A, &TA)); 695 PetscCall(MatCreateTranspose(TA, &TTA)); 696 PetscCall(MatMatMult(TTA, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 697 PetscCall(CheckLocal(B, X, aB, aX)); 698 PetscCall(MatMatMultEqual(TTA, B, X, 10, &flg)); 699 if (!flg) { 700 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with Transpose(Transpose)\n")); 701 PetscCall(MatMatMult(TTA, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 702 PetscCall(MatAXPY(T, -1.0, X, SAME_NONZERO_PATTERN)); 703 PetscCall(MatView(T, NULL)); 704 PetscCall(MatDestroy(&T)); 705 } 706 PetscCall(MatDestroy(&TA)); 707 PetscCall(MatDestroy(&TTA)); 708 } 709 710 if (testcircular) { /* test circular */ 711 Mat AB; 712 713 PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &AB)); 714 PetscCall(MatMatMult(A, B, MAT_REUSE_MATRIX, PETSC_DEFAULT, &X)); 715 PetscCall(CheckLocal(B, X, aB, aX)); 716 if (M == N && N == K) { 717 PetscCall(MatMatMult(A, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &B)); 718 } else { 719 PetscCall(MatTransposeMatMult(A, X, MAT_REUSE_MATRIX, PETSC_DEFAULT, &B)); 720 } 721 PetscCall(CheckLocal(B, X, aB, aX)); 722 PetscCall(MatDestroy(&AB)); 723 } 724 725 /* Test by Pierre Jolivet */ 726 { 727 Mat C, D, D2, AtA; 728 PetscCall(MatCreateNormal(A, &AtA)); 729 PetscCall(MatDuplicate(X, MAT_DO_NOT_COPY_VALUES, &C)); 730 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &D)); 731 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &D2)); 732 PetscCall(MatSetRandom(B, NULL)); 733 PetscCall(MatSetRandom(C, NULL)); 734 PetscCall(MatSetRandom(D, NULL)); 735 PetscCall(MatSetRandom(D2, NULL)); 736 PetscCall(MatProductCreateWithMat(A, B, NULL, C)); 737 PetscCall(MatProductSetType(C, MATPRODUCT_AB)); 738 PetscCall(MatProductSetFromOptions(C)); 739 PetscCall(MatProductSymbolic(C)); 740 PetscCall(MatProductCreateWithMat(A, C, NULL, D)); 741 PetscCall(MatProductSetType(D, MATPRODUCT_AtB)); 742 PetscCall(MatProductSetFromOptions(D)); 743 PetscCall(MatProductSymbolic(D)); 744 PetscCall(MatProductNumeric(C)); 745 PetscCall(MatMatMultEqual(A, B, C, 10, &flg)); 746 if (!flg) { 747 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with Normal (AB != C)\n")); 748 PetscCall(MatView(A, NULL)); 749 PetscCall(MatView(B, NULL)); 750 PetscCall(MatView(C, NULL)); 751 } 752 PetscCall(MatProductNumeric(D)); 753 PetscCall(MatMatMultEqual(AtA, B, D, 10, &flg)); 754 if (!flg) { 755 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error with Normal (2)\n")); 756 PetscCall(MatMatMult(AtA, C, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &T)); 757 PetscCall(MatView(D, NULL)); 758 PetscCall(MatView(T, NULL)); 759 PetscCall(MatAXPY(T, -1.0, D, SAME_NONZERO_PATTERN)); 760 PetscCall(MatView(T, NULL)); 761 PetscCall(MatDestroy(&T)); 762 } 763 PetscCall(MatDestroy(&C)); 764 PetscCall(MatDestroy(&D)); 765 PetscCall(MatDestroy(&D2)); 766 PetscCall(MatDestroy(&AtA)); 767 } 768 769 PetscCall(MatDestroy(&X)); 770 PetscCall(MatDestroy(&Bt)); 771 PetscCall(MatDestroy(&B)); 772 PetscCall(MatDestroy(&A)); 773 PetscCall(MatDestroy(&R)); 774 PetscCall(MatDestroy(&PtAP)); 775 PetscCall(MatDestroy(&RARt)); 776 PetscCall(PetscFree(dataX)); 777 PetscCall(PetscFree(dataB)); 778 PetscCall(PetscFree(dataR)); 779 PetscCall(PetscFree(dataBt)); 780 PetscCall(PetscFinalize()); 781 return 0; 782 } 783 784 /*TEST 785 786 test: 787 suffix: 1 788 args: -local {{0 1}} -testshellops 789 790 test: 791 output_file: output/ex70_1.out 792 requires: cuda 793 suffix: 1_cuda 794 args: -local {{0 1}} -xgpu {{0 1}} -bgpu {{0 1}} -A_mat_type {{seqaijcusparse seqaij}} -testshellops {{0 1}} 795 796 test: 797 output_file: output/ex70_1.out 798 nsize: 2 799 suffix: 1_par 800 args: -local {{0 1}} -testmatmatt 0 801 802 test: 803 output_file: output/ex70_1.out 804 requires: cuda 805 nsize: 2 806 suffix: 1_par_cuda 807 args: -local {{0 1}} -xgpu {{0 1}} -bgpu {{0 1}} -A_mat_type {{mpiaijcusparse mpiaij}} -testnest 0 -testmatmatt 0 -matmatmult_Bbn 3 808 809 test: 810 output_file: output/ex70_1.out 811 suffix: 2 812 nsize: 1 813 args: -M {{7 11}} -N {{12 9}} -K {{1 3}} -local {{0 1}} 814 815 testset: 816 requires: cuda 817 output_file: output/ex70_1.out 818 nsize: 1 819 args: -M 7 -N 9 -K 2 -local {{0 1}} -testnest 0 -A_mat_type {{seqdensecuda seqdense}} -xgpu {{0 1}} -bgpu {{0 1}} 820 test: 821 requires: !complex 822 suffix: 2_cuda_real 823 test: 824 # complex+single gives a little bigger error in the MatDenseGetColumnVec test 825 requires: complex !single 826 suffix: 2_cuda_complex 827 828 test: 829 output_file: output/ex70_1.out 830 suffix: 2_par 831 nsize: 2 832 args: -M {{7 11}} -N {{12 9}} -K {{1 3}} -local {{0 1}} -testcircular -testmatmatt 0 833 834 test: 835 requires: cuda 836 output_file: output/ex70_1.out 837 suffix: 2_par_cuda 838 nsize: 2 839 args: -M 11 -N 9 -K 1 -local {{0 1}} -testcircular 0 -A_mat_type mpiaijcusparse -xgpu -bgpu -testnest 0 -testmatmatt 0 840 841 test: 842 output_file: output/ex70_1.out 843 suffix: 3 844 nsize: {{1 3}} 845 args: -M 13 -N 13 -K {{1 3}} -local {{0 1}} -A_mat_type sbaij -symm -testproj 0 -testmatmatt 0 846 847 test: 848 output_file: output/ex70_1.out 849 suffix: 4 850 nsize: 1 851 args: -M 3 -N 3 -K 3 -local {{0 1}} -testcircular 852 853 test: 854 output_file: output/ex70_1.out 855 suffix: 5 856 nsize: {{2 4}} 857 args: -M 3 -N 3 -K 3 -local {{0 1}} -testcircular -testmatmatt 0 858 859 test: 860 output_file: output/ex70_1.out 861 suffix: 6 862 nsize: 1 863 args: -M {{1 3}} -N {{2 5}} -K {{1 2}} -local {{0 1}} -testcircular 864 865 test: 866 output_file: output/ex70_1.out 867 suffix: 7 868 nsize: 1 869 args: -M 13 -N 13 -K {{1 3}} -local {{0 1}} -A_mat_type dense -testnest -testcircular 870 871 TEST*/ 872