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 static PetscErrorCode MatProductNumeric_PtAP_Basic(Mat C) 34 { 35 PetscErrorCode ierr; 36 Mat_Product *product = C->product; 37 Mat P = product->B,AP = product->Dwork; 38 39 PetscFunctionBegin; 40 /* AP = A*P */ 41 ierr = MatProductNumeric(AP);CHKERRQ(ierr); 42 /* C = P^T*AP */ 43 ierr = (C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr); 44 PetscFunctionReturn(0); 45 } 46 47 static PetscErrorCode MatProductSymbolic_PtAP_Basic(Mat C) 48 { 49 PetscErrorCode ierr; 50 Mat_Product *product = C->product; 51 Mat A=product->A,P=product->B,AP; 52 PetscReal fill=product->fill; 53 54 PetscFunctionBegin; 55 /* AP = A*P */ 56 ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr); 57 ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr); 58 ierr = MatProductSetAlgorithm(AP,"default");CHKERRQ(ierr); 59 ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr); 60 ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr); 61 ierr = MatProductSymbolic(AP);CHKERRQ(ierr); 62 63 /* C = P^T*AP */ 64 ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr); 65 product->alg = "default"; 66 product->A = P; 67 product->B = AP; 68 ierr = MatProductSetFromOptions(C);CHKERRQ(ierr); 69 ierr = MatProductSymbolic(C);CHKERRQ(ierr); 70 71 /* resume user's original input matrix setting for A and B */ 72 product->A = A; 73 product->B = P; 74 product->Dwork = AP; 75 76 C->ops->productnumeric = MatProductNumeric_PtAP_Basic; 77 PetscFunctionReturn(0); 78 } 79 80 static PetscErrorCode MatProductNumeric_RARt_Basic(Mat C) 81 { 82 PetscErrorCode ierr; 83 Mat_Product *product = C->product; 84 Mat R=product->B,RA=product->Dwork; 85 86 PetscFunctionBegin; 87 /* RA = R*A */ 88 ierr = MatProductNumeric(RA);CHKERRQ(ierr); 89 /* C = RA*R^T */ 90 ierr = (C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr); 91 PetscFunctionReturn(0); 92 } 93 94 static PetscErrorCode MatProductSymbolic_RARt_Basic(Mat C) 95 { 96 PetscErrorCode ierr; 97 Mat_Product *product = C->product; 98 Mat A=product->A,R=product->B,RA; 99 PetscReal fill=product->fill; 100 101 PetscFunctionBegin; 102 /* RA = R*A */ 103 ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr); 104 ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr); 105 ierr = MatProductSetAlgorithm(RA,"default");CHKERRQ(ierr); 106 ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr); 107 ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr); 108 ierr = MatProductSymbolic(RA);CHKERRQ(ierr); 109 110 /* C = RA*R^T */ 111 ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr); 112 product->alg = "default"; 113 product->A = RA; 114 ierr = MatProductSetFromOptions(C);CHKERRQ(ierr); 115 ierr = MatProductSymbolic(C);CHKERRQ(ierr); 116 117 /* resume user's original input matrix setting for A */ 118 product->A = A; 119 product->Dwork = RA; /* save here so it will be destroyed with product C */ 120 C->ops->productnumeric = MatProductNumeric_RARt_Basic; 121 PetscFunctionReturn(0); 122 } 123 124 static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) 125 { 126 PetscErrorCode ierr; 127 Mat_Product *product = mat->product; 128 Mat A=product->A,BC=product->Dwork; 129 130 PetscFunctionBegin; 131 /* Numeric BC = B*C */ 132 ierr = MatProductNumeric(BC);CHKERRQ(ierr); 133 /* Numeric mat = A*BC */ 134 ierr = (mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr); 135 PetscFunctionReturn(0); 136 } 137 138 static PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) 139 { 140 PetscErrorCode ierr; 141 Mat_Product *product = mat->product; 142 Mat B=product->B,C=product->C,BC; 143 PetscReal fill=product->fill; 144 145 PetscFunctionBegin; 146 /* Symbolic BC = B*C */ 147 ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr); 148 ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr); 149 ierr = MatProductSetAlgorithm(BC,"default");CHKERRQ(ierr); 150 ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr); 151 ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr); 152 ierr = MatProductSymbolic(BC);CHKERRQ(ierr); 153 154 /* Symbolic mat = A*BC */ 155 ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr); 156 product->alg = "default"; 157 product->B = BC; 158 product->Dwork = BC; 159 ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr); 160 ierr = MatProductSymbolic(mat);CHKERRQ(ierr); 161 162 /* resume user's original input matrix setting for B */ 163 product->B = B; 164 mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 165 PetscFunctionReturn(0); 166 } 167 168 PetscErrorCode MatProductSymbolic_Basic(Mat mat) 169 { 170 PetscErrorCode ierr; 171 Mat_Product *product = mat->product; 172 173 PetscFunctionBegin; 174 switch (product->type) { 175 case MATPRODUCT_PtAP: 176 PetscInfo2((PetscObject)mat, "MatProduct_Basic_PtAP() for A %s, P %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name); 177 ierr = MatProductSymbolic_PtAP_Basic(mat);CHKERRQ(ierr); 178 break; 179 case MATPRODUCT_RARt: 180 PetscInfo2((PetscObject)mat, "MatProduct_Basic_RARt() for A %s, R %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name); 181 ierr = MatProductSymbolic_RARt_Basic(mat);CHKERRQ(ierr); 182 break; 183 case MATPRODUCT_ABC: 184 PetscInfo3((PetscObject)mat, "MatProduct_Basic_ABC() for A %s, B %s, C %s is used",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name,((PetscObject)product->C)->type_name); 185 ierr = MatProductSymbolic_ABC_Basic(mat);CHKERRQ(ierr); 186 break; 187 default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported"); 188 } 189 PetscFunctionReturn(0); 190 } 191 192 /* ----------------------------------------------- */ 193 /*@C 194 MatProductReplaceMats - Replace input matrices for a matrix product. 195 196 Collective on Mat 197 198 Input Parameters: 199 + A - the matrix or NULL if not being replaced 200 . B - the matrix or NULL if not being replaced 201 . C - the matrix or NULL if not being replaced 202 - D - the matrix product 203 204 Level: intermediate 205 206 Notes: 207 Input matrix must have exactly same data structure as replaced one. 208 209 .seealso: MatProductCreate() 210 @*/ 211 PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D) 212 { 213 PetscErrorCode ierr; 214 Mat_Product *product=D->product; 215 216 PetscFunctionBegin; 217 if (!product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_NULL,"Mat D does not have struct 'product'. Call MatProductReplaceProduct(). \n"); 218 if (A) { 219 if (!product->Areplaced) { 220 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); /* take ownership of input */ 221 ierr = MatDestroy(&product->A);CHKERRQ(ierr); /* release old reference */ 222 product->A = A; 223 } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix A was changed by a PETSc internal routine, cannot be replaced"); 224 } 225 if (B) { 226 if (!product->Breplaced) { 227 ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); /* take ownership of input */ 228 ierr = MatDestroy(&product->B);CHKERRQ(ierr); /* release old reference */ 229 product->B = B; 230 } else SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_SUP,"Matrix B was changed by a PETSc internal routine, cannot be replaced"); 231 } 232 if (C) { 233 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); /* take ownership of input */ 234 ierr = MatDestroy(&product->C);CHKERRQ(ierr); /* release old reference */ 235 product->C = C; 236 } 237 PetscFunctionReturn(0); 238 } 239 240 /* ----------------------------------------------- */ 241 static PetscErrorCode MatProductSetFromOptions_AB(Mat mat) 242 { 243 PetscErrorCode ierr; 244 Mat_Product *product = mat->product; 245 Mat A=product->A,B=product->B; 246 PetscBool sametype; 247 PetscErrorCode (*fA)(Mat); 248 PetscErrorCode (*fB)(Mat); 249 PetscErrorCode (*f)(Mat)=NULL; 250 PetscBool A_istrans,B_istrans; 251 252 PetscFunctionBegin; 253 /* Check matrix global sizes */ 254 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); 255 256 fA = A->ops->productsetfromoptions; 257 fB = B->ops->productsetfromoptions; 258 259 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 260 ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&A_istrans);CHKERRQ(ierr); 261 ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&B_istrans);CHKERRQ(ierr); 262 263 if (fB == fA && sametype && (!A_istrans || !B_istrans)) { 264 f = fB; 265 } else { 266 char mtypes[256]; 267 PetscBool At_istrans=PETSC_TRUE,Bt_istrans=PETSC_TRUE; 268 Mat At = NULL,Bt = NULL; 269 270 if (A_istrans && !B_istrans) { 271 ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr); 272 ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr); 273 if (At_istrans) { /* mat = ATT * B */ 274 Mat Att = NULL; 275 ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr); 276 ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr); 277 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 278 A = Att; 279 product->A = Att; /* use Att for matproduct */ 280 product->Areplaced = PETSC_TRUE; /* Att = A, but has native matrix type */ 281 } else { /* !At_istrans: mat = At^T*B */ 282 ierr = PetscObjectReference((PetscObject)At);CHKERRQ(ierr); 283 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 284 A = At; 285 product->A = At; 286 product->Areplaced = PETSC_TRUE; 287 product->type = MATPRODUCT_AtB; 288 } 289 } else if (!A_istrans && B_istrans) { 290 ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 291 ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr); 292 if (Bt_istrans) { /* mat = A * BTT */ 293 Mat Btt = NULL; 294 ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr); 295 ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr); 296 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 297 B = Btt; 298 product->B = Btt; /* use Btt for matproduct */ 299 product->Breplaced = PETSC_TRUE; 300 } else { /* !Bt_istrans */ 301 /* mat = A*Bt^T */ 302 ierr = PetscObjectReference((PetscObject)Bt);CHKERRQ(ierr); 303 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 304 B = Bt; 305 product->B = Bt; 306 product->Breplaced = PETSC_TRUE; 307 product->type = MATPRODUCT_ABt; 308 } 309 } else if (A_istrans && B_istrans) { /* mat = At^T * Bt^T */ 310 ierr = MatTransposeGetMat(A,&At);CHKERRQ(ierr); 311 ierr = PetscObjectTypeCompare((PetscObject)At,MATTRANSPOSEMAT,&At_istrans);CHKERRQ(ierr); 312 ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 313 ierr = PetscObjectTypeCompare((PetscObject)Bt,MATTRANSPOSEMAT,&Bt_istrans);CHKERRQ(ierr); 314 if (At_istrans && Bt_istrans) { 315 Mat Att= NULL,Btt = NULL; 316 ierr = MatTransposeGetMat(At,&Att);CHKERRQ(ierr); 317 ierr = MatTransposeGetMat(Bt,&Btt);CHKERRQ(ierr); 318 ierr = PetscObjectReference((PetscObject)Att);CHKERRQ(ierr); 319 ierr = PetscObjectReference((PetscObject)Btt);CHKERRQ(ierr); 320 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 321 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 322 A = Att; 323 product->A = Att; product->Areplaced = PETSC_TRUE; 324 B = Btt; 325 product->B = Btt; product->Breplaced = PETSC_TRUE; 326 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Not supported yet"); 327 } 328 329 /* query MatProductSetFromOptions_Atype_Btype */ 330 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 331 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 332 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 333 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 334 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 335 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 336 if (!f) { 337 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 338 } 339 } 340 341 if (!f) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name); 342 ierr = (*f)(mat);CHKERRQ(ierr); 343 PetscFunctionReturn(0); 344 } 345 346 static PetscErrorCode MatProductSetFromOptions_AtB(Mat mat) 347 { 348 PetscErrorCode ierr; 349 Mat_Product *product = mat->product; 350 Mat A=product->A,B=product->B; 351 PetscBool sametype; 352 PetscErrorCode (*fA)(Mat); 353 PetscErrorCode (*fB)(Mat); 354 PetscErrorCode (*f)(Mat)=NULL; 355 356 PetscFunctionBegin; 357 /* Check matrix global sizes */ 358 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); 359 360 fA = A->ops->productsetfromoptions; 361 fB = B->ops->productsetfromoptions; 362 363 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 364 365 if (fB == fA && sametype) { 366 f = fB; 367 } else { 368 char mtypes[256]; 369 PetscBool istrans; 370 ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 371 if (!istrans) { 372 /* query MatProductSetFromOptions_Atype_Btype */ 373 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 374 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 375 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 376 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 377 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 378 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 379 } else { 380 Mat T = NULL; 381 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); 382 383 ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr); 384 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 385 ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr); 386 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 387 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 388 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 389 390 product->type = MATPRODUCT_AtB; 391 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 392 } 393 394 if (!f) { 395 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 396 } 397 } 398 if (!f) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name); 399 400 ierr = (*f)(mat);CHKERRQ(ierr); 401 PetscFunctionReturn(0); 402 } 403 404 static PetscErrorCode MatProductSetFromOptions_ABt(Mat mat) 405 { 406 PetscErrorCode ierr; 407 Mat_Product *product = mat->product; 408 Mat A=product->A,B=product->B; 409 PetscBool sametype; 410 PetscErrorCode (*fA)(Mat); 411 PetscErrorCode (*fB)(Mat); 412 PetscErrorCode (*f)(Mat)=NULL; 413 414 PetscFunctionBegin; 415 /* Check matrix global sizes */ 416 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); 417 418 fA = A->ops->productsetfromoptions; 419 fB = B->ops->productsetfromoptions; 420 421 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 422 423 if (fB == fA && sametype) { 424 f = fB; 425 } else { 426 char mtypes[256]; 427 PetscBool istrans; 428 ierr = PetscObjectTypeCompare((PetscObject)A,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 429 if (!istrans) { 430 /* query MatProductSetFromOptions_Atype_Btype */ 431 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 432 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 433 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 434 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 435 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 436 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 437 } else { 438 Mat T = NULL; 439 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); 440 441 ierr = MatTransposeGetMat(A,&T);CHKERRQ(ierr); 442 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 443 ierr = PetscStrlcat(mtypes,((PetscObject)T)->type_name,sizeof(mtypes));CHKERRQ(ierr); 444 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 445 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 446 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 447 448 product->type = MATPRODUCT_ABt; 449 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 450 } 451 452 if (!f) { 453 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 454 } 455 } 456 if (!f) { 457 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatProductSetFromOptions_AB for A %s and B %s is not supported",((PetscObject)A)->type_name,((PetscObject)B)->type_name); 458 } 459 460 ierr = (*f)(mat);CHKERRQ(ierr); 461 PetscFunctionReturn(0); 462 } 463 464 static PetscErrorCode MatProductSetFromOptions_PtAP(Mat mat) 465 { 466 PetscErrorCode ierr; 467 Mat_Product *product = mat->product; 468 Mat A=product->A,B=product->B; 469 PetscBool sametype; 470 PetscErrorCode (*fA)(Mat); 471 PetscErrorCode (*fB)(Mat); 472 PetscErrorCode (*f)(Mat)=NULL; 473 474 PetscFunctionBegin; 475 /* Check matrix global sizes */ 476 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); 477 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); 478 479 fA = A->ops->productsetfromoptions; 480 fB = B->ops->productsetfromoptions; 481 482 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 483 if (fB == fA && sametype) { 484 f = fB; 485 } else { 486 /* query MatProductSetFromOptions_Atype_Btype */ 487 char mtypes[256]; 488 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 489 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 490 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 491 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 492 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 493 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 494 495 if (!f) { 496 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 497 } 498 } 499 500 if (f) { 501 ierr = (*f)(mat);CHKERRQ(ierr); 502 } else { 503 mat->ops->productsymbolic = MatProductSymbolic_Basic; 504 PetscInfo2((PetscObject)mat, "MatProductSetFromOptions_PtAP for A %s, P %s uses MatProduct_Basic() implementation",((PetscObject)A)->type_name,((PetscObject)B)->type_name); 505 } 506 PetscFunctionReturn(0); 507 } 508 509 static PetscErrorCode MatProductSetFromOptions_RARt(Mat mat) 510 { 511 PetscErrorCode ierr; 512 Mat_Product *product = mat->product; 513 Mat A=product->A,B=product->B; 514 PetscBool sametype; 515 PetscErrorCode (*fA)(Mat); 516 PetscErrorCode (*fB)(Mat); 517 PetscErrorCode (*f)(Mat)=NULL; 518 519 PetscFunctionBegin; 520 /* Check matrix global sizes */ 521 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); 522 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); 523 524 fA = A->ops->productsetfromoptions; 525 fB = B->ops->productsetfromoptions; 526 527 ierr = PetscStrcmp(((PetscObject)A)->type_name,((PetscObject)B)->type_name,&sametype);CHKERRQ(ierr); 528 if (fB == fA && sametype) { 529 f = fB; 530 } else { 531 /* query MatProductSetFromOptions_Atype_Btype */ 532 char mtypes[256]; 533 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 534 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 535 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 536 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 537 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 538 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 539 540 if (!f) { 541 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 542 } 543 } 544 545 if (f) { 546 ierr = (*f)(mat);CHKERRQ(ierr); 547 } else { 548 mat->ops->productsymbolic = MatProductSymbolic_Basic; 549 } 550 PetscFunctionReturn(0); 551 } 552 553 static PetscErrorCode MatProductSetFromOptions_ABC(Mat mat) 554 { 555 PetscErrorCode ierr; 556 Mat_Product *product = mat->product; 557 Mat A=product->A,B=product->B,C=product->C; 558 PetscErrorCode (*fA)(Mat); 559 PetscErrorCode (*fB)(Mat); 560 PetscErrorCode (*fC)(Mat); 561 PetscErrorCode (*f)(Mat)=NULL; 562 563 PetscFunctionBegin; 564 /* Check matrix global sizes */ 565 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); 566 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); 567 568 fA = A->ops->productsetfromoptions; 569 fB = B->ops->productsetfromoptions; 570 fC = C->ops->productsetfromoptions; 571 if (fA == fB && fA == fC && fA) { 572 f = fA; 573 } else { 574 /* query MatProductSetFromOptions_Atype_Btype_Ctype */ 575 char mtypes[256]; 576 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 577 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 578 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 579 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 580 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 581 ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr); 582 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 583 584 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 585 if (!f) { 586 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 587 } 588 if (!f) { 589 ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr); 590 } 591 } 592 593 if (f) { 594 ierr = (*f)(mat);CHKERRQ(ierr); 595 } else { /* use MatProductSymbolic/Numeric_Basic() */ 596 mat->ops->productsymbolic = MatProductSymbolic_Basic; 597 } 598 PetscFunctionReturn(0); 599 } 600 601 /*@C 602 MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database. 603 604 Logically Collective on Mat 605 606 Input Parameter: 607 . mat - the matrix 608 609 Level: beginner 610 611 .seealso: MatSetFromOptions() 612 @*/ 613 PetscErrorCode MatProductSetFromOptions(Mat mat) 614 { 615 PetscErrorCode ierr; 616 617 PetscFunctionBegin; 618 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 619 620 if (mat->ops->productsetfromoptions) { 621 ierr = (*mat->ops->productsetfromoptions)(mat);CHKERRQ(ierr); 622 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Call MatProductSetType() first"); 623 PetscFunctionReturn(0); 624 } 625 626 /* ----------------------------------------------- */ 627 PetscErrorCode MatProductNumeric_AB(Mat mat) 628 { 629 PetscErrorCode ierr; 630 Mat_Product *product = mat->product; 631 Mat A=product->A,B=product->B; 632 633 PetscFunctionBegin; 634 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 635 ierr = (mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr); 636 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 637 PetscFunctionReturn(0); 638 } 639 640 PetscErrorCode MatProductNumeric_AtB(Mat mat) 641 { 642 PetscErrorCode ierr; 643 Mat_Product *product = mat->product; 644 Mat A=product->A,B=product->B; 645 646 PetscFunctionBegin; 647 ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 648 ierr = (mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr); 649 ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 650 PetscFunctionReturn(0); 651 } 652 653 PetscErrorCode MatProductNumeric_ABt(Mat mat) 654 { 655 PetscErrorCode ierr; 656 Mat_Product *product = mat->product; 657 Mat A=product->A,B=product->B; 658 659 PetscFunctionBegin; 660 ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 661 ierr = (mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr); 662 ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 663 PetscFunctionReturn(0); 664 } 665 666 PetscErrorCode MatProductNumeric_PtAP(Mat mat) 667 { 668 PetscErrorCode ierr; 669 Mat_Product *product = mat->product; 670 Mat A=product->A,B=product->B; 671 672 PetscFunctionBegin; 673 ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr); 674 ierr = (mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr); 675 ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr); 676 PetscFunctionReturn(0); 677 } 678 679 PetscErrorCode MatProductNumeric_RARt(Mat mat) 680 { 681 PetscErrorCode ierr; 682 Mat_Product *product = mat->product; 683 Mat A=product->A,B=product->B; 684 685 PetscFunctionBegin; 686 ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr); 687 ierr = (mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr); 688 ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr); 689 PetscFunctionReturn(0); 690 } 691 692 PetscErrorCode MatProductNumeric_ABC(Mat mat) 693 { 694 PetscErrorCode ierr; 695 Mat_Product *product = mat->product; 696 Mat A=product->A,B=product->B,C=product->C; 697 698 PetscFunctionBegin; 699 ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr); 700 ierr = (mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr); 701 ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr); 702 PetscFunctionReturn(0); 703 } 704 705 /*@ 706 MatProductNumeric - Implement a matrix product with numerical values. 707 708 Collective on Mat 709 710 Input Parameters: 711 . mat - the matrix to hold a product 712 713 Output Parameters: 714 . mat - the matrix product 715 716 Level: intermediate 717 718 .seealso: MatProductCreate(), MatSetType() 719 @*/ 720 PetscErrorCode MatProductNumeric(Mat mat) 721 { 722 PetscErrorCode ierr; 723 724 PetscFunctionBegin; 725 PetscValidPointer(mat,1); 726 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 727 728 if (mat->ops->productnumeric) { 729 ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr); 730 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSymbolic() first"); 731 PetscFunctionReturn(0); 732 } 733 734 /* ----------------------------------------------- */ 735 PetscErrorCode MatProductSymbolic_AB(Mat mat) 736 { 737 PetscErrorCode ierr; 738 Mat_Product *product = mat->product; 739 Mat A=product->A,B=product->B; 740 741 PetscFunctionBegin; 742 ierr = (mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 743 mat->ops->productnumeric = MatProductNumeric_AB; 744 PetscFunctionReturn(0); 745 } 746 747 PetscErrorCode MatProductSymbolic_AtB(Mat mat) 748 { 749 PetscErrorCode ierr; 750 Mat_Product *product = mat->product; 751 Mat A=product->A,B=product->B; 752 753 PetscFunctionBegin; 754 ierr = (mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 755 mat->ops->productnumeric = MatProductNumeric_AtB; 756 PetscFunctionReturn(0); 757 } 758 759 PetscErrorCode MatProductSymbolic_ABt(Mat mat) 760 { 761 PetscErrorCode ierr; 762 Mat_Product *product = mat->product; 763 Mat A=product->A,B=product->B; 764 765 PetscFunctionBegin; 766 ierr = (mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 767 mat->ops->productnumeric = MatProductNumeric_ABt; 768 PetscFunctionReturn(0); 769 } 770 771 PetscErrorCode MatProductSymbolic_ABC(Mat mat) 772 { 773 PetscErrorCode ierr; 774 Mat_Product *product = mat->product; 775 Mat A=product->A,B=product->B,C=product->C; 776 777 PetscFunctionBegin; 778 ierr = (mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr); 779 mat->ops->productnumeric = MatProductNumeric_ABC; 780 PetscFunctionReturn(0); 781 } 782 783 /*@ 784 MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce. 785 786 Collective on Mat 787 788 Input Parameters: 789 . mat - the matrix to hold a product 790 791 Output Parameters: 792 . mat - the matrix product data structure 793 794 Level: intermediate 795 796 .seealso: MatProductCreate(), MatSetType(), MatProductNumeric(), MatProductType, MatProductAlgorithm 797 @*/ 798 PetscErrorCode MatProductSymbolic(Mat mat) 799 { 800 PetscErrorCode ierr; 801 Mat_Product *product = mat->product; 802 MatProductType productype = product->type; 803 PetscLogEvent eventtype=-1; 804 805 PetscFunctionBegin; 806 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 807 808 /* log event */ 809 switch (productype) { 810 case MATPRODUCT_AB: 811 eventtype = MAT_MatMultSymbolic; 812 break; 813 case MATPRODUCT_AtB: 814 eventtype = MAT_TransposeMatMultSymbolic; 815 break; 816 case MATPRODUCT_ABt: 817 eventtype = MAT_MatTransposeMultSymbolic; 818 break; 819 case MATPRODUCT_PtAP: 820 eventtype = MAT_PtAPSymbolic; 821 break; 822 case MATPRODUCT_RARt: 823 eventtype = MAT_RARtSymbolic; 824 break; 825 case MATPRODUCT_ABC: 826 eventtype = MAT_MatMatMultSymbolic; 827 break; 828 default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MATPRODUCT type is not supported"); 829 } 830 831 if (mat->ops->productsymbolic) { 832 ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr); 833 ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr); 834 ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr); 835 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_USER,"Call MatProductSetFromOptions() first"); 836 PetscFunctionReturn(0); 837 } 838 839 /*@ 840 MatProductSetFill - Set an expected fill of the matrix product. 841 842 Collective on Mat 843 844 Input Parameters: 845 + mat - the matrix product 846 - 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. 847 848 Level: intermediate 849 850 .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate() 851 @*/ 852 PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill) 853 { 854 Mat_Product *product = mat->product; 855 856 PetscFunctionBegin; 857 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 858 859 if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first"); 860 if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) { 861 product->fill = 2.0; 862 } else product->fill = fill; 863 PetscFunctionReturn(0); 864 } 865 866 /*@ 867 MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation. 868 869 Collective on Mat 870 871 Input Parameters: 872 + mat - the matrix product 873 - alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT. 874 875 Level: intermediate 876 877 .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate() 878 @*/ 879 PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg) 880 { 881 Mat_Product *product = mat->product; 882 883 PetscFunctionBegin; 884 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 885 886 if (!product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first"); 887 product->alg = alg; 888 PetscFunctionReturn(0); 889 } 890 891 /*@ 892 MatProductSetType - Sets a particular matrix product type, for example Mat*Mat. 893 894 Collective on Mat 895 896 Input Parameters: 897 + mat - the matrix 898 - productype - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC. 899 900 Level: intermediate 901 902 .seealso: MatProductCreate(), MatProductType, MatProductAlgorithm 903 @*/ 904 PetscErrorCode MatProductSetType(Mat mat,MatProductType productype) 905 { 906 PetscErrorCode ierr; 907 Mat_Product *product = mat->product; 908 MPI_Comm comm; 909 910 PetscFunctionBegin; 911 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 912 913 ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 914 if (!product) SETERRQ(comm,PETSC_ERR_ARG_NULL,"Data struc Mat_Product is not created, call MatProductCreate() first"); 915 product->type = productype; 916 917 switch (productype) { 918 case MATPRODUCT_AB: 919 mat->ops->productsetfromoptions = MatProductSetFromOptions_AB; 920 break; 921 case MATPRODUCT_AtB: 922 mat->ops->productsetfromoptions = MatProductSetFromOptions_AtB; 923 break; 924 case MATPRODUCT_ABt: 925 mat->ops->productsetfromoptions = MatProductSetFromOptions_ABt; 926 break; 927 case MATPRODUCT_PtAP: 928 mat->ops->productsetfromoptions = MatProductSetFromOptions_PtAP; 929 break; 930 case MATPRODUCT_RARt: 931 mat->ops->productsetfromoptions = MatProductSetFromOptions_RARt; 932 break; 933 case MATPRODUCT_ABC: 934 mat->ops->productsetfromoptions = MatProductSetFromOptions_ABC; 935 break; 936 default: SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType is not supported\n"); 937 } 938 PetscFunctionReturn(0); 939 } 940 941 /*@ 942 MatProductClear - Clears matrix product internal structure. 943 944 Collective on Mat 945 946 Input Parameters: 947 . mat - the product matrix 948 949 Level: intermediate 950 @*/ 951 PetscErrorCode MatProductClear(Mat mat) 952 { 953 PetscErrorCode ierr; 954 Mat_Product *product = mat->product; 955 956 PetscFunctionBegin; 957 if (product) { 958 /* release reference */ 959 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 960 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 961 ierr = MatDestroy(&product->C);CHKERRQ(ierr); 962 ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr); 963 ierr = PetscFree(mat->product);CHKERRQ(ierr); 964 } 965 PetscFunctionReturn(0); 966 } 967 968 /* Create a supporting struct and attach it to the matrix product */ 969 PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D) 970 { 971 PetscErrorCode ierr; 972 Mat_Product *product=NULL; 973 974 PetscFunctionBegin; 975 ierr = PetscNewLog(D,&product);CHKERRQ(ierr); 976 product->A = A; 977 product->B = B; 978 product->C = C; 979 product->Dwork = NULL; 980 product->alg = MATPRODUCTALGORITHM_DEFAULT; 981 product->fill = 2.0; /* PETSC_DEFAULT */ 982 product->Areplaced = PETSC_FALSE; 983 product->Breplaced = PETSC_FALSE; 984 product->api_user = PETSC_FALSE; 985 D->product = product; 986 987 /* take ownership */ 988 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 989 ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); 990 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); 991 PetscFunctionReturn(0); 992 } 993 994 /*@ 995 MatProductCreateWithMat - Setup a given matrix as a matrix product. 996 997 Collective on Mat 998 999 Input Parameters: 1000 + A - the first matrix 1001 . B - the second matrix 1002 . C - the third matrix (optional) 1003 - D - the matrix which will be used as a product 1004 1005 Output Parameters: 1006 . D - the product matrix 1007 1008 Level: intermediate 1009 1010 .seealso: MatProductCreate() 1011 @*/ 1012 PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D) 1013 { 1014 PetscErrorCode ierr; 1015 1016 PetscFunctionBegin; 1017 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1018 PetscValidType(A,1); 1019 MatCheckPreallocated(A,1); 1020 if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1021 if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1022 1023 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 1024 PetscValidType(B,2); 1025 MatCheckPreallocated(B,2); 1026 if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1027 if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1028 1029 if (C) { 1030 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 1031 PetscValidType(C,3); 1032 MatCheckPreallocated(C,3); 1033 if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1034 if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1035 } 1036 1037 PetscValidHeaderSpecific(D,MAT_CLASSID,4); 1038 PetscValidType(D,4); 1039 MatCheckPreallocated(D,4); 1040 if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1041 if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1042 1043 /* Create a supporting struct and attach it to D */ 1044 ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr); 1045 PetscFunctionReturn(0); 1046 } 1047 1048 /*@ 1049 MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations. 1050 1051 Collective on Mat 1052 1053 Input Parameters: 1054 + A - the first matrix 1055 . B - the second matrix 1056 - C - the third matrix (optional) 1057 1058 Output Parameters: 1059 . D - the product matrix 1060 1061 Level: intermediate 1062 1063 .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm() 1064 @*/ 1065 PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D) 1066 { 1067 PetscErrorCode ierr; 1068 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1071 PetscValidType(A,1); 1072 MatCheckPreallocated(A,1); 1073 if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1074 if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1075 1076 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 1077 PetscValidType(B,2); 1078 MatCheckPreallocated(B,2); 1079 if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1080 if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1081 1082 if (C) { 1083 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 1084 PetscValidType(C,3); 1085 MatCheckPreallocated(C,3); 1086 if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1087 if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1088 } 1089 1090 PetscValidPointer(D,4); 1091 1092 ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr); 1093 ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr); 1094 PetscFunctionReturn(0); 1095 } 1096