1 #include <../src/mat/impls/elemental/matelemimpl.h> /*I "petscmat.h" I*/ 2 3 /* 4 The variable Petsc_Elemental_keyval is used to indicate an MPI attribute that 5 is attached to a communicator, in this case the attribute is a Mat_Elemental_Grid 6 */ 7 static PetscMPIInt Petsc_Elemental_keyval = MPI_KEYVAL_INVALID; 8 9 #undef __FUNCT__ 10 #define __FUNCT__ "PetscElementalInitializePackage" 11 /*@C 12 PetscElementalInitializePackage - Initialize Elemental package 13 14 Logically Collective 15 16 Level: developer 17 18 .seealso: MATELEMENTAL, PetscElementalFinalizePackage() 19 @*/ 20 PetscErrorCode PetscElementalInitializePackage(void) 21 { 22 PetscErrorCode ierr; 23 24 PetscFunctionBegin; 25 if (elem::Initialized()) PetscFunctionReturn(0); 26 { /* We have already initialized MPI, so this song and dance is just to pass these variables (which won't be used by Elemental) through the interface that needs references */ 27 int zero = 0; 28 char **nothing = 0; 29 elem::Initialize(zero,nothing); 30 } 31 ierr = PetscRegisterFinalize(PetscElementalFinalizePackage);CHKERRQ(ierr); 32 PetscFunctionReturn(0); 33 } 34 35 #undef __FUNCT__ 36 #define __FUNCT__ "PetscElementalFinalizePackage" 37 /*@C 38 PetscElementalFinalizePackage - Finalize Elemental package 39 40 Logically Collective 41 42 Level: developer 43 44 .seealso: MATELEMENTAL, PetscElementalInitializePackage() 45 @*/ 46 PetscErrorCode PetscElementalFinalizePackage(void) 47 { 48 49 PetscFunctionBegin; 50 elem::Finalize(); 51 PetscFunctionReturn(0); 52 } 53 54 #undef __FUNCT__ 55 #define __FUNCT__ "MatView_Elemental" 56 static PetscErrorCode MatView_Elemental(Mat A,PetscViewer viewer) 57 { 58 PetscErrorCode ierr; 59 Mat_Elemental *a = (Mat_Elemental*)A->data; 60 PetscBool iascii; 61 62 PetscFunctionBegin; 63 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 64 if (iascii) { 65 PetscViewerFormat format; 66 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 67 if (format == PETSC_VIEWER_ASCII_INFO) { 68 /* call elemental viewing function */ 69 ierr = PetscViewerASCIIPrintf(viewer,"Elemental run parameters:\n");CHKERRQ(ierr); 70 ierr = PetscViewerASCIIPrintf(viewer," allocated entries=%d\n",(*a->emat).AllocatedMemory());CHKERRQ(ierr); 71 ierr = PetscViewerASCIIPrintf(viewer," grid height=%d, grid width=%d\n",(*a->emat).Grid().Height(),(*a->emat).Grid().Width());CHKERRQ(ierr); 72 if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 73 /* call elemental viewing function */ 74 ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"test matview_elemental 2\n");CHKERRQ(ierr); 75 } 76 77 } else if (format == PETSC_VIEWER_DEFAULT) { 78 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 79 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");CHKERRQ(ierr); 80 a->emat->Print("Elemental matrix (cyclic ordering)"); 81 ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 82 if (A->factortype == MAT_FACTOR_NONE){ 83 Mat Adense; 84 ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"Elemental matrix (explicit ordering)\n");CHKERRQ(ierr); 85 ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr); 86 ierr = MatView(Adense,viewer);CHKERRQ(ierr); 87 ierr = MatDestroy(&Adense);CHKERRQ(ierr); 88 } 89 } else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Format"); 90 } else { 91 /* convert to dense format and call MatView() */ 92 Mat Adense; 93 ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"Elemental matrix (explicit ordering)\n");CHKERRQ(ierr); 94 ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr); 95 ierr = MatView(Adense,viewer);CHKERRQ(ierr); 96 ierr = MatDestroy(&Adense);CHKERRQ(ierr); 97 } 98 PetscFunctionReturn(0); 99 } 100 101 #undef __FUNCT__ 102 #define __FUNCT__ "MatGetInfo_Elemental" 103 static PetscErrorCode MatGetInfo_Elemental(Mat A,MatInfoType flag,MatInfo *info) 104 { 105 Mat_Elemental *a = (Mat_Elemental*)A->data; 106 PetscMPIInt rank; 107 108 PetscFunctionBegin; 109 MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank); 110 111 /* if (!rank) printf(" .........MatGetInfo_Elemental ...\n"); */ 112 info->block_size = 1.0; 113 114 if (flag == MAT_LOCAL) { 115 info->nz_allocated = (double)(*a->emat).AllocatedMemory(); /* locally allocated */ 116 info->nz_used = info->nz_allocated; 117 } else if (flag == MAT_GLOBAL_MAX) { 118 //ierr = MPI_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr); 119 /* see MatGetInfo_MPIAIJ() for getting global info->nz_allocated! */ 120 //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_MAX not written yet"); 121 } else if (flag == MAT_GLOBAL_SUM) { 122 //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_SUM not written yet"); 123 info->nz_allocated = (double)(*a->emat).AllocatedMemory(); /* locally allocated */ 124 info->nz_used = info->nz_allocated; /* assume Elemental does accurate allocation */ 125 //ierr = MPI_Allreduce(isend,irecv,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 126 //PetscPrintf(PETSC_COMM_SELF," ... [%d] locally allocated %g\n",rank,info->nz_allocated); 127 } 128 129 info->nz_unneeded = 0.0; 130 info->assemblies = (double)A->num_ass; 131 info->mallocs = 0; 132 info->memory = ((PetscObject)A)->mem; 133 info->fill_ratio_given = 0; /* determined by Elemental */ 134 info->fill_ratio_needed = 0; 135 info->factor_mallocs = 0; 136 PetscFunctionReturn(0); 137 } 138 139 #undef __FUNCT__ 140 #define __FUNCT__ "MatSetValues_Elemental" 141 static PetscErrorCode MatSetValues_Elemental(Mat A,PetscInt nr,const PetscInt *rows,PetscInt nc,const PetscInt *cols,const PetscScalar *vals,InsertMode imode) 142 { 143 PetscErrorCode ierr; 144 Mat_Elemental *a = (Mat_Elemental*)A->data; 145 PetscMPIInt rank; 146 PetscInt i,j,rrank,ridx,crank,cidx; 147 148 PetscFunctionBegin; 149 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr); 150 151 const elem::Grid &grid = a->emat->Grid(); 152 for (i=0; i<nr; i++) { 153 PetscInt erow,ecol,elrow,elcol; 154 if (rows[i] < 0) continue; 155 P2RO(A,0,rows[i],&rrank,&ridx); 156 RO2E(A,0,rrank,ridx,&erow); 157 if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation"); 158 for (j=0; j<nc; j++) { 159 if (cols[j] < 0) continue; 160 P2RO(A,1,cols[j],&crank,&cidx); 161 RO2E(A,1,crank,cidx,&ecol); 162 if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation"); 163 if (erow % grid.MCSize() != grid.MCRank() || ecol % grid.MRSize() != grid.MRRank()){ /* off-proc entry */ 164 if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported"); 165 /* PetscPrintf(PETSC_COMM_SELF,"[%D] add off-proc entry (%D,%D, %g) (%D %D)\n",rank,rows[i],cols[j],*(vals+i*nc),erow,ecol); */ 166 a->esubmat->Set(0,0, (PetscElemScalar)vals[i*nc+j]); 167 a->interface->Axpy(1.0,*(a->esubmat),erow,ecol); 168 continue; 169 } 170 elrow = erow / grid.MCSize(); 171 elcol = ecol / grid.MRSize(); 172 switch (imode) { 173 case INSERT_VALUES: a->emat->SetLocal(elrow,elcol,(PetscElemScalar)vals[i*nc+j]); break; 174 case ADD_VALUES: a->emat->UpdateLocal(elrow,elcol,(PetscElemScalar)vals[i*nc+j]); break; 175 default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode); 176 } 177 } 178 } 179 PetscFunctionReturn(0); 180 } 181 182 #undef __FUNCT__ 183 #define __FUNCT__ "MatMult_Elemental" 184 static PetscErrorCode MatMult_Elemental(Mat A,Vec X,Vec Y) 185 { 186 Mat_Elemental *a = (Mat_Elemental*)A->data; 187 PetscErrorCode ierr; 188 const PetscElemScalar *x; 189 PetscElemScalar *y; 190 PetscElemScalar one = 1,zero = 0; 191 192 PetscFunctionBegin; 193 ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 194 ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 195 { /* Scoping so that constructor is called before pointer is returned */ 196 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> xe(A->cmap->N,1,0,x,A->cmap->n,*a->grid); 197 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> ye(A->rmap->N,1,0,y,A->rmap->n,*a->grid); 198 elem::Gemv(elem::NORMAL,one,*a->emat,xe,zero,ye); 199 } 200 ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 201 ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 202 PetscFunctionReturn(0); 203 } 204 205 #undef __FUNCT__ 206 #define __FUNCT__ "MatMultTranspose_Elemental" 207 static PetscErrorCode MatMultTranspose_Elemental(Mat A,Vec X,Vec Y) 208 { 209 Mat_Elemental *a = (Mat_Elemental*)A->data; 210 PetscErrorCode ierr; 211 const PetscElemScalar *x; 212 PetscElemScalar *y; 213 PetscElemScalar one = 1,zero = 0; 214 215 PetscFunctionBegin; 216 ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 217 ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 218 { /* Scoping so that constructor is called before pointer is returned */ 219 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> xe(A->rmap->N,1,0,x,A->rmap->n,*a->grid); 220 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> ye(A->cmap->N,1,0,y,A->cmap->n,*a->grid); 221 elem::Gemv(elem::TRANSPOSE,one,*a->emat,xe,zero,ye); 222 } 223 ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 224 ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 225 PetscFunctionReturn(0); 226 } 227 228 #undef __FUNCT__ 229 #define __FUNCT__ "MatMultAdd_Elemental" 230 static PetscErrorCode MatMultAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z) 231 { 232 Mat_Elemental *a = (Mat_Elemental*)A->data; 233 PetscErrorCode ierr; 234 const PetscElemScalar *x; 235 PetscElemScalar *z; 236 PetscElemScalar one = 1; 237 238 PetscFunctionBegin; 239 if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);} 240 ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 241 ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 242 { /* Scoping so that constructor is called before pointer is returned */ 243 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> xe(A->cmap->N,1,0,x,A->cmap->n,*a->grid); 244 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> ze(A->rmap->N,1,0,z,A->rmap->n,*a->grid); 245 elem::Gemv(elem::NORMAL,one,*a->emat,xe,one,ze); 246 } 247 ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 248 ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 249 PetscFunctionReturn(0); 250 } 251 252 #undef __FUNCT__ 253 #define __FUNCT__ "MatMultTransposeAdd_Elemental" 254 static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z) 255 { 256 Mat_Elemental *a = (Mat_Elemental*)A->data; 257 PetscErrorCode ierr; 258 const PetscElemScalar *x; 259 PetscElemScalar *z; 260 PetscElemScalar one = 1; 261 262 PetscFunctionBegin; 263 if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);} 264 ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 265 ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 266 { /* Scoping so that constructor is called before pointer is returned */ 267 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> xe(A->rmap->N,1,0,x,A->rmap->n,*a->grid); 268 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> ze(A->cmap->N,1,0,z,A->cmap->n,*a->grid); 269 elem::Gemv(elem::TRANSPOSE,one,*a->emat,xe,one,ze); 270 } 271 ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 272 ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 273 PetscFunctionReturn(0); 274 } 275 276 #undef __FUNCT__ 277 #define __FUNCT__ "MatMatMultNumeric_Elemental" 278 static PetscErrorCode MatMatMultNumeric_Elemental(Mat A,Mat B,Mat C) 279 { 280 Mat_Elemental *a = (Mat_Elemental*)A->data; 281 Mat_Elemental *b = (Mat_Elemental*)B->data; 282 Mat_Elemental *c = (Mat_Elemental*)C->data; 283 PetscElemScalar one = 1,zero = 0; 284 285 PetscFunctionBegin; 286 { /* Scoping so that constructor is called before pointer is returned */ 287 elem::Gemm(elem::NORMAL,elem::NORMAL,one,*a->emat,*b->emat,zero,*c->emat); 288 } 289 C->assembled = PETSC_TRUE; 290 PetscFunctionReturn(0); 291 } 292 293 #undef __FUNCT__ 294 #define __FUNCT__ "MatMatMultSymbolic_Elemental" 295 static PetscErrorCode MatMatMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat *C) 296 { 297 PetscErrorCode ierr; 298 Mat Ce; 299 MPI_Comm comm; 300 301 PetscFunctionBegin; 302 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 303 ierr = MatCreate(comm,&Ce);CHKERRQ(ierr); 304 ierr = MatSetSizes(Ce,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 305 ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr); 306 ierr = MatSetUp(Ce);CHKERRQ(ierr); 307 *C = Ce; 308 PetscFunctionReturn(0); 309 } 310 311 #undef __FUNCT__ 312 #define __FUNCT__ "MatMatMult_Elemental" 313 static PetscErrorCode MatMatMult_Elemental(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 314 { 315 PetscErrorCode ierr; 316 317 PetscFunctionBegin; 318 if (scall == MAT_INITIAL_MATRIX){ 319 ierr = MatMatMultSymbolic_Elemental(A,B,1.0,C);CHKERRQ(ierr); 320 } 321 ierr = MatMatMultNumeric_Elemental(A,B,*C);CHKERRQ(ierr); 322 PetscFunctionReturn(0); 323 } 324 325 #undef __FUNCT__ 326 #define __FUNCT__ "MatMatTransposeMultNumeric_Elemental" 327 static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A,Mat B,Mat C) 328 { 329 Mat_Elemental *a = (Mat_Elemental*)A->data; 330 Mat_Elemental *b = (Mat_Elemental*)B->data; 331 Mat_Elemental *c = (Mat_Elemental*)C->data; 332 PetscElemScalar one = 1,zero = 0; 333 334 PetscFunctionBegin; 335 { /* Scoping so that constructor is called before pointer is returned */ 336 elem::Gemm(elem::NORMAL,elem::TRANSPOSE,one,*a->emat,*b->emat,zero,*c->emat); 337 } 338 C->assembled = PETSC_TRUE; 339 PetscFunctionReturn(0); 340 } 341 342 #undef __FUNCT__ 343 #define __FUNCT__ "MatMatTransposeMultSymbolic_Elemental" 344 static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat *C) 345 { 346 PetscErrorCode ierr; 347 Mat Ce; 348 MPI_Comm comm; 349 350 PetscFunctionBegin; 351 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 352 ierr = MatCreate(comm,&Ce);CHKERRQ(ierr); 353 ierr = MatSetSizes(Ce,A->rmap->n,B->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 354 ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr); 355 ierr = MatSetUp(Ce);CHKERRQ(ierr); 356 *C = Ce; 357 PetscFunctionReturn(0); 358 } 359 360 #undef __FUNCT__ 361 #define __FUNCT__ "MatMatTransposeMult_Elemental" 362 static PetscErrorCode MatMatTransposeMult_Elemental(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 363 { 364 PetscErrorCode ierr; 365 366 PetscFunctionBegin; 367 if (scall == MAT_INITIAL_MATRIX){ 368 ierr = PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr); 369 ierr = MatMatMultSymbolic_Elemental(A,B,1.0,C);CHKERRQ(ierr); 370 ierr = PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr); 371 } 372 ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 373 ierr = MatMatTransposeMultNumeric_Elemental(A,B,*C);CHKERRQ(ierr); 374 ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 375 PetscFunctionReturn(0); 376 } 377 378 #undef __FUNCT__ 379 #define __FUNCT__ "MatGetDiagonal_Elemental" 380 static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D) 381 { 382 PetscInt i,nrows,ncols,nD,rrank,ridx,crank,cidx; 383 Mat_Elemental *a = (Mat_Elemental*)A->data; 384 PetscErrorCode ierr; 385 PetscElemScalar v; 386 MPI_Comm comm; 387 388 PetscFunctionBegin; 389 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 390 ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr); 391 nD = nrows>ncols ? ncols : nrows; 392 for (i=0; i<nD; i++) { 393 PetscInt erow,ecol; 394 P2RO(A,0,i,&rrank,&ridx); 395 RO2E(A,0,rrank,ridx,&erow); 396 if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation"); 397 P2RO(A,1,i,&crank,&cidx); 398 RO2E(A,1,crank,cidx,&ecol); 399 if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation"); 400 v = a->emat->Get(erow,ecol); 401 ierr = VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES);CHKERRQ(ierr); 402 } 403 ierr = VecAssemblyBegin(D);CHKERRQ(ierr); 404 ierr = VecAssemblyEnd(D);CHKERRQ(ierr); 405 PetscFunctionReturn(0); 406 } 407 408 #undef __FUNCT__ 409 #define __FUNCT__ "MatDiagonalScale_Elemental" 410 static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R) 411 { 412 Mat_Elemental *x = (Mat_Elemental*)X->data; 413 const PetscElemScalar *d; 414 PetscErrorCode ierr; 415 416 PetscFunctionBegin; 417 if (R) { 418 ierr = VecGetArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr); 419 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> de(X->cmap->N,1,0,d,X->cmap->n,*x->grid); 420 elem::DiagonalScale(elem::RIGHT,elem::NORMAL,de,*x->emat); 421 ierr = VecRestoreArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr); 422 } 423 if (L) { 424 ierr = VecGetArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr); 425 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> de(X->rmap->N,1,0,d,X->rmap->n,*x->grid); 426 elem::DiagonalScale(elem::LEFT,elem::NORMAL,de,*x->emat); 427 ierr = VecRestoreArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr); 428 } 429 PetscFunctionReturn(0); 430 } 431 432 #undef __FUNCT__ 433 #define __FUNCT__ "MatScale_Elemental" 434 static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a) 435 { 436 Mat_Elemental *x = (Mat_Elemental*)X->data; 437 438 PetscFunctionBegin; 439 elem::Scal((PetscElemScalar)a,*x->emat); 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "MatAXPY_Elemental" 445 static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str) 446 { 447 Mat_Elemental *x = (Mat_Elemental*)X->data; 448 Mat_Elemental *y = (Mat_Elemental*)Y->data; 449 450 PetscFunctionBegin; 451 elem::Axpy((PetscElemScalar)a,*x->emat,*y->emat); 452 PetscFunctionReturn(0); 453 } 454 455 #undef __FUNCT__ 456 #define __FUNCT__ "MatCopy_Elemental" 457 static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str) 458 { 459 Mat_Elemental *a=(Mat_Elemental*)A->data; 460 Mat_Elemental *b=(Mat_Elemental*)B->data; 461 462 PetscFunctionBegin; 463 elem::Copy(*a->emat,*b->emat); 464 PetscFunctionReturn(0); 465 } 466 467 #undef __FUNCT__ 468 #define __FUNCT__ "MatDuplicate_Elemental" 469 static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B) 470 { 471 Mat Be; 472 MPI_Comm comm; 473 Mat_Elemental *a=(Mat_Elemental*)A->data; 474 PetscErrorCode ierr; 475 476 PetscFunctionBegin; 477 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 478 ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 479 ierr = MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 480 ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 481 ierr = MatSetUp(Be);CHKERRQ(ierr); 482 *B = Be; 483 if (op == MAT_COPY_VALUES) { 484 Mat_Elemental *b=(Mat_Elemental*)Be->data; 485 elem::Copy(*a->emat,*b->emat); 486 } 487 Be->assembled = PETSC_TRUE; 488 PetscFunctionReturn(0); 489 } 490 491 #undef __FUNCT__ 492 #define __FUNCT__ "MatTranspose_Elemental" 493 static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 494 { 495 Mat Be; 496 PetscErrorCode ierr; 497 MPI_Comm comm; 498 Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 499 500 PetscFunctionBegin; 501 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 502 /* Only out-of-place supported */ 503 if (reuse == MAT_INITIAL_MATRIX){ 504 ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 505 ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 506 ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 507 ierr = MatSetUp(Be);CHKERRQ(ierr); 508 *B = Be; 509 } 510 b = (Mat_Elemental*)Be->data; 511 elem::Transpose(*a->emat,*b->emat); 512 Be->assembled = PETSC_TRUE; 513 PetscFunctionReturn(0); 514 } 515 516 #undef __FUNCT__ 517 #define __FUNCT__ "MatConjugate_Elemental" 518 static PetscErrorCode MatConjugate_Elemental(Mat A) 519 { 520 Mat_Elemental *a = (Mat_Elemental*)A->data; 521 522 PetscFunctionBegin; 523 elem::Conjugate(*a->emat); 524 PetscFunctionReturn(0); 525 } 526 527 #undef __FUNCT__ 528 #define __FUNCT__ "MatHermitianTranspose_Elemental" 529 static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 530 { 531 Mat Be; 532 PetscErrorCode ierr; 533 MPI_Comm comm; 534 Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 535 536 PetscFunctionBegin; 537 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 538 /* Only out-of-place supported */ 539 if (reuse == MAT_INITIAL_MATRIX){ 540 ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 541 ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 542 ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 543 ierr = MatSetUp(Be);CHKERRQ(ierr); 544 *B = Be; 545 } 546 b = (Mat_Elemental*)Be->data; 547 elem::Adjoint(*a->emat,*b->emat); 548 Be->assembled = PETSC_TRUE; 549 PetscFunctionReturn(0); 550 } 551 552 #undef __FUNCT__ 553 #define __FUNCT__ "MatSolve_Elemental" 554 static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X) 555 { 556 Mat_Elemental *a = (Mat_Elemental*)A->data; 557 PetscErrorCode ierr; 558 PetscElemScalar *x; 559 560 PetscFunctionBegin; 561 ierr = VecCopy(B,X);CHKERRQ(ierr); 562 ierr = VecGetArray(X,(PetscScalar **)&x);CHKERRQ(ierr); 563 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> xe(A->rmap->N,1,0,x,A->rmap->n,*a->grid); 564 elem::DistMatrix<PetscElemScalar,elem::MC,elem::MR> xer = xe; 565 switch (A->factortype) { 566 case MAT_FACTOR_LU: 567 if ((*a->pivot).AllocatedMemory()) { 568 elem::SolveAfterLU(elem::NORMAL,*a->emat,*a->pivot,xer); 569 elem::Copy(xer,xe); 570 } else { 571 elem::SolveAfterLU(elem::NORMAL,*a->emat,xer); 572 elem::Copy(xer,xe); 573 } 574 break; 575 case MAT_FACTOR_CHOLESKY: 576 elem::SolveAfterCholesky(elem::UPPER,elem::NORMAL,*a->emat,xer); 577 elem::Copy(xer,xe); 578 break; 579 default: 580 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 581 break; 582 } 583 ierr = VecRestoreArray(X,(PetscScalar **)&x);CHKERRQ(ierr); 584 PetscFunctionReturn(0); 585 } 586 587 #undef __FUNCT__ 588 #define __FUNCT__ "MatSolveAdd_Elemental" 589 static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X) 590 { 591 PetscErrorCode ierr; 592 593 PetscFunctionBegin; 594 ierr = MatSolve_Elemental(A,B,X);CHKERRQ(ierr); 595 ierr = VecAXPY(X,1,Y);CHKERRQ(ierr); 596 PetscFunctionReturn(0); 597 } 598 599 #undef __FUNCT__ 600 #define __FUNCT__ "MatMatSolve_Elemental" 601 static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X) 602 { 603 Mat_Elemental *a=(Mat_Elemental*)A->data; 604 Mat_Elemental *b=(Mat_Elemental*)B->data; 605 Mat_Elemental *x=(Mat_Elemental*)X->data; 606 607 PetscFunctionBegin; 608 elem::Copy(*b->emat,*x->emat); 609 switch (A->factortype) { 610 case MAT_FACTOR_LU: 611 if ((*a->pivot).AllocatedMemory()) { 612 elem::SolveAfterLU(elem::NORMAL,*a->emat,*a->pivot,*x->emat); 613 } else { 614 elem::SolveAfterLU(elem::NORMAL,*a->emat,*x->emat); 615 } 616 break; 617 case MAT_FACTOR_CHOLESKY: 618 elem::SolveAfterCholesky(elem::UPPER,elem::NORMAL,*a->emat,*x->emat); 619 break; 620 default: 621 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 622 break; 623 } 624 PetscFunctionReturn(0); 625 } 626 627 #undef __FUNCT__ 628 #define __FUNCT__ "MatLUFactor_Elemental" 629 static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info) 630 { 631 Mat_Elemental *a = (Mat_Elemental*)A->data; 632 633 PetscFunctionBegin; 634 if (info->dtcol){ 635 elem::LU(*a->emat,*a->pivot); 636 } else { 637 elem::LU(*a->emat); 638 } 639 A->factortype = MAT_FACTOR_LU; 640 A->assembled = PETSC_TRUE; 641 PetscFunctionReturn(0); 642 } 643 644 #undef __FUNCT__ 645 #define __FUNCT__ "MatLUFactorNumeric_Elemental" 646 static PetscErrorCode MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 647 { 648 PetscErrorCode ierr; 649 650 PetscFunctionBegin; 651 ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 652 ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr); 653 PetscFunctionReturn(0); 654 } 655 656 #undef __FUNCT__ 657 #define __FUNCT__ "MatLUFactorSymbolic_Elemental" 658 static PetscErrorCode MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 659 { 660 PetscFunctionBegin; 661 /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 662 PetscFunctionReturn(0); 663 } 664 665 #undef __FUNCT__ 666 #define __FUNCT__ "MatCholeskyFactor_Elemental" 667 static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info) 668 { 669 Mat_Elemental *a = (Mat_Elemental*)A->data; 670 elem::DistMatrix<PetscElemScalar,elem::MC,elem::STAR> d; 671 672 PetscFunctionBegin; 673 elem::Cholesky(elem::UPPER,*a->emat); 674 A->factortype = MAT_FACTOR_CHOLESKY; 675 A->assembled = PETSC_TRUE; 676 PetscFunctionReturn(0); 677 } 678 679 #undef __FUNCT__ 680 #define __FUNCT__ "MatCholeskyFactorNumeric_Elemental" 681 static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 682 { 683 PetscErrorCode ierr; 684 685 PetscFunctionBegin; 686 ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 687 ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr); 688 PetscFunctionReturn(0); 689 } 690 691 #undef __FUNCT__ 692 #define __FUNCT__ "MatCholeskyFactorSymbolic_Elemental" 693 static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info) 694 { 695 PetscFunctionBegin; 696 /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 697 PetscFunctionReturn(0); 698 } 699 700 #undef __FUNCT__ 701 #define __FUNCT__ "MatFactorGetSolverPackage_elemental_elemental" 702 PetscErrorCode MatFactorGetSolverPackage_elemental_elemental(Mat A,const MatSolverPackage *type) 703 { 704 PetscFunctionBegin; 705 *type = MATSOLVERELEMENTAL; 706 PetscFunctionReturn(0); 707 } 708 709 #undef __FUNCT__ 710 #define __FUNCT__ "MatGetFactor_elemental_elemental" 711 static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F) 712 { 713 Mat B; 714 PetscErrorCode ierr; 715 716 PetscFunctionBegin; 717 /* Create the factorization matrix */ 718 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 719 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 720 ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr); 721 ierr = MatSetUp(B);CHKERRQ(ierr); 722 B->factortype = ftype; 723 ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverPackage_C",MatFactorGetSolverPackage_elemental_elemental);CHKERRQ(ierr); 724 *F = B; 725 PetscFunctionReturn(0); 726 } 727 728 #undef __FUNCT__ 729 #define __FUNCT__ "MatNorm_Elemental" 730 static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm) 731 { 732 Mat_Elemental *a=(Mat_Elemental*)A->data; 733 734 PetscFunctionBegin; 735 switch (type){ 736 case NORM_1: 737 *nrm = elem::Norm(*a->emat,elem::ONE_NORM); 738 break; 739 case NORM_FROBENIUS: 740 *nrm = elem::Norm(*a->emat,elem::FROBENIUS_NORM); 741 break; 742 case NORM_INFINITY: 743 *nrm = elem::Norm(*a->emat,elem::INFINITY_NORM); 744 break; 745 default: 746 printf("Error: unsupported norm type!\n"); 747 } 748 PetscFunctionReturn(0); 749 } 750 751 #undef __FUNCT__ 752 #define __FUNCT__ "MatZeroEntries_Elemental" 753 static PetscErrorCode MatZeroEntries_Elemental(Mat A) 754 { 755 Mat_Elemental *a=(Mat_Elemental*)A->data; 756 757 PetscFunctionBegin; 758 elem::Zero(*a->emat); 759 PetscFunctionReturn(0); 760 } 761 762 #undef __FUNCT__ 763 #define __FUNCT__ "MatGetOwnershipIS_Elemental" 764 static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols) 765 { 766 Mat_Elemental *a = (Mat_Elemental*)A->data; 767 PetscErrorCode ierr; 768 PetscInt i,m,shift,stride,*idx; 769 770 PetscFunctionBegin; 771 if (rows) { 772 m = a->emat->LocalHeight(); 773 shift = a->emat->ColShift(); 774 stride = a->emat->ColStride(); 775 ierr = PetscMalloc(m*sizeof(PetscInt),&idx);CHKERRQ(ierr); 776 for (i=0; i<m; i++) { 777 PetscInt rank,offset; 778 E2RO(A,0,shift+i*stride,&rank,&offset); 779 RO2P(A,0,rank,offset,&idx[i]); 780 } 781 ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr); 782 } 783 if (cols) { 784 m = a->emat->LocalWidth(); 785 shift = a->emat->RowShift(); 786 stride = a->emat->RowStride(); 787 ierr = PetscMalloc(m*sizeof(PetscInt),&idx);CHKERRQ(ierr); 788 for (i=0; i<m; i++) { 789 PetscInt rank,offset; 790 E2RO(A,1,shift+i*stride,&rank,&offset); 791 RO2P(A,1,rank,offset,&idx[i]); 792 } 793 ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr); 794 } 795 PetscFunctionReturn(0); 796 } 797 798 #undef __FUNCT__ 799 #define __FUNCT__ "MatConvert_Elemental_Dense" 800 static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B) 801 { 802 Mat Bmpi; 803 Mat_Elemental *a = (Mat_Elemental*)A->data; 804 MPI_Comm comm; 805 PetscErrorCode ierr; 806 PetscInt rrank,ridx,crank,cidx,nrows,ncols,i,j; 807 PetscElemScalar v; 808 PetscBool s1,s2,s3; 809 810 PetscFunctionBegin; 811 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 812 ierr = PetscStrcmp(newtype,MATDENSE,&s1);CHKERRQ(ierr); 813 ierr = PetscStrcmp(newtype,MATSEQDENSE,&s2);CHKERRQ(ierr); 814 ierr = PetscStrcmp(newtype,MATMPIDENSE,&s3);CHKERRQ(ierr); 815 if (!s1 && !s2 && !s3) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported New MatType: must be MATDENSE, MATSEQDENSE or MATMPIDENSE"); 816 ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr); 817 ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 818 ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr); 819 ierr = MatSetUp(Bmpi);CHKERRQ(ierr); 820 ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr); 821 for (i=0; i<nrows; i++) { 822 PetscInt erow,ecol; 823 P2RO(A,0,i,&rrank,&ridx); 824 RO2E(A,0,rrank,ridx,&erow); 825 if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation"); 826 for (j=0; j<ncols; j++) { 827 P2RO(A,1,j,&crank,&cidx); 828 RO2E(A,1,crank,cidx,&ecol); 829 if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation"); 830 v = a->emat->Get(erow,ecol); 831 ierr = MatSetValues(Bmpi,1,&i,1,&j,(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr); 832 } 833 } 834 ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 835 ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 836 if (reuse == MAT_REUSE_MATRIX) { 837 ierr = MatHeaderReplace(A,Bmpi);CHKERRQ(ierr); 838 } else { 839 *B = Bmpi; 840 } 841 PetscFunctionReturn(0); 842 } 843 844 #undef __FUNCT__ 845 #define __FUNCT__ "MatDestroy_Elemental" 846 static PetscErrorCode MatDestroy_Elemental(Mat A) 847 { 848 Mat_Elemental *a = (Mat_Elemental*)A->data; 849 PetscErrorCode ierr; 850 Mat_Elemental_Grid *commgrid; 851 PetscBool flg; 852 MPI_Comm icomm; 853 854 PetscFunctionBegin; 855 a->interface->Detach(); 856 delete a->interface; 857 delete a->esubmat; 858 delete a->emat; 859 860 elem::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 861 ierr = PetscCommDuplicate(cxxcomm,&icomm,NULL);CHKERRQ(ierr); 862 ierr = MPI_Attr_get(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr); 863 if (--commgrid->grid_refct == 0) { 864 delete commgrid->grid; 865 ierr = PetscFree(commgrid);CHKERRQ(ierr); 866 } 867 ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr); 868 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL);CHKERRQ(ierr); 869 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetFactor_petsc_C",NULL);CHKERRQ(ierr); 870 ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverPackage_C",NULL);CHKERRQ(ierr); 871 ierr = PetscFree(A->data);CHKERRQ(ierr); 872 PetscFunctionReturn(0); 873 } 874 875 #undef __FUNCT__ 876 #define __FUNCT__ "MatSetUp_Elemental" 877 PetscErrorCode MatSetUp_Elemental(Mat A) 878 { 879 Mat_Elemental *a = (Mat_Elemental*)A->data; 880 PetscErrorCode ierr; 881 PetscMPIInt rsize,csize; 882 883 PetscFunctionBegin; 884 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 885 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 886 887 a->emat->ResizeTo(A->rmap->N,A->cmap->N);CHKERRQ(ierr); 888 elem::Zero(*a->emat); 889 890 ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRQ(ierr); 891 ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRQ(ierr); 892 if (csize != rsize) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes"); 893 a->commsize = rsize; 894 a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize; 895 a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize; 896 a->m[0] = A->rmap->N / rsize + (a->mr[0] != rsize); 897 a->m[1] = A->cmap->N / csize + (a->mr[1] != csize); 898 PetscFunctionReturn(0); 899 } 900 901 #undef __FUNCT__ 902 #define __FUNCT__ "MatAssemblyBegin_Elemental" 903 PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type) 904 { 905 Mat_Elemental *a = (Mat_Elemental*)A->data; 906 907 PetscFunctionBegin; 908 a->interface->Detach(); 909 a->interface->Attach(elem::LOCAL_TO_GLOBAL,*(a->emat)); 910 PetscFunctionReturn(0); 911 } 912 913 #undef __FUNCT__ 914 #define __FUNCT__ "MatAssemblyEnd_Elemental" 915 PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type) 916 { 917 PetscFunctionBegin; 918 /* Currently does nothing */ 919 PetscFunctionReturn(0); 920 } 921 922 /* -------------------------------------------------------------------*/ 923 static struct _MatOps MatOps_Values = { 924 MatSetValues_Elemental, 925 0, 926 0, 927 MatMult_Elemental, 928 /* 4*/ MatMultAdd_Elemental, 929 MatMultTranspose_Elemental, 930 MatMultTransposeAdd_Elemental, 931 MatSolve_Elemental, 932 MatSolveAdd_Elemental, 933 0, //MatSolveTranspose_Elemental, 934 /*10*/ 0, //MatSolveTransposeAdd_Elemental, 935 MatLUFactor_Elemental, 936 MatCholeskyFactor_Elemental, 937 0, 938 MatTranspose_Elemental, 939 /*15*/ MatGetInfo_Elemental, 940 0, 941 MatGetDiagonal_Elemental, 942 MatDiagonalScale_Elemental, 943 MatNorm_Elemental, 944 /*20*/ MatAssemblyBegin_Elemental, 945 MatAssemblyEnd_Elemental, 946 0, //MatSetOption_Elemental, 947 MatZeroEntries_Elemental, 948 /*24*/ 0, 949 MatLUFactorSymbolic_Elemental, 950 MatLUFactorNumeric_Elemental, 951 MatCholeskyFactorSymbolic_Elemental, 952 MatCholeskyFactorNumeric_Elemental, 953 /*29*/ MatSetUp_Elemental, 954 0, 955 0, 956 0, 957 0, 958 /*34*/ MatDuplicate_Elemental, 959 0, 960 0, 961 0, 962 0, 963 /*39*/ MatAXPY_Elemental, 964 0, 965 0, 966 0, 967 MatCopy_Elemental, 968 /*44*/ 0, 969 MatScale_Elemental, 970 0, 971 0, 972 0, 973 /*49*/ 0, 974 0, 975 0, 976 0, 977 0, 978 /*54*/ 0, 979 0, 980 0, 981 0, 982 0, 983 /*59*/ 0, 984 MatDestroy_Elemental, 985 MatView_Elemental, 986 0, 987 0, 988 /*64*/ 0, 989 0, 990 0, 991 0, 992 0, 993 /*69*/ 0, 994 0, 995 MatConvert_Elemental_Dense, 996 0, 997 0, 998 /*74*/ 0, 999 0, 1000 0, 1001 0, 1002 0, 1003 /*79*/ 0, 1004 0, 1005 0, 1006 0, 1007 0, 1008 /*84*/ 0, 1009 0, 1010 0, 1011 0, 1012 0, 1013 /*89*/ MatMatMult_Elemental, 1014 MatMatMultSymbolic_Elemental, 1015 MatMatMultNumeric_Elemental, 1016 0, 1017 0, 1018 /*94*/ 0, 1019 MatMatTransposeMult_Elemental, 1020 MatMatTransposeMultSymbolic_Elemental, 1021 MatMatTransposeMultNumeric_Elemental, 1022 0, 1023 /*99*/ 0, 1024 0, 1025 0, 1026 MatConjugate_Elemental, 1027 0, 1028 /*104*/0, 1029 0, 1030 0, 1031 0, 1032 0, 1033 /*109*/MatMatSolve_Elemental, 1034 0, 1035 0, 1036 0, 1037 0, 1038 /*114*/0, 1039 0, 1040 0, 1041 0, 1042 0, 1043 /*119*/0, 1044 MatHermitianTranspose_Elemental, 1045 0, 1046 0, 1047 0, 1048 /*124*/0, 1049 0, 1050 0, 1051 0, 1052 0, 1053 /*129*/0, 1054 0, 1055 0, 1056 0, 1057 0, 1058 /*134*/0, 1059 0, 1060 0, 1061 0, 1062 0 1063 }; 1064 1065 /*MC 1066 MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package 1067 1068 Options Database Keys: 1069 . -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions() 1070 . -mat_elemental_grid_height - sets Grid Height 1071 . -mat_elemental_grid_width - sets Grid Width 1072 1073 Level: beginner 1074 1075 .seealso: MATDENSE 1076 M*/ 1077 1078 #undef __FUNCT__ 1079 #define __FUNCT__ "MatCreate_Elemental" 1080 PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A) 1081 { 1082 Mat_Elemental *a; 1083 PetscErrorCode ierr; 1084 PetscBool flg,flg1,flg2; 1085 Mat_Elemental_Grid *commgrid; 1086 MPI_Comm icomm; 1087 PetscInt optv1,optv2; 1088 1089 PetscFunctionBegin; 1090 ierr = PetscElementalInitializePackage();CHKERRQ(ierr); 1091 ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 1092 A->insertmode = NOT_SET_VALUES; 1093 1094 ierr = PetscNewLog(A,Mat_Elemental,&a);CHKERRQ(ierr); 1095 A->data = (void*)a; 1096 1097 /* Set up the elemental matrix */ 1098 elem::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 1099 1100 /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */ 1101 if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) { 1102 ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0); 1103 } 1104 ierr = PetscCommDuplicate(cxxcomm,&icomm,NULL);CHKERRQ(ierr); 1105 ierr = MPI_Attr_get(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr); 1106 if (!flg) { 1107 ierr = PetscNewLog(A,Mat_Elemental_Grid,&commgrid);CHKERRQ(ierr); 1108 1109 ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr); 1110 /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until elem::Grid() is called */ 1111 ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",elem::mpi::CommSize(cxxcomm),&optv1,&flg1);CHKERRQ(ierr); 1112 ierr = PetscOptionsInt("-mat_elemental_grid_width","Grid Width","None",1,&optv2,&flg2);CHKERRQ(ierr); 1113 if (flg1 || flg2) { 1114 if (optv1*optv2 != elem::mpi::CommSize(cxxcomm)) { 1115 SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Grid Height times Grid Width must equal CommSize"); 1116 } 1117 commgrid->grid = new elem::Grid(cxxcomm,optv1,optv2); /* use user-provided grid sizes */ 1118 } else { 1119 commgrid->grid = new elem::Grid(cxxcomm); /* use Elemental default grid sizes */ 1120 } 1121 commgrid->grid_refct = 1; 1122 ierr = MPI_Attr_put(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRQ(ierr); 1123 PetscOptionsEnd(); 1124 } else { 1125 commgrid->grid_refct++; 1126 } 1127 ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr); 1128 a->grid = commgrid->grid; 1129 a->emat = new elem::DistMatrix<PetscElemScalar>(*a->grid); 1130 a->esubmat = new elem::Matrix<PetscElemScalar>(1,1); 1131 a->interface = new elem::AxpyInterface<PetscElemScalar>; 1132 a->pivot = new elem::DistMatrix<PetscInt,elem::VC,elem::STAR>; 1133 1134 /* build cache for off array entries formed */ 1135 a->interface->Attach(elem::LOCAL_TO_GLOBAL,*(a->emat)); 1136 1137 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental);CHKERRQ(ierr); 1138 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetFactor_elemental_C",MatGetFactor_elemental_elemental);CHKERRQ(ierr); 1139 1140 ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr); 1141 PetscFunctionReturn(0); 1142 } 1143 1144