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_Private(D) 11 # Check matrix global sizes 12 if the matrices have the same setfromoptions routine, use it 13 if not, try: 14 -> Query MatProductSetFromOptions_Atype_Btype_Ctype_C(D) from A, B and C (in order) 15 if found -> run the specific setup that must set the symbolic operation (these callbacks should never fail) 16 if callback not found or no symbolic operation set 17 -> Query MatProductSetFromOptions_anytype_C(D) from A, B and C (in order) (e.g, matrices may have inner matrices like MATTRANPOSEMAT) 18 if dispatch found but combination still not present do 19 -> check if B is dense and product type AtB or AB -> if true, basic looping of dense columns 20 -> check if triple product (PtAP, RARt or ABC) -> if true, set the Basic routines 21 22 # The setfromoptions calls MatProductSetFromOptions_Atype_Btype_Ctype should 23 # Check matrix local sizes for mpi matrices 24 # Set default algorithm 25 # Get runtime option 26 # Set D->ops->productsymbolic = MatProductSymbolic_productype_Atype_Btype_Ctype if found 27 28 PetscLogEventBegin() 29 MatProductSymbolic(D) 30 # Call MatProductSymbolic_productype_Atype_Btype_Ctype() 31 the callback must set the numeric phase D->ops->productnumeric = MatProductNumeric_productype_Atype_Btype_Ctype 32 PetscLogEventEnd() 33 34 PetscLogEventBegin() 35 MatProductNumeric(D) 36 # Call the numeric phase 37 PetscLogEventEnd() 38 39 # The symbolic phases are allowed to set extra data structures and attach those to the product 40 # this additional data can be reused between multiple numeric phases with the same matrices 41 # if not needed, call 42 MatProductClear(D) 43 */ 44 45 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 46 47 const char *const MatProductTypes[] = {"UNSPECIFIED","AB","AtB","ABt","PtAP","RARt","ABC"}; 48 49 /* these are basic implementations relying on the old function pointers 50 * they are dangerous and should be removed in the future */ 51 static PetscErrorCode MatProductNumeric_PtAP_Basic(Mat C) 52 { 53 PetscErrorCode ierr; 54 Mat_Product *product = C->product; 55 Mat P = product->B,AP = product->Dwork; 56 57 PetscFunctionBegin; 58 /* AP = A*P */ 59 ierr = MatProductNumeric(AP);CHKERRQ(ierr); 60 /* C = P^T*AP */ 61 if (!C->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage"); 62 ierr = (*C->ops->transposematmultnumeric)(P,AP,C);CHKERRQ(ierr); 63 PetscFunctionReturn(0); 64 } 65 66 static PetscErrorCode MatProductSymbolic_PtAP_Basic(Mat C) 67 { 68 PetscErrorCode ierr; 69 Mat_Product *product = C->product; 70 Mat A=product->A,P=product->B,AP; 71 PetscReal fill=product->fill; 72 73 PetscFunctionBegin; 74 ierr = PetscInfo2((PetscObject)C,"for A %s, P %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr); 75 /* AP = A*P */ 76 ierr = MatProductCreate(A,P,NULL,&AP);CHKERRQ(ierr); 77 ierr = MatProductSetType(AP,MATPRODUCT_AB);CHKERRQ(ierr); 78 ierr = MatProductSetAlgorithm(AP,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 79 ierr = MatProductSetFill(AP,fill);CHKERRQ(ierr); 80 ierr = MatProductSetFromOptions(AP);CHKERRQ(ierr); 81 ierr = MatProductSymbolic(AP);CHKERRQ(ierr); 82 83 /* C = P^T*AP */ 84 ierr = MatProductSetType(C,MATPRODUCT_AtB);CHKERRQ(ierr); 85 ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 86 product->A = P; 87 product->B = AP; 88 ierr = MatProductSetFromOptions(C);CHKERRQ(ierr); 89 ierr = MatProductSymbolic(C);CHKERRQ(ierr); 90 91 /* resume user's original input matrix setting for A and B */ 92 product->A = A; 93 product->B = P; 94 product->Dwork = AP; 95 96 C->ops->productnumeric = MatProductNumeric_PtAP_Basic; 97 PetscFunctionReturn(0); 98 } 99 100 static PetscErrorCode MatProductNumeric_RARt_Basic(Mat C) 101 { 102 PetscErrorCode ierr; 103 Mat_Product *product = C->product; 104 Mat R=product->B,RA=product->Dwork; 105 106 PetscFunctionBegin; 107 /* RA = R*A */ 108 ierr = MatProductNumeric(RA);CHKERRQ(ierr); 109 /* C = RA*R^T */ 110 if (!C->ops->mattransposemultnumeric) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing numeric stage"); 111 ierr = (*C->ops->mattransposemultnumeric)(RA,R,C);CHKERRQ(ierr); 112 PetscFunctionReturn(0); 113 } 114 115 static PetscErrorCode MatProductSymbolic_RARt_Basic(Mat C) 116 { 117 PetscErrorCode ierr; 118 Mat_Product *product = C->product; 119 Mat A=product->A,R=product->B,RA; 120 PetscReal fill=product->fill; 121 122 PetscFunctionBegin; 123 ierr = PetscInfo2((PetscObject)C,"for A %s, R %s is used\n",((PetscObject)product->A)->type_name,((PetscObject)product->B)->type_name);CHKERRQ(ierr); 124 /* RA = R*A */ 125 ierr = MatProductCreate(R,A,NULL,&RA);CHKERRQ(ierr); 126 ierr = MatProductSetType(RA,MATPRODUCT_AB);CHKERRQ(ierr); 127 ierr = MatProductSetAlgorithm(RA,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 128 ierr = MatProductSetFill(RA,fill);CHKERRQ(ierr); 129 ierr = MatProductSetFromOptions(RA);CHKERRQ(ierr); 130 ierr = MatProductSymbolic(RA);CHKERRQ(ierr); 131 132 /* C = RA*R^T */ 133 ierr = MatProductSetType(C,MATPRODUCT_ABt);CHKERRQ(ierr); 134 ierr = MatProductSetAlgorithm(C,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 135 product->A = RA; 136 ierr = MatProductSetFromOptions(C);CHKERRQ(ierr); 137 ierr = MatProductSymbolic(C);CHKERRQ(ierr); 138 139 /* resume user's original input matrix setting for A */ 140 product->A = A; 141 product->Dwork = RA; /* save here so it will be destroyed with product C */ 142 C->ops->productnumeric = MatProductNumeric_RARt_Basic; 143 PetscFunctionReturn(0); 144 } 145 146 static PetscErrorCode MatProductNumeric_ABC_Basic(Mat mat) 147 { 148 PetscErrorCode ierr; 149 Mat_Product *product = mat->product; 150 Mat A=product->A,BC=product->Dwork; 151 152 PetscFunctionBegin; 153 /* Numeric BC = B*C */ 154 ierr = MatProductNumeric(BC);CHKERRQ(ierr); 155 /* Numeric mat = A*BC */ 156 if (!mat->ops->transposematmultnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing numeric stage"); 157 ierr = (*mat->ops->matmultnumeric)(A,BC,mat);CHKERRQ(ierr); 158 PetscFunctionReturn(0); 159 } 160 161 static PetscErrorCode MatProductSymbolic_ABC_Basic(Mat mat) 162 { 163 PetscErrorCode ierr; 164 Mat_Product *product = mat->product; 165 Mat B=product->B,C=product->C,BC; 166 PetscReal fill=product->fill; 167 168 PetscFunctionBegin; 169 ierr = PetscInfo3((PetscObject)mat,"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); 170 /* Symbolic BC = B*C */ 171 ierr = MatProductCreate(B,C,NULL,&BC);CHKERRQ(ierr); 172 ierr = MatProductSetType(BC,MATPRODUCT_AB);CHKERRQ(ierr); 173 ierr = MatProductSetAlgorithm(BC,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 174 ierr = MatProductSetFill(BC,fill);CHKERRQ(ierr); 175 ierr = MatProductSetFromOptions(BC);CHKERRQ(ierr); 176 ierr = MatProductSymbolic(BC);CHKERRQ(ierr); 177 178 /* Symbolic mat = A*BC */ 179 ierr = MatProductSetType(mat,MATPRODUCT_AB);CHKERRQ(ierr); 180 ierr = MatProductSetAlgorithm(mat,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 181 product->B = BC; 182 product->Dwork = BC; 183 ierr = MatProductSetFromOptions(mat);CHKERRQ(ierr); 184 ierr = MatProductSymbolic(mat);CHKERRQ(ierr); 185 186 /* resume user's original input matrix setting for B */ 187 product->B = B; 188 mat->ops->productnumeric = MatProductNumeric_ABC_Basic; 189 PetscFunctionReturn(0); 190 } 191 192 static PetscErrorCode MatProductSymbolic_Basic(Mat mat) 193 { 194 PetscErrorCode ierr; 195 Mat_Product *product = mat->product; 196 197 PetscFunctionBegin; 198 switch (product->type) { 199 case MATPRODUCT_PtAP: 200 ierr = MatProductSymbolic_PtAP_Basic(mat);CHKERRQ(ierr); 201 break; 202 case MATPRODUCT_RARt: 203 ierr = MatProductSymbolic_RARt_Basic(mat);CHKERRQ(ierr); 204 break; 205 case MATPRODUCT_ABC: 206 ierr = MatProductSymbolic_ABC_Basic(mat);CHKERRQ(ierr); 207 break; 208 default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[product->type]); 209 } 210 PetscFunctionReturn(0); 211 } 212 213 /* ----------------------------------------------- */ 214 /*@C 215 MatProductReplaceMats - Replace input matrices for a matrix product. 216 217 Collective on Mat 218 219 Input Parameters: 220 + A - the matrix or NULL if not being replaced 221 . B - the matrix or NULL if not being replaced 222 . C - the matrix or NULL if not being replaced 223 - D - the matrix product 224 225 Level: intermediate 226 227 Notes: 228 To reuse the symbolic phase, input matrices must have exactly the same data structure as the replaced one. 229 If the type of any of the input matrices is different than what previously used, the product is cleared and MatProductSetFromOptions()/MatProductSymbolic() are invoked again. 230 231 .seealso: MatProductCreate(), MatProductSetFromOptions(), MatProductSymbolic(). MatProductClear() 232 @*/ 233 PetscErrorCode MatProductReplaceMats(Mat A,Mat B,Mat C,Mat D) 234 { 235 PetscErrorCode ierr; 236 Mat_Product *product; 237 PetscBool flgA = PETSC_TRUE,flgB = PETSC_TRUE,flgC = PETSC_TRUE; 238 239 PetscFunctionBegin; 240 PetscValidHeaderSpecific(D,MAT_CLASSID,4); 241 MatCheckProduct(D,4); 242 product = D->product; 243 if (A) { 244 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 245 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 246 ierr = PetscObjectTypeCompare((PetscObject)product->A,((PetscObject)A)->type_name,&flgA);CHKERRQ(ierr); 247 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 248 product->A = A; 249 } 250 if (B) { 251 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 252 ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); 253 ierr = PetscObjectTypeCompare((PetscObject)product->B,((PetscObject)B)->type_name,&flgB);CHKERRQ(ierr); 254 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 255 product->B = B; 256 } 257 if (C) { 258 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 259 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); 260 ierr = PetscObjectTypeCompare((PetscObject)product->C,((PetscObject)C)->type_name,&flgC);CHKERRQ(ierr); 261 ierr = MatDestroy(&product->C);CHKERRQ(ierr); 262 product->C = C; 263 } 264 /* Any of the replaced mats is of a different type, reset */ 265 if (!flgA || !flgB || !flgC) { 266 if (D->product->destroy) { 267 ierr = (*D->product->destroy)(D->product->data);CHKERRQ(ierr); 268 } 269 D->product->destroy = NULL; 270 D->product->data = NULL; 271 if (D->ops->productnumeric || D->ops->productsymbolic) { 272 ierr = MatProductSetFromOptions(D);CHKERRQ(ierr); 273 ierr = MatProductSymbolic(D);CHKERRQ(ierr); 274 } 275 } 276 PetscFunctionReturn(0); 277 } 278 279 static PetscErrorCode MatProductNumeric_X_Dense(Mat C) 280 { 281 PetscErrorCode ierr; 282 Mat_Product *product = C->product; 283 Mat A = product->A, B = product->B; 284 PetscInt k, K = B->cmap->N; 285 PetscBool t = PETSC_TRUE,iscuda = PETSC_FALSE; 286 PetscBool Bcpu = PETSC_TRUE, Ccpu = PETSC_TRUE; 287 char *Btype = NULL,*Ctype = NULL; 288 289 PetscFunctionBegin; 290 switch (product->type) { 291 case MATPRODUCT_AB: 292 t = PETSC_FALSE; 293 case MATPRODUCT_AtB: 294 break; 295 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); 296 } 297 if (PetscDefined(HAVE_CUDA)) { 298 VecType vtype; 299 300 ierr = MatGetVecType(A,&vtype);CHKERRQ(ierr); 301 ierr = PetscStrcmp(vtype,VECCUDA,&iscuda);CHKERRQ(ierr); 302 if (!iscuda) { 303 ierr = PetscStrcmp(vtype,VECSEQCUDA,&iscuda);CHKERRQ(ierr); 304 } 305 if (!iscuda) { 306 ierr = PetscStrcmp(vtype,VECMPICUDA,&iscuda);CHKERRQ(ierr); 307 } 308 if (iscuda) { /* Make sure we have up-to-date data on the GPU */ 309 ierr = PetscStrallocpy(((PetscObject)B)->type_name,&Btype);CHKERRQ(ierr); 310 ierr = PetscStrallocpy(((PetscObject)C)->type_name,&Ctype);CHKERRQ(ierr); 311 ierr = MatConvert(B,MATDENSECUDA,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr); 312 if (!C->assembled) { /* need to flag the matrix as assembled, otherwise MatConvert will complain */ 313 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 314 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 315 } 316 ierr = MatConvert(C,MATDENSECUDA,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr); 317 } else { /* Make sure we have up-to-date data on the CPU */ 318 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL) 319 Bcpu = B->boundtocpu; 320 Ccpu = C->boundtocpu; 321 #endif 322 ierr = MatBindToCPU(B,PETSC_TRUE);CHKERRQ(ierr); 323 ierr = MatBindToCPU(C,PETSC_TRUE);CHKERRQ(ierr); 324 } 325 } 326 for (k=0;k<K;k++) { 327 Vec x,y; 328 329 ierr = MatDenseGetColumnVecRead(B,k,&x);CHKERRQ(ierr); 330 ierr = MatDenseGetColumnVecWrite(C,k,&y);CHKERRQ(ierr); 331 if (t) { 332 ierr = MatMultTranspose(A,x,y);CHKERRQ(ierr); 333 } else { 334 ierr = MatMult(A,x,y);CHKERRQ(ierr); 335 } 336 ierr = MatDenseRestoreColumnVecRead(B,k,&x);CHKERRQ(ierr); 337 ierr = MatDenseRestoreColumnVecWrite(C,k,&y);CHKERRQ(ierr); 338 } 339 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 340 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 341 if (PetscDefined(HAVE_CUDA)) { 342 if (iscuda) { 343 ierr = MatConvert(B,Btype,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr); 344 ierr = MatConvert(C,Ctype,MAT_INPLACE_MATRIX,&C);CHKERRQ(ierr); 345 } else { 346 ierr = MatBindToCPU(B,Bcpu);CHKERRQ(ierr); 347 ierr = MatBindToCPU(C,Ccpu);CHKERRQ(ierr); 348 } 349 } 350 ierr = PetscFree(Btype);CHKERRQ(ierr); 351 ierr = PetscFree(Ctype);CHKERRQ(ierr); 352 PetscFunctionReturn(0); 353 } 354 355 static PetscErrorCode MatProductSymbolic_X_Dense(Mat C) 356 { 357 PetscErrorCode ierr; 358 Mat_Product *product = C->product; 359 Mat A = product->A, B = product->B; 360 PetscBool isdense; 361 362 PetscFunctionBegin; 363 switch (product->type) { 364 case MATPRODUCT_AB: 365 ierr = MatSetSizes(C,A->rmap->n,B->cmap->n,A->rmap->N,B->cmap->N);CHKERRQ(ierr); 366 break; 367 case MATPRODUCT_AtB: 368 ierr = MatSetSizes(C,A->cmap->n,B->cmap->n,A->cmap->N,B->cmap->N);CHKERRQ(ierr); 369 break; 370 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); 371 } 372 ierr = PetscObjectBaseTypeCompareAny((PetscObject)C,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr); 373 if (!isdense) { 374 ierr = MatSetType(C,((PetscObject)B)->type_name);CHKERRQ(ierr); 375 /* If matrix type of C was not set or not dense, we need to reset the pointer */ 376 C->ops->productsymbolic = MatProductSymbolic_X_Dense; 377 } 378 C->ops->productnumeric = MatProductNumeric_X_Dense; 379 ierr = MatSetUp(C);CHKERRQ(ierr); 380 PetscFunctionReturn(0); 381 } 382 383 /* a single driver to query the dispatching */ 384 static PetscErrorCode MatProductSetFromOptions_Private(Mat mat) 385 { 386 PetscErrorCode ierr; 387 Mat_Product *product = mat->product; 388 PetscInt Am,An,Bm,Bn,Cm,Cn; 389 Mat A = product->A,B = product->B,C = product->C; 390 const char* const Bnames[] = { "B", "R", "P" }; 391 const char* bname; 392 PetscErrorCode (*fA)(Mat); 393 PetscErrorCode (*fB)(Mat); 394 PetscErrorCode (*fC)(Mat); 395 PetscErrorCode (*f)(Mat)=NULL; 396 397 PetscFunctionBegin; 398 mat->ops->productsymbolic = NULL; 399 mat->ops->productnumeric = NULL; 400 if (product->type == MATPRODUCT_UNSPECIFIED) PetscFunctionReturn(0); 401 if (product->type != MATPRODUCT_ABC) C = NULL; /* do not use C if not needed */ 402 if (product->type == MATPRODUCT_RARt) bname = Bnames[1]; 403 else if (product->type == MATPRODUCT_PtAP) bname = Bnames[2]; 404 else bname = Bnames[0]; 405 406 /* Check matrices sizes */ 407 Am = A->rmap->N; 408 An = A->cmap->N; 409 Bm = B->rmap->N; 410 Bn = B->cmap->N; 411 Cm = C ? C->rmap->N : 0; 412 Cn = C ? C->cmap->N : 0; 413 if (product->type == MATPRODUCT_RARt || product->type == MATPRODUCT_ABt) { PetscInt t = Bn; Bn = Bm; Bm = t; } 414 if (product->type == MATPRODUCT_AtB) { PetscInt t = An; An = Am; Am = t; } 415 if (An != Bm) SETERRQ7(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Matrix dimensions of A and %s are incompatible for MatProductType %s: A %Dx%D, %s %Dx%D",bname,MatProductTypes[product->type],A->rmap->N,A->cmap->N,bname,B->rmap->N,B->cmap->N); 416 if (Cm && Cm != Bn) SETERRQ5(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_SIZ,"Matrix dimensions of B and C are incompatible for MatProductType %s: B %Dx%D, C %Dx%D",MatProductTypes[product->type],B->rmap->N,B->cmap->N,Cm,Cn); 417 418 fA = A->ops->productsetfromoptions; 419 fB = B->ops->productsetfromoptions; 420 fC = C ? C->ops->productsetfromoptions : fA; 421 if (C) { 422 ierr = PetscInfo5(mat,"MatProductType %s for A %s, %s %s, C %s\n",MatProductTypes[product->type],((PetscObject)A)->type_name,bname,((PetscObject)B)->type_name,((PetscObject)C)->type_name);CHKERRQ(ierr); 423 } else { 424 ierr = PetscInfo4(mat,"MatProductType %s for A %s, %s %s\n",MatProductTypes[product->type],((PetscObject)A)->type_name,bname,((PetscObject)B)->type_name);CHKERRQ(ierr); 425 } 426 if (fA == fB && fA == fC && fA) { 427 ierr = PetscInfo(mat," matching op\n");CHKERRQ(ierr); 428 ierr = (*fA)(mat);CHKERRQ(ierr); 429 } else { 430 /* query MatProductSetFromOptions_Atype_Btype_Ctype */ 431 char mtypes[256]; 432 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_",sizeof(mtypes));CHKERRQ(ierr); 433 ierr = PetscStrlcat(mtypes,((PetscObject)A)->type_name,sizeof(mtypes));CHKERRQ(ierr); 434 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 435 ierr = PetscStrlcat(mtypes,((PetscObject)B)->type_name,sizeof(mtypes));CHKERRQ(ierr); 436 if (C) { 437 ierr = PetscStrlcat(mtypes,"_",sizeof(mtypes));CHKERRQ(ierr); 438 ierr = PetscStrlcat(mtypes,((PetscObject)C)->type_name,sizeof(mtypes));CHKERRQ(ierr); 439 } 440 ierr = PetscStrlcat(mtypes,"_C",sizeof(mtypes));CHKERRQ(ierr); 441 442 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 443 ierr = PetscInfo2(mat," querying %s from A? %p\n",mtypes,f);CHKERRQ(ierr); 444 if (!f) { 445 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 446 ierr = PetscInfo3(mat," querying %s from %s? %p\n",mtypes,bname,f);CHKERRQ(ierr); 447 } 448 if (!f && C) { 449 ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr); 450 ierr = PetscInfo2(mat," querying %s from C? %p\n",mtypes,f);CHKERRQ(ierr); 451 } 452 if (f) { ierr = (*f)(mat);CHKERRQ(ierr); } 453 454 /* We may have found f but it did not succeed */ 455 /* some matrices (i.e. MATTRANSPOSE, MATSHELL constructed from MatConvert), knows what to do with their inner matrices */ 456 if (!mat->ops->productsymbolic) { 457 ierr = PetscStrncpy(mtypes,"MatProductSetFromOptions_anytype_C",sizeof(mtypes));CHKERRQ(ierr); 458 ierr = PetscObjectQueryFunction((PetscObject)A,mtypes,&f);CHKERRQ(ierr); 459 ierr = PetscInfo2(mat," querying %s from A? %p\n",mtypes,f);CHKERRQ(ierr); 460 if (!f) { 461 ierr = PetscObjectQueryFunction((PetscObject)B,mtypes,&f);CHKERRQ(ierr); 462 ierr = PetscInfo3(mat," querying %s from %s? %p\n",mtypes,bname,f);CHKERRQ(ierr); 463 } 464 if (!f && C) { 465 ierr = PetscObjectQueryFunction((PetscObject)C,mtypes,&f);CHKERRQ(ierr); 466 ierr = PetscInfo2(mat," querying %s from C? %p\n",mtypes,f);CHKERRQ(ierr); 467 } 468 } 469 if (f) { ierr = (*f)(mat);CHKERRQ(ierr); } 470 } 471 472 /* We may have found f but it did not succeed */ 473 if (!mat->ops->productsymbolic) { 474 /* we can still compute the product if B is of type dense */ 475 if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) { 476 PetscBool isdense; 477 478 ierr = PetscObjectBaseTypeCompareAny((PetscObject)B,&isdense,MATSEQDENSE,MATMPIDENSE,"");CHKERRQ(ierr); 479 if (isdense) { 480 481 mat->ops->productsymbolic = MatProductSymbolic_X_Dense; 482 ierr = PetscInfo(mat," using basic looping over columns of a dense matrix\n");CHKERRQ(ierr); 483 } 484 } else if (product->type != MATPRODUCT_ABt) { /* use MatProductSymbolic/Numeric_Basic() for triple products only */ 485 /* 486 TODO: this should be changed to a proper setfromoptions, not setting the symbolic pointer here, because we do not know if 487 the compination will succeed. In order to be sure, we need MatProductGetProductType to return the type of the result 488 before computing the symbolic phase 489 */ 490 ierr = PetscInfo(mat," symbolic product not supported, using MatProductSymbolic_Basic() implementation\n");CHKERRQ(ierr); 491 mat->ops->productsymbolic = MatProductSymbolic_Basic; 492 } 493 } 494 if (!mat->ops->productsymbolic) { 495 ierr = PetscInfo(mat," symbolic product is not supported\n");CHKERRQ(ierr); 496 } 497 PetscFunctionReturn(0); 498 } 499 500 /*@C 501 MatProductSetFromOptions - Creates a matrix product where the type, the algorithm etc are determined from the options database. 502 503 Logically Collective on Mat 504 505 Input Parameter: 506 . mat - the matrix 507 508 Options Database Keys: 509 . -mat_product_clear - Clear intermediate data structures after MatProductNumeric() has been called 510 511 Level: intermediate 512 513 .seealso: MatSetFromOptions(), MatProductCreate(), MatProductCreateWithMat() 514 @*/ 515 PetscErrorCode MatProductSetFromOptions(Mat mat) 516 { 517 PetscErrorCode ierr; 518 519 PetscFunctionBegin; 520 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 521 MatCheckProduct(mat,1); 522 if (mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Cannot call MatProductSetFromOptions with already present data"); 523 ierr = PetscObjectOptionsBegin((PetscObject)mat);CHKERRQ(ierr); 524 ierr = PetscOptionsBool("-mat_product_clear","Clear intermediate data structures after MatProductNumeric() has been called","MatProductClear",mat->product->clear,&mat->product->clear,NULL);CHKERRQ(ierr); 525 ierr = PetscOptionsDeprecated("-mat_freeintermediatedatastructures","-mat_product_clear","3.13","Or call MatProductClear() after MatProductNumeric()");CHKERRQ(ierr); 526 ierr = PetscOptionsEnd();CHKERRQ(ierr); 527 ierr = MatProductSetFromOptions_Private(mat);CHKERRQ(ierr); 528 if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after setup phase"); 529 PetscFunctionReturn(0); 530 } 531 532 /*@C 533 MatProductView - View a MatProduct 534 535 Logically Collective on Mat 536 537 Input Parameter: 538 . mat - the matrix obtained with MatProductCreate() or MatProductCreateWithMat() 539 540 Level: intermediate 541 542 .seealso: MatView(), MatProductCreate(), MatProductCreateWithMat() 543 @*/ 544 PetscErrorCode MatProductView(Mat mat, PetscViewer viewer) 545 { 546 PetscErrorCode ierr; 547 548 PetscFunctionBegin; 549 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 550 if (!mat->product) PetscFunctionReturn(0); 551 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat),&viewer);CHKERRQ(ierr);} 552 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 553 PetscCheckSameComm(mat,1,viewer,2); 554 if (mat->product->view) { 555 ierr = (*mat->product->view)(mat,viewer);CHKERRQ(ierr); 556 } 557 PetscFunctionReturn(0); 558 } 559 560 /* ----------------------------------------------- */ 561 /* these are basic implementations relying on the old function pointers 562 * they are dangerous and should be removed in the future */ 563 PetscErrorCode MatProductNumeric_AB(Mat mat) 564 { 565 PetscErrorCode ierr; 566 Mat_Product *product = mat->product; 567 Mat A=product->A,B=product->B; 568 569 PetscFunctionBegin; 570 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); 571 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 572 ierr = (*mat->ops->matmultnumeric)(A,B,mat);CHKERRQ(ierr); 573 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 574 PetscFunctionReturn(0); 575 } 576 577 PetscErrorCode MatProductNumeric_AtB(Mat mat) 578 { 579 PetscErrorCode ierr; 580 Mat_Product *product = mat->product; 581 Mat A=product->A,B=product->B; 582 583 PetscFunctionBegin; 584 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); 585 ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 586 ierr = (*mat->ops->transposematmultnumeric)(A,B,mat);CHKERRQ(ierr); 587 ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr); 588 PetscFunctionReturn(0); 589 } 590 591 PetscErrorCode MatProductNumeric_ABt(Mat mat) 592 { 593 PetscErrorCode ierr; 594 Mat_Product *product = mat->product; 595 Mat A=product->A,B=product->B; 596 597 PetscFunctionBegin; 598 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); 599 ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 600 ierr = (*mat->ops->mattransposemultnumeric)(A,B,mat);CHKERRQ(ierr); 601 ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 602 PetscFunctionReturn(0); 603 } 604 605 PetscErrorCode MatProductNumeric_PtAP(Mat mat) 606 { 607 PetscErrorCode ierr; 608 Mat_Product *product = mat->product; 609 Mat A=product->A,B=product->B; 610 611 PetscFunctionBegin; 612 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); 613 ierr = PetscLogEventBegin(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr); 614 ierr = (*mat->ops->ptapnumeric)(A,B,mat);CHKERRQ(ierr); 615 ierr = PetscLogEventEnd(MAT_PtAPNumeric,mat,0,0,0);CHKERRQ(ierr); 616 PetscFunctionReturn(0); 617 } 618 619 PetscErrorCode MatProductNumeric_RARt(Mat mat) 620 { 621 PetscErrorCode ierr; 622 Mat_Product *product = mat->product; 623 Mat A=product->A,B=product->B; 624 625 PetscFunctionBegin; 626 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); 627 ierr = PetscLogEventBegin(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr); 628 ierr = (*mat->ops->rartnumeric)(A,B,mat);CHKERRQ(ierr); 629 ierr = PetscLogEventEnd(MAT_RARtNumeric,A,B,0,0);CHKERRQ(ierr); 630 PetscFunctionReturn(0); 631 } 632 633 PetscErrorCode MatProductNumeric_ABC(Mat mat) 634 { 635 PetscErrorCode ierr; 636 Mat_Product *product = mat->product; 637 Mat A=product->A,B=product->B,C=product->C; 638 639 PetscFunctionBegin; 640 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); 641 ierr = PetscLogEventBegin(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr); 642 ierr = (*mat->ops->matmatmultnumeric)(A,B,C,mat);CHKERRQ(ierr); 643 ierr = PetscLogEventEnd(MAT_MatMatMultNumeric,A,B,C,0);CHKERRQ(ierr); 644 PetscFunctionReturn(0); 645 } 646 647 /* ----------------------------------------------- */ 648 649 /*@ 650 MatProductNumeric - Implement a matrix product with numerical values. 651 652 Collective on Mat 653 654 Input/Output Parameter: 655 . mat - the matrix holding the product 656 657 Level: intermediate 658 659 Notes: MatProductSymbolic() must have been called on mat before calling this function 660 661 .seealso: MatProductCreate(), MatSetType(), MatProductSymbolic() 662 @*/ 663 PetscErrorCode MatProductNumeric(Mat mat) 664 { 665 PetscErrorCode ierr; 666 667 PetscFunctionBegin; 668 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 669 MatCheckProduct(mat,1); 670 if (mat->ops->productnumeric) { 671 ierr = (*mat->ops->productnumeric)(mat);CHKERRQ(ierr); 672 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSymbolic() first"); 673 if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after numeric phase"); 674 if (mat->product->clear) { 675 ierr = MatProductClear(mat);CHKERRQ(ierr); 676 } 677 PetscFunctionReturn(0); 678 } 679 680 /* ----------------------------------------------- */ 681 /* these are basic implementations relying on the old function pointers 682 * they are dangerous and should be removed in the future */ 683 PetscErrorCode MatProductSymbolic_AB(Mat mat) 684 { 685 PetscErrorCode ierr; 686 Mat_Product *product = mat->product; 687 Mat A=product->A,B=product->B; 688 689 PetscFunctionBegin; 690 if (!mat->ops->matmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 691 ierr = (*mat->ops->matmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 692 mat->ops->productnumeric = MatProductNumeric_AB; 693 PetscFunctionReturn(0); 694 } 695 696 PetscErrorCode MatProductSymbolic_AtB(Mat mat) 697 { 698 PetscErrorCode ierr; 699 Mat_Product *product = mat->product; 700 Mat A=product->A,B=product->B; 701 702 PetscFunctionBegin; 703 if (!mat->ops->transposematmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 704 ierr = (*mat->ops->transposematmultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 705 mat->ops->productnumeric = MatProductNumeric_AtB; 706 PetscFunctionReturn(0); 707 } 708 709 PetscErrorCode MatProductSymbolic_ABt(Mat mat) 710 { 711 PetscErrorCode ierr; 712 Mat_Product *product = mat->product; 713 Mat A=product->A,B=product->B; 714 715 PetscFunctionBegin; 716 if (!mat->ops->mattransposemultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 717 ierr = (*mat->ops->mattransposemultsymbolic)(A,B,product->fill,mat);CHKERRQ(ierr); 718 mat->ops->productnumeric = MatProductNumeric_ABt; 719 PetscFunctionReturn(0); 720 } 721 722 PetscErrorCode MatProductSymbolic_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 if (!mat->ops->matmatmultsymbolic) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing symbolic implementation of product %s",MatProductTypes[product->type]); 730 ierr = (*mat->ops->matmatmultsymbolic)(A,B,C,product->fill,mat);CHKERRQ(ierr); 731 mat->ops->productnumeric = MatProductNumeric_ABC; 732 PetscFunctionReturn(0); 733 } 734 735 /* ----------------------------------------------- */ 736 737 /*@ 738 MatProductSymbolic - Perform the symbolic portion of a matrix product, this creates a data structure for use with the numerical produce. 739 740 Collective on Mat 741 742 Input/Output Parameter: 743 . mat - the matrix to hold a product 744 745 Level: intermediate 746 747 Notes: MatProductSetFromOptions() must have been called on mat before calling this function 748 749 .seealso: MatProductCreate(), MatProductCreateWithMat(), MatProductSetFromOptions(), MatProductNumeric(), MatProductSetType(), MatProductSetAlgorithm() 750 @*/ 751 PetscErrorCode MatProductSymbolic(Mat mat) 752 { 753 PetscErrorCode ierr; 754 PetscLogEvent eventtype=-1; 755 756 PetscFunctionBegin; 757 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 758 MatCheckProduct(mat,1); 759 if (mat->product->data) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Cannot run symbolic phase. Product data not empty"); 760 761 /* log event */ 762 switch (mat->product->type) { 763 case MATPRODUCT_AB: 764 eventtype = MAT_MatMultSymbolic; 765 break; 766 case MATPRODUCT_AtB: 767 eventtype = MAT_TransposeMatMultSymbolic; 768 break; 769 case MATPRODUCT_ABt: 770 eventtype = MAT_MatTransposeMultSymbolic; 771 break; 772 case MATPRODUCT_PtAP: 773 eventtype = MAT_PtAPSymbolic; 774 break; 775 case MATPRODUCT_RARt: 776 eventtype = MAT_RARtSymbolic; 777 break; 778 case MATPRODUCT_ABC: 779 eventtype = MAT_MatMatMultSymbolic; 780 break; 781 default: SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"ProductType %s is not supported",MatProductTypes[mat->product->type]); 782 } 783 784 mat->ops->productnumeric = NULL; 785 if (mat->ops->productsymbolic) { 786 ierr = PetscLogEventBegin(eventtype,mat,0,0,0);CHKERRQ(ierr); 787 ierr = (*mat->ops->productsymbolic)(mat);CHKERRQ(ierr); 788 ierr = PetscLogEventEnd(eventtype,mat,0,0,0);CHKERRQ(ierr); 789 } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ORDER,"Call MatProductSetFromOptions() first"); 790 if (!mat->product) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Missing product after symbolic phase"); 791 if (!mat->ops->productnumeric) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_PLIB,"Symbolic phase did not specify the numeric phase"); 792 PetscFunctionReturn(0); 793 } 794 795 /*@ 796 MatProductSetFill - Set an expected fill of the matrix product. 797 798 Collective on Mat 799 800 Input Parameters: 801 + mat - the matrix product 802 - 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. 803 804 Level: intermediate 805 806 .seealso: MatProductSetType(), MatProductSetAlgorithm(), MatProductCreate() 807 @*/ 808 PetscErrorCode MatProductSetFill(Mat mat,PetscReal fill) 809 { 810 PetscFunctionBegin; 811 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 812 MatCheckProduct(mat,1); 813 if (fill == PETSC_DEFAULT || fill == PETSC_DECIDE) mat->product->fill = 2.0; 814 else mat->product->fill = fill; 815 PetscFunctionReturn(0); 816 } 817 818 /*@ 819 MatProductSetAlgorithm - Requests a particular algorithm for a matrix product implementation. 820 821 Collective on Mat 822 823 Input Parameters: 824 + mat - the matrix product 825 - alg - particular implementation algorithm of the matrix product, e.g., MATPRODUCTALGORITHM_DEFAULT. 826 827 Level: intermediate 828 829 .seealso: MatProductSetType(), MatProductSetFill(), MatProductCreate(), MatProductAlgorithm 830 @*/ 831 PetscErrorCode MatProductSetAlgorithm(Mat mat,MatProductAlgorithm alg) 832 { 833 PetscErrorCode ierr; 834 835 PetscFunctionBegin; 836 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 837 MatCheckProduct(mat,1); 838 ierr = PetscFree(mat->product->alg);CHKERRQ(ierr); 839 ierr = PetscStrallocpy(alg,&mat->product->alg);CHKERRQ(ierr); 840 PetscFunctionReturn(0); 841 } 842 843 /*@ 844 MatProductSetType - Sets a particular matrix product type 845 846 Collective on Mat 847 848 Input Parameters: 849 + mat - the matrix 850 - productype - matrix product type, e.g., MATPRODUCT_AB,MATPRODUCT_AtB,MATPRODUCT_ABt,MATPRODUCT_PtAP,MATPRODUCT_RARt,MATPRODUCT_ABC. 851 852 Level: intermediate 853 854 .seealso: MatProductCreate(), MatProductType 855 @*/ 856 PetscErrorCode MatProductSetType(Mat mat,MatProductType productype) 857 { 858 PetscErrorCode ierr; 859 860 PetscFunctionBegin; 861 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 862 MatCheckProduct(mat,1); 863 PetscValidLogicalCollectiveEnum(mat,productype,2); 864 if (productype != mat->product->type) { 865 if (mat->product->destroy) { 866 ierr = (*mat->product->destroy)(mat->product->data);CHKERRQ(ierr); 867 } 868 mat->product->destroy = NULL; 869 mat->product->data = NULL; 870 mat->ops->productsymbolic = NULL; 871 mat->ops->productnumeric = NULL; 872 } 873 mat->product->type = productype; 874 PetscFunctionReturn(0); 875 } 876 877 /*@ 878 MatProductClear - Clears matrix product internal structure. 879 880 Collective on Mat 881 882 Input Parameters: 883 . mat - the product matrix 884 885 Level: intermediate 886 887 Notes: this function should be called to remove any intermediate data used by the product 888 After having called this function, MatProduct operations can no longer be used on mat 889 @*/ 890 PetscErrorCode MatProductClear(Mat mat) 891 { 892 PetscErrorCode ierr; 893 Mat_Product *product = mat->product; 894 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 897 if (product) { 898 ierr = MatDestroy(&product->A);CHKERRQ(ierr); 899 ierr = MatDestroy(&product->B);CHKERRQ(ierr); 900 ierr = MatDestroy(&product->C);CHKERRQ(ierr); 901 ierr = PetscFree(product->alg);CHKERRQ(ierr); 902 ierr = MatDestroy(&product->Dwork);CHKERRQ(ierr); 903 if (product->destroy) { 904 ierr = (*product->destroy)(product->data);CHKERRQ(ierr); 905 } 906 } 907 ierr = PetscFree(mat->product);CHKERRQ(ierr); 908 mat->ops->productsymbolic = NULL; 909 mat->ops->productnumeric = NULL; 910 PetscFunctionReturn(0); 911 } 912 913 /* Create a supporting struct and attach it to the matrix product */ 914 PetscErrorCode MatProductCreate_Private(Mat A,Mat B,Mat C,Mat D) 915 { 916 PetscErrorCode ierr; 917 Mat_Product *product=NULL; 918 919 PetscFunctionBegin; 920 PetscValidHeaderSpecific(D,MAT_CLASSID,4); 921 if (D->product) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_PLIB,"Product already present"); 922 ierr = PetscNewLog(D,&product);CHKERRQ(ierr); 923 product->A = A; 924 product->B = B; 925 product->C = C; 926 product->type = MATPRODUCT_UNSPECIFIED; 927 product->Dwork = NULL; 928 product->api_user = PETSC_FALSE; 929 product->clear = PETSC_FALSE; 930 D->product = product; 931 932 ierr = MatProductSetAlgorithm(D,MATPRODUCTALGORITHM_DEFAULT);CHKERRQ(ierr); 933 ierr = MatProductSetFill(D,PETSC_DEFAULT);CHKERRQ(ierr); 934 935 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 936 ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr); 937 ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr); 938 PetscFunctionReturn(0); 939 } 940 941 /*@ 942 MatProductCreateWithMat - Setup a given matrix as a matrix product. 943 944 Collective on Mat 945 946 Input Parameters: 947 + A - the first matrix 948 . B - the second matrix 949 . C - the third matrix (optional) 950 - D - the matrix which will be used as a product 951 952 Output Parameters: 953 . D - the product matrix 954 955 Notes: 956 Any product data attached to D will be cleared 957 958 Level: intermediate 959 960 .seealso: MatProductCreate(), MatProductClear() 961 @*/ 962 PetscErrorCode MatProductCreateWithMat(Mat A,Mat B,Mat C,Mat D) 963 { 964 PetscErrorCode ierr; 965 966 PetscFunctionBegin; 967 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 968 PetscValidType(A,1); 969 MatCheckPreallocated(A,1); 970 if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 971 if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 972 973 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 974 PetscValidType(B,2); 975 MatCheckPreallocated(B,2); 976 if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 977 if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 978 979 if (C) { 980 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 981 PetscValidType(C,3); 982 MatCheckPreallocated(C,3); 983 if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 984 if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 985 } 986 987 PetscValidHeaderSpecific(D,MAT_CLASSID,4); 988 PetscValidType(D,4); 989 MatCheckPreallocated(D,4); 990 if (!D->assembled) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 991 if (D->factortype) SETERRQ(PetscObjectComm((PetscObject)D),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 992 993 /* Create a supporting struct and attach it to D */ 994 ierr = MatProductClear(D);CHKERRQ(ierr); 995 ierr = MatProductCreate_Private(A,B,C,D);CHKERRQ(ierr); 996 PetscFunctionReturn(0); 997 } 998 999 /*@ 1000 MatProductCreate - create a matrix product object that can be used to compute various matrix times matrix operations. 1001 1002 Collective on Mat 1003 1004 Input Parameters: 1005 + A - the first matrix 1006 . B - the second matrix 1007 - C - the third matrix (optional) 1008 1009 Output Parameters: 1010 . D - the product matrix 1011 1012 Level: intermediate 1013 1014 .seealso: MatProductCreateWithMat(), MatProductSetType(), MatProductSetAlgorithm() 1015 @*/ 1016 PetscErrorCode MatProductCreate(Mat A,Mat B,Mat C,Mat *D) 1017 { 1018 PetscErrorCode ierr; 1019 1020 PetscFunctionBegin; 1021 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1022 PetscValidType(A,1); 1023 MatCheckPreallocated(A,1); 1024 if (!A->assembled) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1025 if (A->factortype) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1026 1027 PetscValidHeaderSpecific(B,MAT_CLASSID,2); 1028 PetscValidType(B,2); 1029 MatCheckPreallocated(B,2); 1030 if (!B->assembled) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1031 if (B->factortype) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1032 1033 if (C) { 1034 PetscValidHeaderSpecific(C,MAT_CLASSID,3); 1035 PetscValidType(C,3); 1036 MatCheckPreallocated(C,3); 1037 if (!C->assembled) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 1038 if (C->factortype) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 1039 } 1040 1041 PetscValidPointer(D,4); 1042 ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr); 1043 ierr = MatProductCreate_Private(A,B,C,*D);CHKERRQ(ierr); 1044 PetscFunctionReturn(0); 1045 } 1046