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