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