1 #include <petsc-private/dmmbimpl.h> /*I "petscdmmoab.h" I*/ 2 3 #include <petscdmmoab.h> 4 #include <MBTagConventions.hpp> 5 #include <moab/NestedRefine.hpp> 6 7 #undef __FUNCT__ 8 #define __FUNCT__ "DMMoabGenerateHierarchy" 9 /*@ 10 DMMoabGenerateHierarchy - Generate a multi-level uniform refinement hierarchy 11 by succesively refining a coarse mesh, already defined in the DM object 12 provided by the user. 13 14 Collective on MPI_Comm 15 16 Input Parameter: 17 + dmb - The DMMoab object 18 19 Output Parameter: 20 + nlevels - The number of levels of refinement needed to generate the hierarchy 21 . ldegrees - The degree of refinement at each level in the hierarchy 22 23 Level: beginner 24 25 .keywords: DMMoab, create, refinement 26 @*/ 27 PetscErrorCode DMMoabGenerateHierarchy(DM dm,PetscInt nlevels,PetscInt *ldegrees) 28 { 29 DM_Moab *dmmoab; 30 PetscErrorCode ierr; 31 moab::ErrorCode merr; 32 PetscInt *pdegrees,i; 33 std::vector<moab::EntityHandle> hsets; 34 35 PetscFunctionBegin; 36 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 37 dmmoab = (DM_Moab*)(dm)->data; 38 39 if (!ldegrees) { 40 ierr = PetscMalloc1(nlevels,&pdegrees);CHKERRQ(ierr); 41 for (i=0; i<nlevels; i++) pdegrees[i]=2; /* default = Degree 2 refinement */ 42 } 43 else pdegrees=ldegrees; 44 45 /* initialize set level refinement data for hierarchy */ 46 dmmoab->nhlevels=nlevels; 47 48 /* Instantiate the nested refinement class */ 49 dmmoab->hierarchy = new moab::NestedRefine(dynamic_cast<moab::Core*>(dmmoab->mbiface), dmmoab->pcomm, dmmoab->fileset); 50 51 ierr = PetscMalloc1(nlevels+1,&dmmoab->hsets);CHKERRQ(ierr); 52 53 /* generate the mesh hierarchy */ 54 merr = dmmoab->hierarchy->generate_mesh_hierarchy(pdegrees, nlevels, hsets);MBERRNM(merr); 55 56 for (i=0; i<=nlevels; i++) dmmoab->hsets[i]=hsets[i]; 57 58 if (!ldegrees) { 59 ierr = PetscFree(pdegrees);CHKERRQ(ierr); 60 } 61 PetscFunctionReturn(0); 62 } 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "DMRefineHierarchy_Moab" 66 /*@ 67 DMRefineHierarchy_Moab - Generate a multi-level DM hierarchy 68 by succesively refining a coarse mesh. 69 70 Collective on MPI_Comm 71 72 Input Parameter: 73 + dm - The DMMoab object 74 75 Output Parameter: 76 + nlevels - The number of levels of refinement needed to generate the hierarchy 77 . dmf - The DM objects after successive refinement of the hierarchy 78 79 Level: beginner 80 81 .keywords: DMMoab, generate, refinement 82 @*/ 83 PetscErrorCode DMRefineHierarchy_Moab(DM dm,PetscInt nlevels,DM dmf[]) 84 { 85 PetscErrorCode ierr; 86 PetscInt i; 87 88 PetscFunctionBegin; 89 90 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 91 for (i=1; i<nlevels; i++) { 92 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 93 } 94 PetscFunctionReturn(0); 95 } 96 97 #undef __FUNCT__ 98 #define __FUNCT__ "DMCoarsenHierarchy_Moab" 99 /*@ 100 DMCoarsenHierarchy_Moab - Generate a multi-level DM hierarchy 101 by succesively coarsening a refined mesh. 102 103 Collective on MPI_Comm 104 105 Input Parameter: 106 + dm - The DMMoab object 107 108 Output Parameter: 109 + nlevels - The number of levels of refinement needed to generate the hierarchy 110 . dmc - The DM objects after successive coarsening of the hierarchy 111 112 Level: beginner 113 114 .keywords: DMMoab, generate, coarsening 115 @*/ 116 PetscErrorCode DMCoarsenHierarchy_Moab(DM dm,PetscInt nlevels,DM dmc[]) 117 { 118 PetscErrorCode ierr; 119 PetscInt i; 120 121 PetscFunctionBegin; 122 123 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 124 for (i=1; i<nlevels; i++) { 125 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 126 } 127 PetscFunctionReturn(0); 128 } 129 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "DMCreateInterpolation_Moab" 133 /*@ 134 DMCreateInterpolation_Moab - Generate the interpolation operators to transform 135 operators (matrices, vectors) from parent level to child level as defined by 136 the DM inputs provided by the user. 137 138 Collective on MPI_Comm 139 140 Input Parameter: 141 + dm1 - The DMMoab object 142 - dm2 - the second, finer DMMoab object 143 144 Output Parameter: 145 + interpl - The interpolation operator for transferring data between the levels 146 - vec - The scaling vector (optional) 147 148 Level: developer 149 150 .keywords: DMMoab, create, refinement 151 @*/ 152 PetscErrorCode DMCreateInterpolation_Moab(DM dm1,DM dm2,Mat* interpl,Vec* vec) 153 { 154 DM_Moab *dmb1, *dmb2; 155 PetscErrorCode ierr; 156 moab::ErrorCode merr; 157 PetscInt dim; 158 PetscReal factor; 159 PetscBool eonbnd; 160 std::vector<int> bndrows; 161 std::vector<PetscBool> dbdry; 162 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 165 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 166 dmb1 = (DM_Moab*)(dm1)->data; 167 dmb2 = (DM_Moab*)(dm2)->data; 168 169 PetscInfo4(dm1,"Creating interpolation matrix %D X %D to apply transformation between levels %D -> %D.\n",dmb1->nloc,dmb2->nloc,dmb1->hlevel,dmb2->hlevel); 170 171 ierr = MatCreate(PetscObjectComm((PetscObject)dm1), interpl);CHKERRQ(ierr); 172 ierr = MatSetType(*interpl, dm1->mattype);CHKERRQ(ierr); 173 ierr = MatSetSizes(*interpl, dmb2->nloc, dmb1->nloc, dmb2->n, dmb1->n);CHKERRQ(ierr); 174 175 /* TODO: This is a hack for the rectangular system - decipher NNZ pattern better */ 176 ierr = MatSetFromOptions(*interpl);CHKERRQ(ierr); 177 178 ierr = MatSeqAIJSetPreallocation(*interpl,dmb2->nloc,0);CHKERRQ(ierr); 179 ierr = MatMPIAIJSetPreallocation(*interpl,dmb2->nloc,0,dmb2->nghost,0);CHKERRQ(ierr); 180 181 /* set up internal matrix data-structures */ 182 ierr = MatSetUp(*interpl);CHKERRQ(ierr); 183 ierr = MatZeroEntries(*interpl);CHKERRQ(ierr); 184 185 ierr = DMGetDimension(dm1, &dim);CHKERRQ(ierr); 186 187 factor = std::pow(2.0 /*degree_P_for_refinement*/,(dmb2->hlevel-dmb1->hlevel)*dmb1->dim*1.0); 188 189 /* Loop through the remaining vertices. These vertices appear only on the current refined_level. */ 190 for(moab::Range::iterator iter = dmb1->elocal->begin(); iter!= dmb1->elocal->end(); iter++) { 191 192 const moab::EntityHandle ehandle = *iter; 193 std::vector<moab::EntityHandle> children; 194 std::vector<moab::EntityHandle> connp, connc; 195 196 /* Get the relation between the current (coarse) parent and its corresponding (finer) children elements */ 197 merr = dmb1->hierarchy->parent_to_child(ehandle, dmb1->hlevel, dmb2->hlevel, children);MBERRNM(merr); 198 199 /* Get connectivity and coordinates of the parent vertices */ 200 merr = dmb1->hierarchy->get_connectivity(ehandle, dmb1->hlevel, connp);MBERRNM(merr); 201 for (unsigned ic=0; ic < children.size(); ic++) { 202 std::vector<moab::EntityHandle> tconnc; 203 /* Get coordinates of the parent vertices in canonical order */ 204 merr = dmb1->hierarchy->get_connectivity(children[ic], dmb2->hlevel, tconnc);MBERRNM(merr); 205 for (unsigned tc=0; tc<tconnc.size(); tc++) { 206 connc.push_back(tconnc[tc]); 207 } 208 } 209 210 std::vector<double> pcoords(connp.size()*3), ccoords(connc.size()*3), values_phi(connc.size()); 211 /* Get coordinates for connectivity entities in canonical order for both coarse and finer levels */ 212 merr = dmb1->hierarchy->get_coordinates(&connp[0], connp.size(), dmb1->hlevel, &pcoords[0]);MBERRNM(merr); 213 merr = dmb2->hierarchy->get_coordinates(&connc[0], connc.size(), dmb2->hlevel, &ccoords[0]);MBERRNM(merr); 214 215 std::vector<int> dofsp(connp.size()), dofsc(connc.size()); 216 /* TODO: specific to scalar system - use GetDofs */ 217 ierr = DMMoabGetFieldDofs(dm1, connp.size(), &connp[0], 0, &dofsp[0]);CHKERRQ(ierr); 218 ierr = DMMoabGetFieldDofs(dm2, connc.size(), &connc[0], 0, &dofsc[0]);CHKERRQ(ierr); 219 220 /* Compute the interpolation weights by determining distance of 1-ring 221 neighbor vertices from current vertex */ 222 for (unsigned i=0;i<connp.size(); i++) { 223 double normsum=0.0; 224 for (unsigned j=0;j<connc.size(); j++) { 225 values_phi[j] = 0.0; 226 for (unsigned k=0;k<3; k++) 227 values_phi[j] += (pcoords[i*3+k]-ccoords[k+j*3])*(pcoords[i*3+k]-ccoords[k+j*3]); 228 if (values_phi[j] < 1e-12) { 229 values_phi[j] = 1e12; 230 } 231 else { 232 values_phi[j] = 1.0/(values_phi[j]); 233 normsum += values_phi[j]; 234 } 235 } 236 for (unsigned j=0;j<connc.size(); j++) { 237 if (values_phi[j] > 1e11) 238 values_phi[j] = factor*0.5/connc.size(); 239 else 240 values_phi[j] = factor*values_phi[j]*0.5/(connc.size()*normsum); 241 } 242 ierr = MatSetValues(*interpl, connc.size(), &dofsc[0], 1, &dofsp[i], &values_phi[0], ADD_VALUES);CHKERRQ(ierr); 243 } 244 245 /* check if element is on the boundary */ 246 //ierr = DMMoabIsEntityOnBoundary(dm1,ehandle,&eonbnd);CHKERRQ(ierr); 247 dbdry.resize(connc.size()); 248 ierr = DMMoabCheckBoundaryVertices(dm2,connc.size(),&connc[0],dbdry.data());CHKERRQ(ierr); 249 eonbnd=PETSC_FALSE; 250 for (unsigned i=0; i< connc.size(); ++i) 251 if (dbdry[i]) eonbnd=PETSC_TRUE; 252 253 values_phi.clear(); 254 values_phi.resize(connp.size()); 255 /* apply dirichlet boundary conditions */ 256 if (eonbnd) { 257 258 ierr = MatAssemblyBegin(*interpl,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 259 ierr = MatAssemblyEnd(*interpl,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 260 /* get the list of nodes on boundary so that we can enforce dirichlet conditions strongly */ 261 //ierr = DMMoabCheckBoundaryVertices(dm2,connc.size(),&connc[0],dbdry);CHKERRQ(ierr); 262 for (unsigned i=0; i < connc.size(); i++) { 263 if (dbdry[i]) { /* dirichlet node */ 264 /* think about strongly imposing dirichlet */ 265 //bndrows.push_back(dofsc[i]); 266 267 ierr = MatSetValues(*interpl, 1, &dofsc[i], connp.size(), &dofsp[0], &values_phi[0], INSERT_VALUES);CHKERRQ(ierr); 268 //values_phi[0]=1.0; 269 //ierr = MatSetValues(*interpl, 1, &dofsc[i], 1, &dofsc[i], &values_phi[0], INSERT_VALUES);CHKERRQ(ierr); 270 } 271 } 272 273 ierr = MatAssemblyBegin(*interpl,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 274 ierr = MatAssemblyEnd(*interpl,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 275 } 276 277 //get interpolation weights 278 //ierr = Compute_Quad4_Basis(pcoords, 1, coord, values_phi);CHKERRQ(ierr); 279 // for (int j=0;j<dofs_per_element; j++) 280 // std::cout<<"values "<<values_phi[j]<<std::endl; 281 282 //get row and column indices, zero weights are ignored 283 /* 284 int nz_ind = 0; 285 idx = dmb2->vowned->index(vhandle); 286 for (int j=0;j<dofs_per_element; j++){ 287 idy[nz_ind] = dmb1->vowned->index(connectivity[j]); 288 PetscPrintf(PETSC_COMM_WORLD, "Finding coarse connectivity vertex %D associated with [%D, %D] - set to %D\n", connectivity[j], parent.size(), vhandle, idy[nz_ind]); 289 //values_phi[nz_ind] = values_phi[j]; 290 nz_ind = nz_ind+1; 291 } 292 */ 293 294 //ierr = MatSetValues(*interpl, nz_ind, idy, 1, &idx, values_phi, INSERT_VALUES);CHKERRQ(ierr); 295 //ierr = MatSetValues(*interpl, connp.size(), dofsp, connc.size(), dofsc, &values_phi[0], INSERT_VALUES);CHKERRQ(ierr); 296 } 297 298 //PetscPrintf(PETSC_COMM_WORLD, "[Boundary vertices = %D] :: A few: %D %D %D %D \n", bndrows.size(), bndrows[0], bndrows[1], bndrows[2], bndrows[3]); 299 //ierr = MatZeroRows(*interpl, bndrows.size(), &bndrows[0], 1.0, 0, 0);CHKERRQ(ierr); 300 301 ierr = MatAssemblyBegin(*interpl,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 302 ierr = MatAssemblyEnd(*interpl,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 303 PetscFunctionReturn(0); 304 } 305 306 #undef __FUNCT__ 307 #define __FUNCT__ "DMCreateInjection_Moab" 308 /*@ 309 DMCreateInjection_Moab - Generate a multi-level uniform refinement hierarchy 310 by succesively refining a coarse mesh, already defined in the DM object 311 provided by the user. 312 313 Collective on MPI_Comm 314 315 Input Parameter: 316 . dmb - The DMMoab object 317 318 Output Parameter: 319 . nlevels - The number of levels of refinement needed to generate the hierarchy 320 + ldegrees - The degree of refinement at each level in the hierarchy 321 322 Level: beginner 323 324 .keywords: DMMoab, create, refinement 325 @*/ 326 PetscErrorCode DMCreateInjection_Moab(DM dm1,DM dm2,VecScatter* ctx) 327 { 328 //DM_Moab *dmmoab; 329 330 PetscFunctionBegin; 331 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 332 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 333 //dmmoab = (DM_Moab*)(dm1)->data; 334 335 PetscPrintf(PETSC_COMM_WORLD, "[DMCreateInjection_Moab] :: Placeholder\n"); 336 PetscFunctionReturn(0); 337 } 338 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DM_UMR_Moab_Private" 342 PetscErrorCode DM_UMR_Moab_Private(DM dm,MPI_Comm comm,PetscBool refine,DM *dmref) 343 { 344 PetscErrorCode ierr; 345 PetscInt i,dim; 346 DM dm2; 347 moab::ErrorCode merr; 348 DM_Moab *dmb = (DM_Moab*)dm->data,*dd2; 349 350 PetscFunctionBegin; 351 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 352 PetscValidPointer(dmref,4); 353 354 if ( (dmb->hlevel == dmb->nhlevels && refine) || (dmb->hlevel == 0 && !refine) ) { 355 if (dmb->hlevel+1 > dmb->nhlevels && refine) PetscInfo2(NULL,"Invalid multigrid refinement hierarchy level specified (%D). MOAB UMR max levels = %D. Creating a NULL object.\n",dmb->hlevel+1,dmb->nhlevels); 356 if (dmb->hlevel-1 < 0 && !refine) PetscInfo1(NULL,"Invalid multigrid coarsen hierarchy level specified (%D). Creating a NULL object.\n",dmb->hlevel-1); 357 *dmref = PETSC_NULL; 358 PetscFunctionReturn(0); 359 } 360 361 ierr = DMMoabCreate(PetscObjectComm((PetscObject)dm), &dm2);CHKERRQ(ierr); 362 dd2 = (DM_Moab*)dm2->data; 363 364 dd2->mbiface = dmb->mbiface; 365 dd2->pcomm = dmb->pcomm; 366 dd2->icreatedinstance = PETSC_FALSE; 367 368 /* set the new level based on refinement/coarsening */ 369 if (refine) { 370 dd2->hlevel=dmb->hlevel+1; 371 } 372 else { 373 dd2->hlevel=dmb->hlevel-1; 374 } 375 376 /* Copy the multilevel hierarchy pointers in MOAB */ 377 dd2->hierarchy = dmb->hierarchy; 378 dd2->nhlevels = dmb->nhlevels; 379 ierr = PetscMalloc1(dd2->nhlevels+1,&dd2->hsets);CHKERRQ(ierr); 380 for (i=0; i<=dd2->nhlevels; i++) { 381 dd2->hsets[i]=dmb->hsets[i]; 382 } 383 dd2->fileset = dd2->hsets[dd2->hlevel]; 384 385 /* do the remaining initializations for DMMoab */ 386 dd2->bs = dmb->bs; 387 dd2->numFields = dmb->numFields; 388 dd2->rw_dbglevel = dmb->rw_dbglevel; 389 dd2->partition_by_rank = dmb->partition_by_rank; 390 ierr = PetscStrcpy(dd2->extra_read_options, dmb->extra_read_options);CHKERRQ(ierr); 391 ierr = PetscStrcpy(dd2->extra_write_options, dmb->extra_write_options);CHKERRQ(ierr); 392 dd2->read_mode = dmb->read_mode; 393 dd2->write_mode = dmb->write_mode; 394 395 /* set global ID tag handle */ 396 ierr = DMMoabSetLocalToGlobalTag(dm2, dmb->ltog_tag);CHKERRQ(ierr); 397 398 merr = dd2->mbiface->tag_get_handle(MATERIAL_SET_TAG_NAME, dd2->material_tag);MBERRNM(merr); 399 400 ierr = DMSetOptionsPrefix(dm2,((PetscObject)dm)->prefix);CHKERRQ(ierr); 401 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 402 ierr = DMSetDimension(dm2,dim);CHKERRQ(ierr); 403 404 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 405 dm2->ops->creatematrix = dm->ops->creatematrix; 406 407 /* copy fill information if given */ 408 ierr = DMMoabSetBlockFills(dm2, dmb->dfill, dmb->ofill);CHKERRQ(ierr); 409 410 /* copy vector type information */ 411 ierr = DMSetMatType(dm2,dm->mattype);CHKERRQ(ierr); 412 ierr = DMSetVecType(dm2,dm->vectype);CHKERRQ(ierr); 413 dd2->numFields = dmb->numFields; 414 if (dmb->numFields) { 415 ierr = DMMoabSetFieldNames(dm2,dmb->numFields,dmb->fieldNames);CHKERRQ(ierr); 416 } 417 418 ierr = DMSetFromOptions(dm2);CHKERRQ(ierr); 419 420 /* recreate Dof numbering for the refined DM and make sure the distribution is correctly populated */ 421 ierr = DMSetUp(dm2);CHKERRQ(ierr); 422 423 *dmref = dm2; 424 PetscFunctionReturn(0); 425 } 426 427 428 #undef __FUNCT__ 429 #define __FUNCT__ "DMRefine_Moab" 430 /*@ 431 DMRefine_Moab - Generate a multi-level uniform refinement hierarchy 432 by succesively refining a coarse mesh, already defined in the DM object 433 provided by the user. 434 435 Collective on DM 436 437 Input Parameter: 438 + dm - The DMMoab object 439 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 440 441 Output Parameter: 442 . dmf - the refined DM, or NULL 443 444 Note: If no refinement was done, the return value is NULL 445 446 Level: developer 447 448 .keywords: DMMoab, create, refinement 449 @*/ 450 PetscErrorCode DMRefine_Moab(DM dm,MPI_Comm comm,DM* dmf) 451 { 452 PetscErrorCode ierr; 453 454 PetscFunctionBegin; 455 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 456 457 ierr = DM_UMR_Moab_Private(dm,comm,PETSC_TRUE,dmf);CHKERRQ(ierr); 458 PetscFunctionReturn(0); 459 } 460 461 #undef __FUNCT__ 462 #define __FUNCT__ "DMCoarsen_Moab" 463 /*@ 464 DMCoarsen_Moab - Generate a multi-level uniform refinement hierarchy 465 by succesively refining a coarse mesh, already defined in the DM object 466 provided by the user. 467 468 Collective on DM 469 470 Input Parameter: 471 . dm - The DMMoab object 472 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 473 474 Output Parameter: 475 . dmf - the coarsened DM, or NULL 476 477 Note: If no coarsening was done, the return value is NULL 478 479 Level: developer 480 481 .keywords: DMMoab, create, coarsening 482 @*/ 483 PetscErrorCode DMCoarsen_Moab(DM dm,MPI_Comm comm,DM* dmc) 484 { 485 PetscErrorCode ierr; 486 487 PetscFunctionBegin; 488 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 489 490 ierr = DM_UMR_Moab_Private(dm,comm,PETSC_FALSE,dmc);CHKERRQ(ierr); 491 PetscFunctionReturn(0); 492 } 493