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