1 2 /* 3 Routines for matrix products. Calling procedure: 4 5 MatProductCreate(A,B,C,&D); or MatProductCreateWithMat(A,B,C,D); 6 MatProductSetType(D, MATPRODUCT_AB/AtB/ABt/PtAP/RARt/ABC); 7 MatProductSetAlgorithm(D, alg); 8 MatProductSetFill(D,fill); 9 MatProductSetFromOptions(D); 10 -> MatProductSetFromOptions_producttype(D): 11 # Check matrix global sizes 12 -> MatProductSetFromOptions_Atype_Btype_Ctype(D); 13 ->MatProductSetFromOptions_Atype_Btype_Ctype_productype(D): 14 # Check matrix local sizes for mpi matrices 15 # Set default algorithm 16 # Get runtime option 17 # Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype; 18 19 PetscLogEventBegin() 20 MatProductSymbolic(D): 21 # Call MatxxxSymbolic_Atype_Btype_Ctype(); 22 # Set D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype; 23 PetscLogEventEnd() 24 25 PetscLogEventBegin() 26 MatProductNumeric(D); 27 # Call (D->ops->matxxxnumeric)(); 28 PetscLogEventEnd() 29 */ 30 31 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 32 33 const char *const MatProductTypes[] = {"AB","AtB","ABt","PtAP","RARt","ABC","MatProductType","MAT_Product_",0}; 34 35 static PetscErrorCode MatProductNumeric_PtAP_Basic(Mat C) 36 { 37 PetscErrorCode ierr; 38 Mat_Product *product = C->product; 39 Mat P = product->B,AP = product->Dwork; 40 41 PetscFunctionBegin; 42 /* AP = A*P */ 43 ierr = MatProductNumeric(AP);CHKERRQ(ierr); 44 /* C = P^T*AP */ 45 if (!C->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage"); 46 ierr = (*C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr); 47 PetscFunctionReturn(0); 48 } 49 50 static PetscErrorCode MatProductSymbolic_PtAP_Basic(Mat C) 51 { 52 PetscErrorCode ierr; 53 Mat_Product *product = C->product; 54 Mat A=product->A,P=product->B,AP; 55 PetscReal fill=product->fill; 56 57 PetscFunctionBegin; 58 /* AP = A*P */ 59 ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr); 60 ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr); 61 ierr = MatProductSetAlgorithm(AP,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 62 ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr); 63 ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr); 64 ierr = MatProductSymbolic(AP);CHKERRQ(ierr); 65 66 /* C = P^T*AP */ 67 ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr); 68 ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 69 product->A = P; 70 product->B = AP; 71 ierr = MatProductSetFromOptions(C);CHKERRQ(ierr); 72 ierr = MatProductSymbolic(C);CHKERRQ(ierr); 73 74 /* resume user's original input matrix setting for A and B */ 75 product->A = A; 76 product->B = P; 77 product->Dwork = AP; 78 79 C->ops->productnumeric = MatProductNumeric_PtAP_Basic; 80 PetscFunctionReturn(0); 81 } 82 83 static PetscErrorCode MatProductNumeric_RARt_Basic(Mat C) 84 { 85 PetscErrorCode ierr; 86 Mat_Product *product = C->product; 87 Mat R=product->B,RA=product->Dwork; 88 89 PetscFunctionBegin; 90 /* RA = R*A */ 91 ierr = MatProductNumeric(RA);CHKERRQ(ierr); 92 /* C = RA*R^T */ 93 if (!C->ops->mattransposemultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage"); 94 ierr = (*C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr); 95 PetscFunctionReturn(0); 96 } 97 98 static PetscErrorCode MatProductSymbolic_RARt_Basic(Mat C) 99 { 100 PetscErrorCode ierr; 101 Mat_Product *product = C->product; 102 Mat A=product->A,R=product->B,RA; 103 PetscReal fill=product->fill; 104 105 PetscFunctionBegin; 106 /* RA = R*A */ 107 ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr); 108 ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr); 109 ierr = MatProductSetAlgorithm(RA,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 110 ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr); 111 ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr); 112 ierr = MatProductSymbolic(RA);CHKERRQ(ierr); 113 114 /* C = RA*R^T */ 115 ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr); 116 ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 117 product->A = RA; 118 ierr = MatProductSetFromOptions(C);CHKERRQ(ierr); 119 ierr = MatProductSymbolic(C);CHKERRQ(ierr); 120 121 /* resume user's original input matrix setting for A */ 122 product->A = A; 123 product->Dwork = RA; /* save here so it will be destroyed with product C */ 124 C->ops->productnumeric = MatProductNumeric_RARt_Basic; 125 PetscFunctionReturn(0); 126 } 127 128 static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) 129 { 130 PetscErrorCode ierr; 131 Mat_Product *product = mat->product; 132 Mat A=product->A,BC=product->Dwork; 133 134 PetscFunctionBegin; 135 /* Numeric BC = B*C */ 136 ierr = MatProductNumeric(BC);CHKERRQ(ierr); 137 /* Numeric mat = A*BC */ 138 if (!mat->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric stage"); 139 ierr = (*mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr); 140 PetscFunctionReturn(0); 141 } 142 143 static PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) 144 { 145 PetscErrorCode ierr; 146 Mat_Product *product = mat->product; 147 Mat B=product->B,C=product->C,BC; 148 PetscReal fill=product->fill; 149 150 PetscFunctionBegin; 151 /* Symbolic BC = B*C */ 152 ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr); 153 ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr); 154 ierr = MatProductSetAlgorithm(BC,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 155 ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr); 156 ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr); 157 ierr = MatProductSymbolic(BC);CHKERRQ(ierr); 158 159 /* Symbolic mat = A*BC */ 160 ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr); 161 ierr = MatProductSetAlgorithm(mat,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 162 product->B = BC; 163 product->Dwork = BC; 164 ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr); 165 ierr = MatProductSymbolic(mat);CHKERRQ(ierr); 166 167 /* resume user's original input matrix setting for B */ 168 product->B = B; 169 mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 170 PetscFunctionReturn(0); 171 } 172 173 PetscErrorCode MatProductSymbolic_Basic(Mat mat) 174 { 175 PetscErrorCode ierr; 176 Mat_Product *product = mat->product; 177 178 PetscFunctionBegin; 179 switch (product->type) { 180 case MATPRODUCT_PtAP: 181 ierr = PetscInfo2((PetscObject)mat, "MatProduct_Basic_PtAP() for A %s, P %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr); 182 ierr = MatProductSymbolic_PtAP_Basic(mat);CHKERRQ(ierr); 183 break; 184 case MATPRODUCT_RARt: 185 ierr = PetscInfo2((PetscObject)mat, "MatProduct_Basic_RARt() for A %s, R %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr); 186 ierr = MatProductSymbolic_RARt_Basic(mat);CHKERRQ(ierr); 187 break; 188 case MATPRODUCT_ABC: 189 ierr = PetscInfo3((PetscObject)mat, "MatProduct_Basic_ABC() for A %s, B %s, C %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name,((PetscObject)product->C)->type_name);CHKERRQ(ierr); 190 ierr = MatProductSymbolic_ABC_Basic(mat);CHKERRQ(ierr); 191 break; 192 default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported"); 193 } 194 PetscFunctionReturn(0); 195 } 196 197 /* ----------------------------------------------- */ 198 /*@C 199 MatProductReplaceMats - Replace input matrices for a matrix product. 200 201 Collective on Mat 202 203 Input Parameters: 204 + A - the matrix or NULL if not being replaced 205 . B - the matrix or NULL if not being replaced 206 . C - the matrix or NULL if not being replaced 207 - D - the matrix product 208 209 Level: intermediate 210 211 Notes: 212 Input matrix must have exactly same data structure as replaced one. 213 214 .seealso: MatProductCreate() 215 @*/ 216 PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D) 217 { 218 PetscErrorCode ierr; 219 Mat_Product *product=D->product; 220 221 PetscFunctionBegin; 222 PetscValidHeaderSpecific(D,MAT_CLASSID,4); 223 if (!product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ORDER,"Mat D does not have struct 'product'. Call MatProductReplaceProduct()"); 224 if (A) { 225 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 226 if (!product->Areplaced) { 227 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); /* take ownership of input */ 228 ierr = MatDestroy(&product->A);CHKERRQ(ierr); /* release old reference */ 229 product->A = A; 230 } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix A was changed by a PETSc internal routine, cannot be replaced"); 231 } 232 if (B) { 233 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 234 if (!product->Breplaced) { 235 ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); /* take ownership of input */ 236 ierr = MatDestroy(&product->B);CHKERRQ(ierr); /* release old reference */ 237 product->B = B; 238 } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix B was changed by a PETSc internal routine, cannot be replaced"); 239 } 240 if (C) { 241 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 242 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); /* take ownership of input */ 243 ierr = MatDestroy(&product->C);CHKERRQ(ierr); /* release old reference */ 244 product->C = C; 245 } 246 PetscFunctionReturn(0); 247 } 248 249 static PetscErrorCode MatProductNumeric_X_Dense(Mat C) 250 { 251 PetscErrorCode ierr; 252 Mat_Product *product = C->product; 253 Mat A = product->A, B = product->B; 254 PetscInt k, K = B->cmap->N; 255 PetscBool t = PETSC_TRUE,iscuda = PETSC_FALSE; 256 PetscBool Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE; 257 char *Btype = NULL,*Ctype = NULL; 258 259 PetscFunctionBegin; 260 switch (product->type) { 261 case MATPRODUCT_AB: 262 t = PETSC_FALSE; 263 case MATPRODUCT_AtB: 264 break; 265 default: SETERRQ3(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatProductNumeric type %s not supported for %s and %s matrices",MatProductTypes[product->type],((PetscObject)A)->type_name,((PetscObject)B)->type_name); 266 } 267 if (PetscDefined(HAVE_CUDA)) { 268 VecType vtype; 269 270 ierr = MatGetVecType(A,&vtype);CHKERRQ(ierr); 271 ierr = PetscStrcmp(vtype,VECCUDA,&iscuda);CHKERRQ(ierr); 272 if (!iscuda) { 273 ierr = PetscStrcmp(vtype,VECSEQCUDA,&iscuda);CHKERRQ(ierr); 274 } 275 if (!iscuda) { 276 ierr = PetscStrcmp(vtype,VECMPICUDA,&iscuda);CHKERRQ(ierr); 277 } 278 if (iscuda) { /* Make sure we have up-to-date data on the GPU */ 279 ierr = PetscStrallocpy(((PetscObject)B)->type_name,&Btype);CHKERRQ(ierr); 280 ierr = PetscStrallocpy(((PetscObject)C)->type_name,&Ctype);CHKERRQ(ierr); 281 ierr = MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr); 282 if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */ 283 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 284 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 285 } 286 ierr = MatConvert(C,MATDENSECUDA,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr); 287 } else { /* Make sure we have up-to-date data on the CPU */ 288 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL) 289 Bcpu = B->boundtocpu; 290 Ccpu = C->boundtocpu; 291 #endif 292 ierr = MatBindToCPU(B,PETSC_TRUE);CHKERRQ(ierr); 293 ierr = MatBindToCPU(C,PETSC_TRUE);CHKERRQ(ierr); 294 } 295 } 296 for (k=0;k<K;k++) { 297 Vec x,y; 298 299 ierr = MatDenseGetColumnVecRead(B,k,&x);CHKERRQ(ierr); 300 ierr = MatDenseGetColumnVecWrite(C,k,&y);CHKERRQ(ierr); 301 if (t) { 302 ierr = MatMultTranspose(A,x,y);CHKERRQ(ierr); 303 } else { 304 ierr = MatMult(A,x,y);CHKERRQ(ierr); 305 } 306 ierr = MatDenseRestoreColumnVecRead(B,k,&x);CHKERRQ(ierr); 307 ierr = MatDenseRestoreColumnVecWrite(C,k,&y);CHKERRQ(ierr); 308 } 309 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 310 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 311 if (PetscDefined(HAVE_CUDA)) { 312 if (iscuda) { 313 ierr = MatConvert(B,Btype,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr); 314 ierr = MatConvert(C,Ctype,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr); 315 } else { 316 ierr = MatBindToCPU(B,Bcpu);CHKERRQ(ierr); 317 ierr = MatBindToCPU(C,Ccpu);CHKERRQ(ierr); 318 } 319 } 320 ierr = PetscFree(Btype);CHKERRQ(ierr); 321 ierr = PetscFree(Ctype);CHKERRQ(ierr); 322 PetscFunctionReturn(0); 323 } 324 325 static PetscErrorCode MatProductSymbolic_X_Dense(Mat C) 326 { 327 PetscErrorCode ierr; 328 Mat_Product *product = C->product; 329 Mat A = product->A, B = product->B; 330 PetscBool isdense; 331 332 PetscFunctionBegin; 333 switch (product->type) { 334 case MATPRODUCT_AB: 335 ierr = MatSetSizes(C,A->rmap->n,B->cmap->n,A->rmap->N,B->cmap->N);CHKERRQ(ierr); 336 break; 337 case MATPRODUCT_AtB: 338 ierr = MatSetSizes(C,A->cmap->n,B->cmap->n,A->cmap->N,B->cmap->N);CHKERRQ(ierr); 339 break; 340 default: SETERRQ3(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatProductSymbolic type %s not supported for %s and %s matrices",MatProductTypes[product->type],((PetscObject)A)->type_name,((PetscObject)B)->type_name); 341 } 342 ierr = PetscObjectBaseTypeCompareAny((PetscObject)C,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr); 343 if (!isdense) { 344 ierr = MatSetType(C,((PetscObject)B)->type_name);CHKERRQ(ierr); 345 /* If matrix type of C was not set or not dense, we need to reset this pointers */ 346 C->ops->productsymbolic = MatProductSymbolic_X_Dense; 347 C->ops->productnumeric = MatProductNumeric_X_Dense; 348 } 349 ierr = MatSetUp(C);CHKERRQ(ierr); 350 PetscFunctionReturn(0); 351 } 352 353 static PetscErrorCode MatProductSetFromOptions_X_Dense(Mat C) 354 { 355 Mat_Product *product = C->product; 356 Mat A = product->A, B = product->B; 357 358 PetscFunctionBegin; 359 C->ops->productsymbolic = NULL; 360 C->ops->productnumeric = NULL; 361 switch (product->type) { 362 case MATPRODUCT_AB: 363 case MATPRODUCT_AtB: 364 C->ops->productsymbolic = MatProductSymbolic_X_Dense; 365 C->ops->productnumeric = MatProductNumeric_X_Dense; 366 break; 367 default: SETERRQ3(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatProduct type %s not supported for %s and %s matrices",MatProductTypes[product->type],((PetscObject)A)->type_name,((PetscObject)B)->type_name); 368 } 369 PetscFunctionReturn(0); 370 } 371 372 /* ----------------------------------------------- */ 373 static PetscErrorCode MatProductSetFromOptions_AB(Mat mat) 374 { 375 PetscErrorCode ierr; 376 Mat_Product *product = mat->product; 377 Mat A=product->A,B=product->B; 378 PetscBool sametype; 379 PetscErrorCode (*fA)(Mat); 380 PetscErrorCode (*fB)(Mat); 381 PetscErrorCode (*f)(Mat)=NULL; 382 PetscBool A_istrans,B_istrans; 383 384 PetscFunctionBegin; 385 /* Check matrix global sizes */ 386 if (B->rmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N); 387 388 fA = A->ops->productsetfromoptions; 389 fB = B->ops->productsetfromoptions; 390 391 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 392 ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&A_istrans);CHKERRQ(ierr); 393 ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&B_istrans);CHKERRQ(ierr); 394 ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 395 396 if (fB == fA && sametype && (!A_istrans || !B_istrans)) { 397 ierr = PetscInfo(mat," sametype and matching op\n");CHKERRQ(ierr); 398 f = fB; 399 } else { 400 char mtypes[256]; 401 PetscBool At_istrans=PETSC_TRUE,Bt_istrans=PETSC_TRUE; 402 Mat At = NULL,Bt = NULL; 403 404 if (A_istrans && !B_istrans) { 405 ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr); 406 ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr); 407 if (At_istrans) { /* mat = ATT * B */ 408 Mat Att = NULL; 409 ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr); 410 ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr); 411 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 412 A = Att; 413 product->A = Att; /* use Att for matproduct */ 414 product->Areplaced = PETSC_TRUE; /* Att = A, but has native matrix type */ 415 } else { /* !At_istrans: mat = At^T*B */ 416 ierr = PetscObjectReference((PetscObject)At);CHKERRQ(ierr); 417 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 418 A = At; 419 product->A = At; 420 product->Areplaced = PETSC_TRUE; 421 product->type = MATPRODUCT_AtB; 422 } 423 } else if (!A_istrans && B_istrans) { 424 ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 425 ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr); 426 if (Bt_istrans) { /* mat = A * BTT */ 427 Mat Btt = NULL; 428 ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr); 429 ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr); 430 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 431 B = Btt; 432 product->B = Btt; /* use Btt for matproduct */ 433 product->Breplaced = PETSC_TRUE; 434 } else { /* !Bt_istrans */ 435 /* mat = A*Bt^T */ 436 ierr = PetscObjectReference((PetscObject)Bt);CHKERRQ(ierr); 437 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 438 B = Bt; 439 product->B = Bt; 440 product->Breplaced = PETSC_TRUE; 441 product->type = MATPRODUCT_ABt; 442 } 443 } else if (A_istrans && B_istrans) { /* mat = At^T * Bt^T */ 444 ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr); 445 ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr); 446 ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 447 ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr); 448 if (At_istrans && Bt_istrans) { 449 Mat Att= NULL,Btt = NULL; 450 ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr); 451 ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr); 452 ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr); 453 ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr); 454 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 455 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 456 A = Att; 457 product->A = Att; product->Areplaced = PETSC_TRUE; 458 B = Btt; 459 product->B = Btt; product->Breplaced = PETSC_TRUE; 460 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not supported yet"); 461 } 462 463 /* query MatProductSetFromOptions_Atype_Btype */ 464 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 465 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 466 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 467 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 468 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 469 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 470 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 471 if (!f) { 472 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 473 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 474 } 475 } 476 477 /* last chance, we can still compute the product if B is of type dense */ 478 if (!f && (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB)) { 479 PetscBool isdense; 480 481 ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr); 482 if (isdense) { 483 f = MatProductSetFromOptions_X_Dense; 484 ierr = PetscInfo(mat," using basic looping over columns of a dense matrix\n");CHKERRQ(ierr); 485 } 486 } 487 488 if (f) { 489 ierr = (*f)(mat);CHKERRQ(ierr); 490 } else { /* reset pointers since the matrix types combination is not available */ 491 ierr = PetscInfo2(mat," for A %s and B %s is not supported\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 492 mat->ops->productsymbolic = NULL; 493 mat->ops->productnumeric = NULL; 494 } 495 PetscFunctionReturn(0); 496 } 497 498 static PetscErrorCode MatProductSetFromOptions_AtB(Mat mat) 499 { 500 PetscErrorCode ierr; 501 Mat_Product *product = mat->product; 502 Mat A=product->A,B=product->B; 503 PetscBool sametype; 504 PetscErrorCode (*fA)(Mat); 505 PetscErrorCode (*fB)(Mat); 506 PetscErrorCode (*f)(Mat)=NULL; 507 508 PetscFunctionBegin; 509 /* Check matrix global sizes */ 510 if (B->rmap->N!=A->rmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->rmap->N); 511 512 fA = A->ops->productsetfromoptions; 513 fB = B->ops->productsetfromoptions; 514 515 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 516 ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 517 518 if (fB == fA && sametype) { 519 ierr = PetscInfo(mat," sametype and matching op\n");CHKERRQ(ierr); 520 f = fB; 521 } else { 522 char mtypes[256]; 523 PetscBool istrans; 524 ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 525 if (!istrans) { 526 /* query MatProductSetFromOptions_Atype_Btype */ 527 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 528 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 529 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 530 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 531 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 532 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 533 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 534 } else { 535 Mat T = NULL; 536 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AtB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name); 537 538 ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr); 539 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 540 ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr); 541 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 542 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 543 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 544 545 product->type = MATPRODUCT_AtB; 546 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 547 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 548 } 549 550 if (!f) { 551 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 552 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 553 } 554 } 555 556 /* last chance, we can still compute the product if B is of type dense */ 557 if (!f && (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB)) { 558 PetscBool isdense; 559 560 ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr); 561 if (isdense) { 562 f = MatProductSetFromOptions_X_Dense; 563 ierr = PetscInfo(mat," using basic looping over columns of a dense matrix\n");CHKERRQ(ierr); 564 } 565 } 566 567 if (f) { 568 ierr = (*f)(mat);CHKERRQ(ierr); 569 } else { /* reset pointers since the matrix types combination is not available */ 570 ierr = PetscInfo2(mat," for A %s and B %s is not supported\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 571 mat->ops->productsymbolic = NULL; 572 mat->ops->productnumeric = NULL; 573 } 574 PetscFunctionReturn(0); 575 } 576 577 static PetscErrorCode MatProductSetFromOptions_ABt(Mat mat) 578 { 579 PetscErrorCode ierr; 580 Mat_Product *product = mat->product; 581 Mat A=product->A,B=product->B; 582 PetscBool sametype; 583 PetscErrorCode (*fA)(Mat); 584 PetscErrorCode (*fB)(Mat); 585 PetscErrorCode (*f)(Mat)=NULL; 586 587 PetscFunctionBegin; 588 /* Check matrix global sizes */ 589 if (B->cmap->N!=A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, AN %D != BN %D",A->cmap->N,B->cmap->N); 590 591 fA = A->ops->productsetfromoptions; 592 fB = B->ops->productsetfromoptions; 593 594 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 595 ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 596 if (fB == fA && sametype) { 597 ierr = PetscInfo(mat," sametype and matching op\n");CHKERRQ(ierr); 598 f = fB; 599 } else { 600 char mtypes[256]; 601 PetscBool istrans; 602 ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 603 if (!istrans) { 604 /* query MatProductSetFromOptions_Atype_Btype */ 605 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 606 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 607 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 608 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 609 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 610 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 611 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 612 } else { 613 Mat T = NULL; 614 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_ABt for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name); 615 616 ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr); 617 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 618 ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr); 619 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 620 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 621 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 622 623 product->type = MATPRODUCT_ABt; 624 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 625 ierr = PetscInfo2(mat," querying %s (ABt)? %p\n",mtypes,f);CHKERRQ(ierr); 626 } 627 628 if (!f) { 629 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 630 ierr = PetscInfo2(mat," querying %s (ABt)? %p\n",mtypes,f);CHKERRQ(ierr); 631 } 632 } 633 634 /* last chance, we can still compute the product if B is of type dense */ 635 if (!f && (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB)) { 636 PetscBool isdense; 637 638 ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr); 639 if (isdense) { 640 f = MatProductSetFromOptions_X_Dense; 641 ierr = PetscInfo(mat," using basic looping over columns of a dense matrix\n");CHKERRQ(ierr); 642 } 643 } 644 645 if (f) { 646 ierr = (*f)(mat);CHKERRQ(ierr); 647 } else { /* reset pointers since the matrix types combination is not available */ 648 ierr = PetscInfo2(mat," for A %s and B %s is not supported\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 649 mat->ops->productsymbolic = NULL; 650 mat->ops->productnumeric = NULL; 651 } 652 PetscFunctionReturn(0); 653 } 654 655 static PetscErrorCode MatProductSetFromOptions_PtAP(Mat mat) 656 { 657 PetscErrorCode ierr; 658 Mat_Product *product = mat->product; 659 Mat A=product->A,B=product->B; 660 PetscBool sametype; 661 PetscErrorCode (*fA)(Mat); 662 PetscErrorCode (*fB)(Mat); 663 PetscErrorCode (*f)(Mat)=NULL; 664 665 PetscFunctionBegin; 666 /* Check matrix global sizes */ 667 if (A->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix A must be square, %D != %D",A->rmap->N,A->cmap->N); 668 if (B->rmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N); 669 670 fA = A->ops->productsetfromoptions; 671 fB = B->ops->productsetfromoptions; 672 673 ierr = PetscInfo2(mat,"for A %s, P %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 674 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 675 if (fB == fA && sametype) { 676 ierr = PetscInfo(mat," sametype and matching op\n");CHKERRQ(ierr); 677 f = fB; 678 } else { 679 /* query MatProductSetFromOptions_Atype_Btype */ 680 char mtypes[256]; 681 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 682 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 683 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 684 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 685 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 686 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 687 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 688 689 if (!f) { 690 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 691 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 692 } 693 } 694 695 if (f) { 696 ierr = (*f)(mat);CHKERRQ(ierr); 697 } else { 698 ierr = PetscInfo2(mat," for A %s, P %s uses MatProduct_Basic() implementation\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 699 mat->ops->productsymbolic = MatProductSymbolic_Basic; 700 } 701 PetscFunctionReturn(0); 702 } 703 704 static PetscErrorCode MatProductSetFromOptions_RARt(Mat mat) 705 { 706 PetscErrorCode ierr; 707 Mat_Product *product = mat->product; 708 Mat A=product->A,B=product->B; 709 PetscBool sametype; 710 PetscErrorCode (*fA)(Mat); 711 PetscErrorCode (*fB)(Mat); 712 PetscErrorCode (*f)(Mat)=NULL; 713 714 PetscFunctionBegin; 715 /* Check matrix global sizes */ 716 if (A->rmap->N != B->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix A must be square, %D != %D",A->rmap->N,A->cmap->N); 717 if (B->cmap->N != A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->cmap->N,A->cmap->N); 718 719 fA = A->ops->productsetfromoptions; 720 fB = B->ops->productsetfromoptions; 721 722 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 723 ierr = PetscInfo2(mat,"for A %s, B %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 724 if (fB == fA && sametype) { 725 ierr = PetscInfo(mat," sametype and matching op\n");CHKERRQ(ierr); 726 f = fB; 727 } else { 728 /* query MatProductSetFromOptions_Atype_Btype */ 729 char mtypes[256]; 730 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 731 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 732 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 733 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 734 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 735 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 736 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 737 738 if (!f) { 739 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 740 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 741 } 742 } 743 744 if (f) { 745 ierr = (*f)(mat);CHKERRQ(ierr); 746 } else { 747 ierr = PetscInfo2(mat," for A %s, P %s uses MatProduct_Basic() implementation\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name);CHKERRQ(ierr); 748 mat->ops->productsymbolic = MatProductSymbolic_Basic; 749 } 750 PetscFunctionReturn(0); 751 } 752 753 static PetscErrorCode MatProductSetFromOptions_ABC(Mat mat) 754 { 755 PetscErrorCode ierr; 756 Mat_Product *product = mat->product; 757 Mat A=product->A,B=product->B,C=product->C; 758 PetscErrorCode (*fA)(Mat); 759 PetscErrorCode (*fB)(Mat); 760 PetscErrorCode (*fC)(Mat); 761 PetscErrorCode (*f)(Mat)=NULL; 762 763 PetscFunctionBegin; 764 /* Check matrix global sizes */ 765 if (B->rmap->N!= A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",B->rmap->N,A->cmap->N); 766 if (C->rmap->N!= B->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %D != %D",C->rmap->N,B->cmap->N); 767 768 fA = A->ops->productsetfromoptions; 769 fB = B->ops->productsetfromoptions; 770 fC = C->ops->productsetfromoptions; 771 ierr = PetscInfo3(mat,"for A %s, B %s and C %s\n",((PetscObject)A)->type_name,((PetscObject)B)->type_name,((PetscObject)C)->type_name);CHKERRQ(ierr); 772 if (fA == fB && fA == fC && fA) { 773 ierr = PetscInfo(mat," matching op\n");CHKERRQ(ierr); 774 f = fA; 775 } else { 776 /* query MatProductSetFromOptions_Atype_Btype_Ctype */ 777 char mtypes[256]; 778 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 779 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 780 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 781 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 782 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 783 ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr); 784 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 785 786 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 787 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 788 if (!f) { 789 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 790 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 791 } 792 if (!f) { 793 ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr); 794 ierr = PetscInfo2(mat," querying %s? %p\n",mtypes,f);CHKERRQ(ierr); 795 } 796 } 797 798 if (f) { 799 ierr = (*f)(mat);CHKERRQ(ierr); 800 } else { /* use MatProductSymbolic/Numeric_Basic() */ 801 ierr = PetscInfo3(mat," for A %s, B %s and C %s uses MatProduct_Basic() implementation",((PetscObject)A)->type_name,((PetscObject)B)->type_name,((PetscObject)C)->type_name);CHKERRQ(ierr); 802 mat->ops->productsymbolic = MatProductSymbolic_Basic; 803 } 804 PetscFunctionReturn(0); 805 } 806 807 /*@C 808 MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database. 809 810 Logically Collective on Mat 811 812 Input Parameter: 813 . mat - the matrix 814 815 Level: beginner 816 817 .seealso: MatSetFromOptions() 818 @*/ 819 PetscErrorCode MatProductSetFromOptions(Mat mat) 820 { 821 PetscErrorCode ierr; 822 823 PetscFunctionBegin; 824 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 825 if (mat->ops->productsetfromoptions) { 826 ierr = (*mat->ops->productsetfromoptions)(mat);CHKERRQ(ierr); 827 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSetType() first"); 828 PetscFunctionReturn(0); 829 } 830 831 /* ----------------------------------------------- */ 832 PetscErrorCode MatProductNumeric_AB(Mat mat) 833 { 834 PetscErrorCode ierr; 835 Mat_Product *product = mat->product; 836 Mat A=product->A,B=product->B; 837 838 PetscFunctionBegin; 839 if (!mat->ops->matmultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name); 840 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 841 ierr = (*mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr); 842 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 843 PetscFunctionReturn(0); 844 } 845 846 PetscErrorCode MatProductNumeric_AtB(Mat mat) 847 { 848 PetscErrorCode ierr; 849 Mat_Product *product = mat->product; 850 Mat A=product->A,B=product->B; 851 852 PetscFunctionBegin; 853 if (!mat->ops->transposematmultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name); 854 ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 855 ierr = (*mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr); 856 ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 857 PetscFunctionReturn(0); 858 } 859 860 PetscErrorCode MatProductNumeric_ABt(Mat mat) 861 { 862 PetscErrorCode ierr; 863 Mat_Product *product = mat->product; 864 Mat A=product->A,B=product->B; 865 866 PetscFunctionBegin; 867 if (!mat->ops->mattransposemultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name); 868 ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 869 ierr = (*mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr); 870 ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 871 PetscFunctionReturn(0); 872 } 873 874 PetscErrorCode MatProductNumeric_PtAP(Mat mat) 875 { 876 PetscErrorCode ierr; 877 Mat_Product *product = mat->product; 878 Mat A=product->A,B=product->B; 879 880 PetscFunctionBegin; 881 if (!mat->ops->ptapnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name); 882 ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr); 883 ierr = (*mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr); 884 ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr); 885 PetscFunctionReturn(0); 886 } 887 888 PetscErrorCode MatProductNumeric_RARt(Mat mat) 889 { 890 PetscErrorCode ierr; 891 Mat_Product *product = mat->product; 892 Mat A=product->A,B=product->B; 893 894 PetscFunctionBegin; 895 if (!mat->ops->rartnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name); 896 ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr); 897 ierr = (*mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr); 898 ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr); 899 PetscFunctionReturn(0); 900 } 901 902 PetscErrorCode MatProductNumeric_ABC(Mat mat) 903 { 904 PetscErrorCode ierr; 905 Mat_Product *product = mat->product; 906 Mat A=product->A,B=product->B,C=product->C; 907 908 PetscFunctionBegin; 909 if (!mat->ops->matmatmultnumeric) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric implementation of product %s for mat %s",MatProductTypes[product->type],((PetscObject)mat)->type_name); 910 ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr); 911 ierr = (*mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr); 912 ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr); 913 PetscFunctionReturn(0); 914 } 915 916 /*@ 917 MatProductNumeric - Implement a matrix product with numerical values. 918 919 Collective on Mat 920 921 Input Parameters: 922 . mat - the matrix to hold a product 923 924 Output Parameters: 925 . mat - the matrix product 926 927 Level: intermediate 928 929 .seealso: MatProductCreate(), MatSetType() 930 @*/ 931 PetscErrorCode MatProductNumeric(Mat mat) 932 { 933 PetscErrorCode ierr; 934 935 PetscFunctionBegin; 936 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 937 if (mat->ops->productnumeric) { 938 ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr); 939 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSymbolic() first"); 940 PetscFunctionReturn(0); 941 } 942 943 /* ----------------------------------------------- */ 944 PetscErrorCode MatProductSymbolic_AB(Mat mat) 945 { 946 PetscErrorCode ierr; 947 Mat_Product *product = mat->product; 948 Mat A=product->A,B=product->B; 949 950 PetscFunctionBegin; 951 if (!mat->ops->matmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 952 ierr = (*mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 953 mat->ops->productnumeric = MatProductNumeric_AB; 954 PetscFunctionReturn(0); 955 } 956 957 PetscErrorCode MatProductSymbolic_AtB(Mat mat) 958 { 959 PetscErrorCode ierr; 960 Mat_Product *product = mat->product; 961 Mat A=product->A,B=product->B; 962 963 PetscFunctionBegin; 964 if (!mat->ops->transposematmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 965 ierr = (*mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 966 mat->ops->productnumeric = MatProductNumeric_AtB; 967 PetscFunctionReturn(0); 968 } 969 970 PetscErrorCode MatProductSymbolic_ABt(Mat mat) 971 { 972 PetscErrorCode ierr; 973 Mat_Product *product = mat->product; 974 Mat A=product->A,B=product->B; 975 976 PetscFunctionBegin; 977 if (!mat->ops->mattransposemultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 978 ierr = (*mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 979 mat->ops->productnumeric = MatProductNumeric_ABt; 980 PetscFunctionReturn(0); 981 } 982 983 PetscErrorCode MatProductSymbolic_ABC(Mat mat) 984 { 985 PetscErrorCode ierr; 986 Mat_Product *product = mat->product; 987 Mat A=product->A,B=product->B,C=product->C; 988 989 PetscFunctionBegin; 990 if (!mat->ops->matmatmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 991 ierr = (*mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr); 992 mat->ops->productnumeric = MatProductNumeric_ABC; 993 PetscFunctionReturn(0); 994 } 995 996 /*@ 997 MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce. 998 999 Collective on Mat 1000 1001 Input Parameters: 1002 . mat - the matrix to hold a product 1003 1004 Output Parameters: 1005 . mat - the matrix product data structure 1006 1007 Level: intermediate 1008 1009 .seealso: MatProductCreate(), MatSetType(), MatProductNumeric(), MatProductType, MatProductAlgorithm 1010 @*/ 1011 PetscErrorCode MatProductSymbolic(Mat mat) 1012 { 1013 PetscErrorCode ierr; 1014 Mat_Product *product = mat->product; 1015 MatProductType productype = product->type; 1016 PetscLogEvent eventtype=-1; 1017 1018 PetscFunctionBegin; 1019 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1020 1021 /* log event */ 1022 switch (productype) { 1023 case MATPRODUCT_AB: 1024 eventtype = MAT_MatMultSymbolic; 1025 break; 1026 case MATPRODUCT_AtB: 1027 eventtype = MAT_TransposeMatMultSymbolic; 1028 break; 1029 case MATPRODUCT_ABt: 1030 eventtype = MAT_MatTransposeMultSymbolic; 1031 break; 1032 case MATPRODUCT_PtAP: 1033 eventtype = MAT_PtAPSymbolic; 1034 break; 1035 case MATPRODUCT_RARt: 1036 eventtype = MAT_RARtSymbolic; 1037 break; 1038 case MATPRODUCT_ABC: 1039 eventtype = MAT_MatMatMultSymbolic; 1040 break; 1041 default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MATPRODUCT type is not supported"); 1042 } 1043 1044 if (mat->ops->productsymbolic) { 1045 ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr); 1046 ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr); 1047 ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr); 1048 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSetFromOptions() first"); 1049 PetscFunctionReturn(0); 1050 } 1051 1052 /*@ 1053 MatProductSetFill - Set an expected fill of the matrix product. 1054 1055 Collective on Mat 1056 1057 Input Parameters: 1058 + mat - the matrix product 1059 - fill - expected fill as ratio of nnz(mat)/(nnz(A) + nnz(B) + nnz(C)); use PETSC_DEFAULT if you do not have a good estimate. If the product is a dense matrix, this is irrelevent. 1060 1061 Level: intermediate 1062 1063 .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate() 1064 @*/ 1065 PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill) 1066 { 1067 Mat_Product *product = mat->product; 1068 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1071 if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Data struct Mat_Product is not created, call MatProductCreate() first"); 1072 if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) product->fill = 2.0; 1073 else product->fill = fill; 1074 PetscFunctionReturn(0); 1075 } 1076 1077 /*@ 1078 MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation. 1079 1080 Collective on Mat 1081 1082 Input Parameters: 1083 + mat - the matrix product 1084 - alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT. 1085 1086 Level: intermediate 1087 1088 .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate() 1089 @*/ 1090 PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg) 1091 { 1092 PetscErrorCode ierr; 1093 Mat_Product *product = mat->product; 1094 1095 PetscFunctionBegin; 1096 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1097 if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Data struct Mat_Product is not created, call MatProductCreate() first"); 1098 ierr = PetscFree(product->alg);CHKERRQ(ierr); 1099 ierr = PetscStrallocpy(alg,&product->alg);CHKERRQ(ierr); 1100 PetscFunctionReturn(0); 1101 } 1102 1103 /*@ 1104 MatProductSetType - Sets a particular matrix product type, for example Mat*Mat. 1105 1106 Collective on Mat 1107 1108 Input Parameters: 1109 + mat - the matrix 1110 - productype - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC. 1111 1112 Level: intermediate 1113 1114 .seealso: MatProductCreate(), MatProductType, MatProductAlgorithm 1115 @*/ 1116 PetscErrorCode MatProductSetType(Mat mat,MatProductType productype) 1117 { 1118 Mat_Product *product = mat->product; 1119 1120 PetscFunctionBegin; 1121 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1122 PetscValidLogicalCollectiveEnum(mat,productype,2); 1123 if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Data struct Mat_Product is not created, call MatProductCreate() first"); 1124 product->type = productype; 1125 1126 switch (productype) { 1127 case MATPRODUCT_AB: 1128 mat->ops->productsetfromoptions = MatProductSetFromOptions_AB; 1129 break; 1130 case MATPRODUCT_AtB: 1131 mat->ops->productsetfromoptions = MatProductSetFromOptions_AtB; 1132 break; 1133 case MATPRODUCT_ABt: 1134 mat->ops->productsetfromoptions = MatProductSetFromOptions_ABt; 1135 break; 1136 case MATPRODUCT_PtAP: 1137 mat->ops->productsetfromoptions = MatProductSetFromOptions_PtAP; 1138 break; 1139 case MATPRODUCT_RARt: 1140 mat->ops->productsetfromoptions = MatProductSetFromOptions_RARt; 1141 break; 1142 case MATPRODUCT_ABC: 1143 mat->ops->productsetfromoptions = MatProductSetFromOptions_ABC; 1144 break; 1145 default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[product->type]); 1146 } 1147 PetscFunctionReturn(0); 1148 } 1149 1150 /*@ 1151 MatProductClear - Clears matrix product internal structure. 1152 1153 Collective on Mat 1154 1155 Input Parameters: 1156 . mat - the product matrix 1157 1158 Level: intermediate 1159 @*/ 1160 PetscErrorCode MatProductClear(Mat mat) 1161 { 1162 PetscErrorCode ierr; 1163 Mat_Product *product = mat->product; 1164 1165 PetscFunctionBegin; 1166 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 1167 if (product) { 1168 /* release reference */ 1169 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 1170 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 1171 ierr = MatDestroy(&product->C);CHKERRQ(ierr); 1172 ierr = PetscFree(product->alg);CHKERRQ(ierr); 1173 ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr); 1174 ierr = PetscFree(mat->product);CHKERRQ(ierr); 1175 } 1176 PetscFunctionReturn(0); 1177 } 1178 1179 /* Create a supporting struct and attach it to the matrix product */ 1180 PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D) 1181 { 1182 PetscErrorCode ierr; 1183 Mat_Product *product=NULL; 1184 1185 PetscFunctionBegin; 1186 ierr = PetscNewLog(D,&product);CHKERRQ(ierr); 1187 product->A = A; 1188 product->B = B; 1189 product->C = C; 1190 product->Dwork = NULL; 1191 product->fill = 2.0; /* PETSC_DEFAULT */ 1192 product->Areplaced = PETSC_FALSE; 1193 product->Breplaced = PETSC_FALSE; 1194 product->api_user = PETSC_FALSE; 1195 D->product = product; 1196 1197 ierr = MatProductSetAlgorithm(D,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 1198 1199 /* take ownership */ 1200 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 1201 ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); 1202 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); 1203 PetscFunctionReturn(0); 1204 } 1205 1206 /*@ 1207 MatProductCreateWithMat - Setup a given matrix as a matrix product. 1208 1209 Collective on Mat 1210 1211 Input Parameters: 1212 + A - the first matrix 1213 . B - the second matrix 1214 . C - the third matrix (optional) 1215 - D - the matrix which will be used as a product 1216 1217 Output Parameters: 1218 . D - the product matrix 1219 1220 Level: intermediate 1221 1222 .seealso: MatProductCreate() 1223 @*/ 1224 PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D) 1225 { 1226 PetscErrorCode ierr; 1227 1228 PetscFunctionBegin; 1229 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1230 PetscValidType(A,1); 1231 MatCheckPreallocated(A,1); 1232 if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1233 if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1234 1235 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 1236 PetscValidType(B,2); 1237 MatCheckPreallocated(B,2); 1238 if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1239 if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1240 1241 if (C) { 1242 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 1243 PetscValidType(C,3); 1244 MatCheckPreallocated(C,3); 1245 if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1246 if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1247 } 1248 1249 PetscValidHeaderSpecific(D,MAT_CLASSID,4); 1250 PetscValidType(D,4); 1251 MatCheckPreallocated(D,4); 1252 if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1253 if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1254 1255 /* Create a supporting struct and attach it to D */ 1256 ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr); 1257 PetscFunctionReturn(0); 1258 } 1259 1260 /*@ 1261 MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations. 1262 1263 Collective on Mat 1264 1265 Input Parameters: 1266 + A - the first matrix 1267 . B - the second matrix 1268 - C - the third matrix (optional) 1269 1270 Output Parameters: 1271 . D - the product matrix 1272 1273 Level: intermediate 1274 1275 .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm() 1276 @*/ 1277 PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D) 1278 { 1279 PetscErrorCode ierr; 1280 1281 PetscFunctionBegin; 1282 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1283 PetscValidType(A,1); 1284 MatCheckPreallocated(A,1); 1285 if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1286 if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1287 1288 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 1289 PetscValidType(B,2); 1290 MatCheckPreallocated(B,2); 1291 if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1292 if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1293 1294 if (C) { 1295 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 1296 PetscValidType(C,3); 1297 MatCheckPreallocated(C,3); 1298 if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1299 if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1300 } 1301 1302 PetscValidPointer(D,4); 1303 1304 ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr); 1305 ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr); 1306 PetscFunctionReturn(0); 1307 } 1308