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 = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 320 ierr = MatMatMultSymbolic_Elemental(A,B,1.0,C);CHKERRQ(ierr); 321 ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 322 } 323 ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 324 ierr = MatMatMultNumeric_Elemental(A,B,*C);CHKERRQ(ierr); 325 ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 326 PetscFunctionReturn(0); 327 } 328 329 #undef __FUNCT__ 330 #define __FUNCT__ "MatMatTransposeMultNumeric_Elemental" 331 static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A,Mat B,Mat C) 332 { 333 Mat_Elemental *a = (Mat_Elemental*)A->data; 334 Mat_Elemental *b = (Mat_Elemental*)B->data; 335 Mat_Elemental *c = (Mat_Elemental*)C->data; 336 PetscElemScalar one = 1,zero = 0; 337 338 PetscFunctionBegin; 339 { /* Scoping so that constructor is called before pointer is returned */ 340 elem::Gemm(elem::NORMAL,elem::TRANSPOSE,one,*a->emat,*b->emat,zero,*c->emat); 341 } 342 C->assembled = PETSC_TRUE; 343 PetscFunctionReturn(0); 344 } 345 346 #undef __FUNCT__ 347 #define __FUNCT__ "MatMatTransposeMultSymbolic_Elemental" 348 static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat *C) 349 { 350 PetscErrorCode ierr; 351 Mat Ce; 352 MPI_Comm comm; 353 354 PetscFunctionBegin; 355 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 356 ierr = MatCreate(comm,&Ce);CHKERRQ(ierr); 357 ierr = MatSetSizes(Ce,A->rmap->n,B->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 358 ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr); 359 ierr = MatSetUp(Ce);CHKERRQ(ierr); 360 *C = Ce; 361 PetscFunctionReturn(0); 362 } 363 364 #undef __FUNCT__ 365 #define __FUNCT__ "MatMatTransposeMult_Elemental" 366 static PetscErrorCode MatMatTransposeMult_Elemental(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 367 { 368 PetscErrorCode ierr; 369 370 PetscFunctionBegin; 371 if (scall == MAT_INITIAL_MATRIX){ 372 ierr = PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr); 373 ierr = MatMatMultSymbolic_Elemental(A,B,1.0,C);CHKERRQ(ierr); 374 ierr = PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr); 375 } 376 ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 377 ierr = MatMatTransposeMultNumeric_Elemental(A,B,*C);CHKERRQ(ierr); 378 ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr); 379 PetscFunctionReturn(0); 380 } 381 382 #undef __FUNCT__ 383 #define __FUNCT__ "MatGetDiagonal_Elemental" 384 static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D) 385 { 386 PetscInt i,nrows,ncols,nD,rrank,ridx,crank,cidx; 387 Mat_Elemental *a = (Mat_Elemental*)A->data; 388 PetscErrorCode ierr; 389 PetscElemScalar v; 390 MPI_Comm comm; 391 392 PetscFunctionBegin; 393 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 394 ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr); 395 nD = nrows>ncols ? ncols : nrows; 396 for (i=0; i<nD; i++) { 397 PetscInt erow,ecol; 398 P2RO(A,0,i,&rrank,&ridx); 399 RO2E(A,0,rrank,ridx,&erow); 400 if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation"); 401 P2RO(A,1,i,&crank,&cidx); 402 RO2E(A,1,crank,cidx,&ecol); 403 if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation"); 404 v = a->emat->Get(erow,ecol); 405 ierr = VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES);CHKERRQ(ierr); 406 } 407 ierr = VecAssemblyBegin(D);CHKERRQ(ierr); 408 ierr = VecAssemblyEnd(D);CHKERRQ(ierr); 409 PetscFunctionReturn(0); 410 } 411 412 #undef __FUNCT__ 413 #define __FUNCT__ "MatDiagonalScale_Elemental" 414 static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R) 415 { 416 Mat_Elemental *x = (Mat_Elemental*)X->data; 417 const PetscElemScalar *d; 418 PetscErrorCode ierr; 419 420 PetscFunctionBegin; 421 if (R) { 422 ierr = VecGetArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr); 423 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> de(X->cmap->N,1,0,d,X->cmap->n,*x->grid); 424 elem::DiagonalScale(elem::RIGHT,elem::NORMAL,de,*x->emat); 425 ierr = VecRestoreArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr); 426 } 427 if (L) { 428 ierr = VecGetArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr); 429 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> de(X->rmap->N,1,0,d,X->rmap->n,*x->grid); 430 elem::DiagonalScale(elem::LEFT,elem::NORMAL,de,*x->emat); 431 ierr = VecRestoreArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr); 432 } 433 PetscFunctionReturn(0); 434 } 435 436 #undef __FUNCT__ 437 #define __FUNCT__ "MatScale_Elemental" 438 static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a) 439 { 440 Mat_Elemental *x = (Mat_Elemental*)X->data; 441 442 PetscFunctionBegin; 443 elem::Scal((PetscElemScalar)a,*x->emat); 444 PetscFunctionReturn(0); 445 } 446 447 #undef __FUNCT__ 448 #define __FUNCT__ "MatAXPY_Elemental" 449 static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str) 450 { 451 Mat_Elemental *x = (Mat_Elemental*)X->data; 452 Mat_Elemental *y = (Mat_Elemental*)Y->data; 453 454 PetscFunctionBegin; 455 elem::Axpy((PetscElemScalar)a,*x->emat,*y->emat); 456 PetscFunctionReturn(0); 457 } 458 459 #undef __FUNCT__ 460 #define __FUNCT__ "MatCopy_Elemental" 461 static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str) 462 { 463 Mat_Elemental *a=(Mat_Elemental*)A->data; 464 Mat_Elemental *b=(Mat_Elemental*)B->data; 465 466 PetscFunctionBegin; 467 elem::Copy(*a->emat,*b->emat); 468 PetscFunctionReturn(0); 469 } 470 471 #undef __FUNCT__ 472 #define __FUNCT__ "MatDuplicate_Elemental" 473 static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B) 474 { 475 Mat Be; 476 MPI_Comm comm; 477 Mat_Elemental *a=(Mat_Elemental*)A->data; 478 PetscErrorCode ierr; 479 480 PetscFunctionBegin; 481 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 482 ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 483 ierr = MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 484 ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 485 ierr = MatSetUp(Be);CHKERRQ(ierr); 486 *B = Be; 487 if (op == MAT_COPY_VALUES) { 488 Mat_Elemental *b=(Mat_Elemental*)Be->data; 489 elem::Copy(*a->emat,*b->emat); 490 } 491 Be->assembled = PETSC_TRUE; 492 PetscFunctionReturn(0); 493 } 494 495 #undef __FUNCT__ 496 #define __FUNCT__ "MatTranspose_Elemental" 497 static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 498 { 499 Mat Be; 500 PetscErrorCode ierr; 501 MPI_Comm comm; 502 Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 503 504 PetscFunctionBegin; 505 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 506 /* Only out-of-place supported */ 507 if (reuse == MAT_INITIAL_MATRIX){ 508 ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 509 ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 510 ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 511 ierr = MatSetUp(Be);CHKERRQ(ierr); 512 *B = Be; 513 } 514 b = (Mat_Elemental*)Be->data; 515 elem::Transpose(*a->emat,*b->emat); 516 Be->assembled = PETSC_TRUE; 517 PetscFunctionReturn(0); 518 } 519 520 #undef __FUNCT__ 521 #define __FUNCT__ "MatConjugate_Elemental" 522 static PetscErrorCode MatConjugate_Elemental(Mat A) 523 { 524 Mat_Elemental *a = (Mat_Elemental*)A->data; 525 526 PetscFunctionBegin; 527 elem::Conjugate(*a->emat); 528 PetscFunctionReturn(0); 529 } 530 531 #undef __FUNCT__ 532 #define __FUNCT__ "MatHermitianTranspose_Elemental" 533 static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 534 { 535 Mat Be; 536 PetscErrorCode ierr; 537 MPI_Comm comm; 538 Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 539 540 PetscFunctionBegin; 541 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 542 /* Only out-of-place supported */ 543 if (reuse == MAT_INITIAL_MATRIX){ 544 ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 545 ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 546 ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 547 ierr = MatSetUp(Be);CHKERRQ(ierr); 548 *B = Be; 549 } 550 b = (Mat_Elemental*)Be->data; 551 elem::Adjoint(*a->emat,*b->emat); 552 Be->assembled = PETSC_TRUE; 553 PetscFunctionReturn(0); 554 } 555 556 #undef __FUNCT__ 557 #define __FUNCT__ "MatSolve_Elemental" 558 static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X) 559 { 560 Mat_Elemental *a = (Mat_Elemental*)A->data; 561 PetscErrorCode ierr; 562 PetscElemScalar *x; 563 564 PetscFunctionBegin; 565 ierr = VecCopy(B,X);CHKERRQ(ierr); 566 ierr = VecGetArray(X,(PetscScalar **)&x);CHKERRQ(ierr); 567 elem::DistMatrix<PetscElemScalar,elem::VC,elem::STAR> xe(A->rmap->N,1,0,x,A->rmap->n,*a->grid); 568 elem::DistMatrix<PetscElemScalar,elem::MC,elem::MR> xer = xe; 569 switch (A->factortype) { 570 case MAT_FACTOR_LU: 571 if ((*a->pivot).AllocatedMemory()) { 572 elem::lu::SolveAfter(elem::NORMAL,*a->emat,*a->pivot,xer); 573 elem::Copy(xer,xe); 574 } else { 575 elem::lu::SolveAfter(elem::NORMAL,*a->emat,xer); 576 elem::Copy(xer,xe); 577 } 578 break; 579 case MAT_FACTOR_CHOLESKY: 580 elem::cholesky::SolveAfter(elem::UPPER,elem::NORMAL,*a->emat,xer); 581 elem::Copy(xer,xe); 582 break; 583 default: 584 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 585 break; 586 } 587 ierr = VecRestoreArray(X,(PetscScalar **)&x);CHKERRQ(ierr); 588 PetscFunctionReturn(0); 589 } 590 591 #undef __FUNCT__ 592 #define __FUNCT__ "MatSolveAdd_Elemental" 593 static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X) 594 { 595 PetscErrorCode ierr; 596 597 PetscFunctionBegin; 598 ierr = MatSolve_Elemental(A,B,X);CHKERRQ(ierr); 599 ierr = VecAXPY(X,1,Y);CHKERRQ(ierr); 600 PetscFunctionReturn(0); 601 } 602 603 #undef __FUNCT__ 604 #define __FUNCT__ "MatMatSolve_Elemental" 605 static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X) 606 { 607 Mat_Elemental *a=(Mat_Elemental*)A->data; 608 Mat_Elemental *b=(Mat_Elemental*)B->data; 609 Mat_Elemental *x=(Mat_Elemental*)X->data; 610 611 PetscFunctionBegin; 612 elem::Copy(*b->emat,*x->emat); 613 switch (A->factortype) { 614 case MAT_FACTOR_LU: 615 if ((*a->pivot).AllocatedMemory()) { 616 elem::lu::SolveAfter(elem::NORMAL,*a->emat,*a->pivot,*x->emat); 617 } else { 618 elem::lu::SolveAfter(elem::NORMAL,*a->emat,*x->emat); 619 } 620 break; 621 case MAT_FACTOR_CHOLESKY: 622 elem::cholesky::SolveAfter(elem::UPPER,elem::NORMAL,*a->emat,*x->emat); 623 break; 624 default: 625 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 626 break; 627 } 628 PetscFunctionReturn(0); 629 } 630 631 #undef __FUNCT__ 632 #define __FUNCT__ "MatLUFactor_Elemental" 633 static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info) 634 { 635 Mat_Elemental *a = (Mat_Elemental*)A->data; 636 637 PetscFunctionBegin; 638 if (info->dtcol){ 639 elem::LU(*a->emat,*a->pivot); 640 } else { 641 elem::LU(*a->emat); 642 } 643 A->factortype = MAT_FACTOR_LU; 644 A->assembled = PETSC_TRUE; 645 PetscFunctionReturn(0); 646 } 647 648 #undef __FUNCT__ 649 #define __FUNCT__ "MatLUFactorNumeric_Elemental" 650 static PetscErrorCode MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 651 { 652 PetscErrorCode ierr; 653 654 PetscFunctionBegin; 655 ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 656 ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr); 657 PetscFunctionReturn(0); 658 } 659 660 #undef __FUNCT__ 661 #define __FUNCT__ "MatLUFactorSymbolic_Elemental" 662 static PetscErrorCode MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 663 { 664 PetscFunctionBegin; 665 /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 666 PetscFunctionReturn(0); 667 } 668 669 #undef __FUNCT__ 670 #define __FUNCT__ "MatCholeskyFactor_Elemental" 671 static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info) 672 { 673 Mat_Elemental *a = (Mat_Elemental*)A->data; 674 elem::DistMatrix<PetscElemScalar,elem::MC,elem::STAR> d; 675 676 PetscFunctionBegin; 677 elem::Cholesky(elem::UPPER,*a->emat); 678 A->factortype = MAT_FACTOR_CHOLESKY; 679 A->assembled = PETSC_TRUE; 680 PetscFunctionReturn(0); 681 } 682 683 #undef __FUNCT__ 684 #define __FUNCT__ "MatCholeskyFactorNumeric_Elemental" 685 static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 686 { 687 PetscErrorCode ierr; 688 689 PetscFunctionBegin; 690 ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 691 ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr); 692 PetscFunctionReturn(0); 693 } 694 695 #undef __FUNCT__ 696 #define __FUNCT__ "MatCholeskyFactorSymbolic_Elemental" 697 static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info) 698 { 699 PetscFunctionBegin; 700 /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 701 PetscFunctionReturn(0); 702 } 703 704 #undef __FUNCT__ 705 #define __FUNCT__ "MatFactorGetSolverPackage_elemental_elemental" 706 PetscErrorCode MatFactorGetSolverPackage_elemental_elemental(Mat A,const MatSolverPackage *type) 707 { 708 PetscFunctionBegin; 709 *type = MATSOLVERELEMENTAL; 710 PetscFunctionReturn(0); 711 } 712 713 #undef __FUNCT__ 714 #define __FUNCT__ "MatGetFactor_elemental_elemental" 715 static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F) 716 { 717 Mat B; 718 PetscErrorCode ierr; 719 720 PetscFunctionBegin; 721 /* Create the factorization matrix */ 722 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 723 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 724 ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr); 725 ierr = MatSetUp(B);CHKERRQ(ierr); 726 B->factortype = ftype; 727 ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverPackage_C",MatFactorGetSolverPackage_elemental_elemental);CHKERRQ(ierr); 728 *F = B; 729 PetscFunctionReturn(0); 730 } 731 732 #undef __FUNCT__ 733 #define __FUNCT__ "MatNorm_Elemental" 734 static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm) 735 { 736 Mat_Elemental *a=(Mat_Elemental*)A->data; 737 738 PetscFunctionBegin; 739 switch (type){ 740 case NORM_1: 741 *nrm = elem::OneNorm(*a->emat); 742 break; 743 case NORM_FROBENIUS: 744 *nrm = elem::FrobeniusNorm(*a->emat); 745 break; 746 case NORM_INFINITY: 747 *nrm = elem::InfinityNorm(*a->emat); 748 break; 749 default: 750 printf("Error: unsupported norm type!\n"); 751 } 752 PetscFunctionReturn(0); 753 } 754 755 #undef __FUNCT__ 756 #define __FUNCT__ "MatZeroEntries_Elemental" 757 static PetscErrorCode MatZeroEntries_Elemental(Mat A) 758 { 759 Mat_Elemental *a=(Mat_Elemental*)A->data; 760 761 PetscFunctionBegin; 762 elem::Zero(*a->emat); 763 PetscFunctionReturn(0); 764 } 765 766 #undef __FUNCT__ 767 #define __FUNCT__ "MatGetOwnershipIS_Elemental" 768 static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols) 769 { 770 Mat_Elemental *a = (Mat_Elemental*)A->data; 771 PetscErrorCode ierr; 772 PetscInt i,m,shift,stride,*idx; 773 774 PetscFunctionBegin; 775 if (rows) { 776 m = a->emat->LocalHeight(); 777 shift = a->emat->ColShift(); 778 stride = a->emat->ColStride(); 779 ierr = PetscMalloc(m*sizeof(PetscInt),&idx);CHKERRQ(ierr); 780 for (i=0; i<m; i++) { 781 PetscInt rank,offset; 782 E2RO(A,0,shift+i*stride,&rank,&offset); 783 RO2P(A,0,rank,offset,&idx[i]); 784 } 785 ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr); 786 } 787 if (cols) { 788 m = a->emat->LocalWidth(); 789 shift = a->emat->RowShift(); 790 stride = a->emat->RowStride(); 791 ierr = PetscMalloc(m*sizeof(PetscInt),&idx);CHKERRQ(ierr); 792 for (i=0; i<m; i++) { 793 PetscInt rank,offset; 794 E2RO(A,1,shift+i*stride,&rank,&offset); 795 RO2P(A,1,rank,offset,&idx[i]); 796 } 797 ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr); 798 } 799 PetscFunctionReturn(0); 800 } 801 802 #undef __FUNCT__ 803 #define __FUNCT__ "MatConvert_Elemental_Dense" 804 static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B) 805 { 806 Mat Bmpi; 807 Mat_Elemental *a = (Mat_Elemental*)A->data; 808 MPI_Comm comm; 809 PetscErrorCode ierr; 810 PetscInt rrank,ridx,crank,cidx,nrows,ncols,i,j; 811 PetscElemScalar v; 812 PetscBool s1,s2,s3; 813 814 PetscFunctionBegin; 815 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 816 ierr = PetscStrcmp(newtype,MATDENSE,&s1);CHKERRQ(ierr); 817 ierr = PetscStrcmp(newtype,MATSEQDENSE,&s2);CHKERRQ(ierr); 818 ierr = PetscStrcmp(newtype,MATMPIDENSE,&s3);CHKERRQ(ierr); 819 if (!s1 && !s2 && !s3) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported New MatType: must be MATDENSE, MATSEQDENSE or MATMPIDENSE"); 820 ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr); 821 ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 822 ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr); 823 ierr = MatSetUp(Bmpi);CHKERRQ(ierr); 824 ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr); 825 for (i=0; i<nrows; i++) { 826 PetscInt erow,ecol; 827 P2RO(A,0,i,&rrank,&ridx); 828 RO2E(A,0,rrank,ridx,&erow); 829 if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation"); 830 for (j=0; j<ncols; j++) { 831 P2RO(A,1,j,&crank,&cidx); 832 RO2E(A,1,crank,cidx,&ecol); 833 if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation"); 834 v = a->emat->Get(erow,ecol); 835 ierr = MatSetValues(Bmpi,1,&i,1,&j,(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr); 836 } 837 } 838 ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 839 ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 840 if (reuse == MAT_REUSE_MATRIX) { 841 ierr = MatHeaderReplace(A,Bmpi);CHKERRQ(ierr); 842 } else { 843 *B = Bmpi; 844 } 845 PetscFunctionReturn(0); 846 } 847 848 #undef __FUNCT__ 849 #define __FUNCT__ "MatDestroy_Elemental" 850 static PetscErrorCode MatDestroy_Elemental(Mat A) 851 { 852 Mat_Elemental *a = (Mat_Elemental*)A->data; 853 PetscErrorCode ierr; 854 Mat_Elemental_Grid *commgrid; 855 PetscBool flg; 856 MPI_Comm icomm; 857 858 PetscFunctionBegin; 859 a->interface->Detach(); 860 delete a->interface; 861 delete a->esubmat; 862 delete a->emat; 863 864 elem::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 865 ierr = PetscCommDuplicate(cxxcomm,&icomm,NULL);CHKERRQ(ierr); 866 ierr = MPI_Attr_get(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr); 867 if (--commgrid->grid_refct == 0) { 868 delete commgrid->grid; 869 ierr = PetscFree(commgrid);CHKERRQ(ierr); 870 } 871 ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr); 872 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL);CHKERRQ(ierr); 873 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetFactor_petsc_C",NULL);CHKERRQ(ierr); 874 ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverPackage_C",NULL);CHKERRQ(ierr); 875 ierr = PetscFree(A->data);CHKERRQ(ierr); 876 PetscFunctionReturn(0); 877 } 878 879 #undef __FUNCT__ 880 #define __FUNCT__ "MatSetUp_Elemental" 881 PetscErrorCode MatSetUp_Elemental(Mat A) 882 { 883 Mat_Elemental *a = (Mat_Elemental*)A->data; 884 PetscErrorCode ierr; 885 PetscMPIInt rsize,csize; 886 887 PetscFunctionBegin; 888 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 889 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 890 891 a->emat->ResizeTo(A->rmap->N,A->cmap->N);CHKERRQ(ierr); 892 elem::Zero(*a->emat); 893 894 ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRQ(ierr); 895 ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRQ(ierr); 896 if (csize != rsize) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes"); 897 a->commsize = rsize; 898 a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize; 899 a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize; 900 a->m[0] = A->rmap->N / rsize + (a->mr[0] != rsize); 901 a->m[1] = A->cmap->N / csize + (a->mr[1] != csize); 902 PetscFunctionReturn(0); 903 } 904 905 #undef __FUNCT__ 906 #define __FUNCT__ "MatAssemblyBegin_Elemental" 907 PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type) 908 { 909 Mat_Elemental *a = (Mat_Elemental*)A->data; 910 911 PetscFunctionBegin; 912 a->interface->Detach(); 913 a->interface->Attach(elem::LOCAL_TO_GLOBAL,*(a->emat)); 914 PetscFunctionReturn(0); 915 } 916 917 #undef __FUNCT__ 918 #define __FUNCT__ "MatAssemblyEnd_Elemental" 919 PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type) 920 { 921 PetscFunctionBegin; 922 /* Currently does nothing */ 923 PetscFunctionReturn(0); 924 } 925 926 /* -------------------------------------------------------------------*/ 927 static struct _MatOps MatOps_Values = { 928 MatSetValues_Elemental, 929 0, 930 0, 931 MatMult_Elemental, 932 /* 4*/ MatMultAdd_Elemental, 933 MatMultTranspose_Elemental, 934 MatMultTransposeAdd_Elemental, 935 MatSolve_Elemental, 936 MatSolveAdd_Elemental, 937 0, //MatSolveTranspose_Elemental, 938 /*10*/ 0, //MatSolveTransposeAdd_Elemental, 939 MatLUFactor_Elemental, 940 MatCholeskyFactor_Elemental, 941 0, 942 MatTranspose_Elemental, 943 /*15*/ MatGetInfo_Elemental, 944 0, 945 MatGetDiagonal_Elemental, 946 MatDiagonalScale_Elemental, 947 MatNorm_Elemental, 948 /*20*/ MatAssemblyBegin_Elemental, 949 MatAssemblyEnd_Elemental, 950 0, //MatSetOption_Elemental, 951 MatZeroEntries_Elemental, 952 /*24*/ 0, 953 MatLUFactorSymbolic_Elemental, 954 MatLUFactorNumeric_Elemental, 955 MatCholeskyFactorSymbolic_Elemental, 956 MatCholeskyFactorNumeric_Elemental, 957 /*29*/ MatSetUp_Elemental, 958 0, 959 0, 960 0, 961 0, 962 /*34*/ MatDuplicate_Elemental, 963 0, 964 0, 965 0, 966 0, 967 /*39*/ MatAXPY_Elemental, 968 0, 969 0, 970 0, 971 MatCopy_Elemental, 972 /*44*/ 0, 973 MatScale_Elemental, 974 0, 975 0, 976 0, 977 /*49*/ 0, 978 0, 979 0, 980 0, 981 0, 982 /*54*/ 0, 983 0, 984 0, 985 0, 986 0, 987 /*59*/ 0, 988 MatDestroy_Elemental, 989 MatView_Elemental, 990 0, 991 0, 992 /*64*/ 0, 993 0, 994 0, 995 0, 996 0, 997 /*69*/ 0, 998 0, 999 MatConvert_Elemental_Dense, 1000 0, 1001 0, 1002 /*74*/ 0, 1003 0, 1004 0, 1005 0, 1006 0, 1007 /*79*/ 0, 1008 0, 1009 0, 1010 0, 1011 0, 1012 /*84*/ 0, 1013 0, 1014 0, 1015 0, 1016 0, 1017 /*89*/ MatMatMult_Elemental, 1018 MatMatMultSymbolic_Elemental, 1019 MatMatMultNumeric_Elemental, 1020 0, 1021 0, 1022 /*94*/ 0, 1023 MatMatTransposeMult_Elemental, 1024 MatMatTransposeMultSymbolic_Elemental, 1025 MatMatTransposeMultNumeric_Elemental, 1026 0, 1027 /*99*/ 0, 1028 0, 1029 0, 1030 MatConjugate_Elemental, 1031 0, 1032 /*104*/0, 1033 0, 1034 0, 1035 0, 1036 0, 1037 /*109*/MatMatSolve_Elemental, 1038 0, 1039 0, 1040 0, 1041 0, 1042 /*114*/0, 1043 0, 1044 0, 1045 0, 1046 0, 1047 /*119*/0, 1048 MatHermitianTranspose_Elemental, 1049 0, 1050 0, 1051 0, 1052 /*124*/0, 1053 0, 1054 0, 1055 0, 1056 0, 1057 /*129*/0, 1058 0, 1059 0, 1060 0, 1061 0, 1062 /*134*/0, 1063 0, 1064 0, 1065 0, 1066 0 1067 }; 1068 1069 /*MC 1070 MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package 1071 1072 Options Database Keys: 1073 . -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions() 1074 . -mat_elemental_grid_height - sets Grid Height 1075 . -mat_elemental_grid_width - sets Grid Width 1076 1077 Level: beginner 1078 1079 .seealso: MATDENSE 1080 M*/ 1081 1082 #undef __FUNCT__ 1083 #define __FUNCT__ "MatCreate_Elemental" 1084 PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A) 1085 { 1086 Mat_Elemental *a; 1087 PetscErrorCode ierr; 1088 PetscBool flg,flg1,flg2; 1089 Mat_Elemental_Grid *commgrid; 1090 MPI_Comm icomm; 1091 PetscInt optv1,optv2; 1092 1093 PetscFunctionBegin; 1094 ierr = PetscElementalInitializePackage();CHKERRQ(ierr); 1095 ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 1096 A->insertmode = NOT_SET_VALUES; 1097 1098 ierr = PetscNewLog(A,Mat_Elemental,&a);CHKERRQ(ierr); 1099 A->data = (void*)a; 1100 1101 /* Set up the elemental matrix */ 1102 elem::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 1103 1104 /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */ 1105 if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) { 1106 ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0); 1107 } 1108 ierr = PetscCommDuplicate(cxxcomm,&icomm,NULL);CHKERRQ(ierr); 1109 ierr = MPI_Attr_get(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr); 1110 if (!flg) { 1111 ierr = PetscNewLog(A,Mat_Elemental_Grid,&commgrid);CHKERRQ(ierr); 1112 1113 ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr); 1114 /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until elem::Grid() is called */ 1115 ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",elem::mpi::CommSize(cxxcomm),&optv1,&flg1);CHKERRQ(ierr); 1116 ierr = PetscOptionsInt("-mat_elemental_grid_width","Grid Width","None",1,&optv2,&flg2);CHKERRQ(ierr); 1117 if (flg1 || flg2) { 1118 if (optv1*optv2 != elem::mpi::CommSize(cxxcomm)) { 1119 SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Grid Height times Grid Width must equal CommSize"); 1120 } 1121 commgrid->grid = new elem::Grid(cxxcomm,optv1,optv2); /* use user-provided grid sizes */ 1122 } else { 1123 commgrid->grid = new elem::Grid(cxxcomm); /* use Elemental default grid sizes */ 1124 } 1125 commgrid->grid_refct = 1; 1126 ierr = MPI_Attr_put(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRQ(ierr); 1127 PetscOptionsEnd(); 1128 } else { 1129 commgrid->grid_refct++; 1130 } 1131 ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr); 1132 a->grid = commgrid->grid; 1133 a->emat = new elem::DistMatrix<PetscElemScalar>(*a->grid); 1134 a->esubmat = new elem::Matrix<PetscElemScalar>(1,1); 1135 a->interface = new elem::AxpyInterface<PetscElemScalar>; 1136 a->pivot = new elem::DistMatrix<PetscInt,elem::VC,elem::STAR>; 1137 1138 /* build cache for off array entries formed */ 1139 a->interface->Attach(elem::LOCAL_TO_GLOBAL,*(a->emat)); 1140 1141 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental);CHKERRQ(ierr); 1142 ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetFactor_elemental_C",MatGetFactor_elemental_elemental);CHKERRQ(ierr); 1143 1144 ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr); 1145 PetscFunctionReturn(0); 1146 } 1147 1148