1 2 #include <private/daimpl.h> /*I "petscdmda.h" I*/ 3 4 #undef __FUNCT__ 5 #define __FUNCT__ "DMView_DA_2d" 6 PetscErrorCode DMView_DA_2d(DM da,PetscViewer viewer) 7 { 8 PetscErrorCode ierr; 9 PetscMPIInt rank; 10 PetscBool iascii,isdraw,isbinary; 11 DM_DA *dd = (DM_DA*)da->data; 12 #if defined(PETSC_HAVE_MATLAB_ENGINE) 13 PetscBool ismatlab; 14 #endif 15 16 PetscFunctionBegin; 17 ierr = MPI_Comm_rank(((PetscObject)da)->comm,&rank);CHKERRQ(ierr); 18 19 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 20 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 21 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 22 #if defined(PETSC_HAVE_MATLAB_ENGINE) 23 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);CHKERRQ(ierr); 24 #endif 25 if (iascii) { 26 PetscViewerFormat format; 27 28 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 29 if (format != PETSC_VIEWER_ASCII_VTK && format != PETSC_VIEWER_ASCII_VTK_CELL) { 30 DMDALocalInfo info; 31 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 32 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 33 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Processor [%d] M %D N %D m %D n %D w %D s %D\n",rank,dd->M,dd->N,dd->m,dd->n,dd->w,dd->s);CHKERRQ(ierr); 34 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"X range of indices: %D %D, Y range of indices: %D %D\n",info.xs,info.xs+info.xm,info.ys,info.ys+info.ym);CHKERRQ(ierr); 35 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 36 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 37 } else { 38 ierr = DMView_DA_VTK(da,viewer);CHKERRQ(ierr); 39 } 40 } else if (isdraw) { 41 PetscDraw draw; 42 double ymin = -1*dd->s-1,ymax = dd->N+dd->s; 43 double xmin = -1*dd->s-1,xmax = dd->M+dd->s; 44 double x,y; 45 PetscInt base,*idx; 46 char node[10]; 47 PetscBool isnull; 48 49 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 50 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 51 if (!dd->coordinates) { 52 ierr = PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);CHKERRQ(ierr); 53 } 54 ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr); 55 56 /* first processor draw all node lines */ 57 if (!rank) { 58 ymin = 0.0; ymax = dd->N - 1; 59 for (xmin=0; xmin<dd->M; xmin++) { 60 ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_BLACK);CHKERRQ(ierr); 61 } 62 xmin = 0.0; xmax = dd->M - 1; 63 for (ymin=0; ymin<dd->N; ymin++) { 64 ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_BLACK);CHKERRQ(ierr); 65 } 66 } 67 ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); 68 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 69 70 /* draw my box */ 71 ymin = dd->ys; ymax = dd->ye - 1; xmin = dd->xs/dd->w; 72 xmax =(dd->xe-1)/dd->w; 73 ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_RED);CHKERRQ(ierr); 74 ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_RED);CHKERRQ(ierr); 75 ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr); 76 ierr = PetscDrawLine(draw,xmax,ymin,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr); 77 78 /* put in numbers */ 79 base = (dd->base)/dd->w; 80 for (y=ymin; y<=ymax; y++) { 81 for (x=xmin; x<=xmax; x++) { 82 sprintf(node,"%d",(int)base++); 83 ierr = PetscDrawString(draw,x,y,PETSC_DRAW_BLACK,node);CHKERRQ(ierr); 84 } 85 } 86 87 ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); 88 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 89 /* overlay ghost numbers, useful for error checking */ 90 /* put in numbers */ 91 92 base = 0; idx = dd->idx; 93 ymin = dd->Ys; ymax = dd->Ye; xmin = dd->Xs; xmax = dd->Xe; 94 for (y=ymin; y<ymax; y++) { 95 for (x=xmin; x<xmax; x++) { 96 if ((base % dd->w) == 0) { 97 sprintf(node,"%d",(int)(idx[base]/dd->w)); 98 ierr = PetscDrawString(draw,x/dd->w,y,PETSC_DRAW_BLUE,node);CHKERRQ(ierr); 99 } 100 base++; 101 } 102 } 103 ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); 104 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 105 } else if (isbinary){ 106 ierr = DMView_DA_Binary(da,viewer);CHKERRQ(ierr); 107 #if defined(PETSC_HAVE_MATLAB_ENGINE) 108 } else if (ismatlab) { 109 ierr = DMView_DA_Matlab(da,viewer);CHKERRQ(ierr); 110 #endif 111 } else SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for DMDA 1d",((PetscObject)viewer)->type_name); 112 PetscFunctionReturn(0); 113 } 114 115 /* 116 M is number of grid points 117 m is number of processors 118 119 */ 120 #undef __FUNCT__ 121 #define __FUNCT__ "DMDASplitComm2d" 122 PetscErrorCode DMDASplitComm2d(MPI_Comm comm,PetscInt M,PetscInt N,PetscInt sw,MPI_Comm *outcomm) 123 { 124 PetscErrorCode ierr; 125 PetscInt m,n = 0,x = 0,y = 0; 126 PetscMPIInt size,csize,rank; 127 128 PetscFunctionBegin; 129 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 130 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 131 132 csize = 4*size; 133 do { 134 if (csize % 4) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cannot split communicator of size %d tried %d %D %D",size,csize,x,y); 135 csize = csize/4; 136 137 m = (PetscInt)(0.5 + sqrt(((double)M)*((double)csize)/((double)N))); 138 if (!m) m = 1; 139 while (m > 0) { 140 n = csize/m; 141 if (m*n == csize) break; 142 m--; 143 } 144 if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;} 145 146 x = M/m + ((M % m) > ((csize-1) % m)); 147 y = (N + (csize-1)/m)/n; 148 } while ((x < 4 || y < 4) && csize > 1); 149 if (size != csize) { 150 MPI_Group entire_group,sub_group; 151 PetscMPIInt i,*groupies; 152 153 ierr = MPI_Comm_group(comm,&entire_group);CHKERRQ(ierr); 154 ierr = PetscMalloc(csize*sizeof(PetscInt),&groupies);CHKERRQ(ierr); 155 for (i=0; i<csize; i++) { 156 groupies[i] = (rank/csize)*csize + i; 157 } 158 ierr = MPI_Group_incl(entire_group,csize,groupies,&sub_group);CHKERRQ(ierr); 159 ierr = PetscFree(groupies);CHKERRQ(ierr); 160 ierr = MPI_Comm_create(comm,sub_group,outcomm);CHKERRQ(ierr); 161 ierr = MPI_Group_free(&entire_group);CHKERRQ(ierr); 162 ierr = MPI_Group_free(&sub_group);CHKERRQ(ierr); 163 ierr = PetscInfo1(0,"DMDASplitComm2d:Creating redundant coarse problems of size %d\n",csize);CHKERRQ(ierr); 164 } else { 165 *outcomm = comm; 166 } 167 PetscFunctionReturn(0); 168 } 169 170 #undef __FUNCT__ 171 #define __FUNCT__ "DMDAFunction" 172 static PetscErrorCode DMDAFunction(DM dm,Vec x,Vec F) 173 { 174 PetscErrorCode ierr; 175 Vec localX; 176 177 PetscFunctionBegin; 178 ierr = DMGetLocalVector(dm,&localX);CHKERRQ(ierr); 179 ierr = DMGlobalToLocalBegin(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr); 180 ierr = DMGlobalToLocalEnd(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr); 181 ierr = DMDAComputeFunction1(dm,localX,F,dm->ctx);CHKERRQ(ierr); 182 ierr = DMRestoreLocalVector(dm,&localX);CHKERRQ(ierr); 183 PetscFunctionReturn(0); 184 } 185 186 #undef __FUNCT__ 187 #define __FUNCT__ "DMDASetLocalFunction" 188 /*@C 189 DMDASetLocalFunction - Caches in a DM a local function. 190 191 Logically Collective on DMDA 192 193 Input Parameter: 194 + da - initial distributed array 195 - lf - the local function 196 197 Level: intermediate 198 199 Notes: 200 If you used SNESSetFunction(snes,r,SNESDMDAComputeFunction,ctx); then the context passed to your function is the ctx set here. 201 202 If you use SNESSetDM() and did not use SNESSetFunction() then the context passed to your function is the context set with DMSetApplicationContext() 203 204 Developer Notes: It is possibly confusing which context is passed to the user function, it would be nice to unify them somehow. 205 206 .keywords: distributed array, refine 207 208 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunctioni() 209 @*/ 210 PetscErrorCode DMDASetLocalFunction(DM da,DMDALocalFunction1 lf) 211 { 212 PetscErrorCode ierr; 213 DM_DA *dd = (DM_DA*)da->data; 214 215 PetscFunctionBegin; 216 PetscValidHeaderSpecific(da,DM_CLASSID,1); 217 ierr = DMSetFunction(da,DMDAFunction);CHKERRQ(ierr); 218 dd->lf = lf; 219 PetscFunctionReturn(0); 220 } 221 222 #undef __FUNCT__ 223 #define __FUNCT__ "DMDASetLocalFunctioni" 224 /*@C 225 DMDASetLocalFunctioni - Caches in a DM a local function that evaluates a single component 226 227 Logically Collective on DMDA 228 229 Input Parameter: 230 + da - initial distributed array 231 - lfi - the local function 232 233 Level: intermediate 234 235 .keywords: distributed array, refine 236 237 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction() 238 @*/ 239 PetscErrorCode DMDASetLocalFunctioni(DM da,PetscErrorCode (*lfi)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*)) 240 { 241 DM_DA *dd = (DM_DA*)da->data; 242 PetscFunctionBegin; 243 PetscValidHeaderSpecific(da,DM_CLASSID,1); 244 dd->lfi = lfi; 245 PetscFunctionReturn(0); 246 } 247 248 #undef __FUNCT__ 249 #define __FUNCT__ "DMDASetLocalFunctionib" 250 /*@C 251 DMDASetLocalFunctionib - Caches in a DM a block local function that evaluates a single component 252 253 Logically Collective on DMDA 254 255 Input Parameter: 256 + da - initial distributed array 257 - lfi - the local function 258 259 Level: intermediate 260 261 .keywords: distributed array, refine 262 263 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction() 264 @*/ 265 PetscErrorCode DMDASetLocalFunctionib(DM da,PetscErrorCode (*lfi)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*)) 266 { 267 DM_DA *dd = (DM_DA*)da->data; 268 PetscFunctionBegin; 269 PetscValidHeaderSpecific(da,DM_CLASSID,1); 270 dd->lfib = lfi; 271 PetscFunctionReturn(0); 272 } 273 274 #undef __FUNCT__ 275 #define __FUNCT__ "DMDASetLocalAdicFunction_Private" 276 PetscErrorCode DMDASetLocalAdicFunction_Private(DM da,DMDALocalFunction1 ad_lf) 277 { 278 DM_DA *dd = (DM_DA*)da->data; 279 PetscFunctionBegin; 280 PetscValidHeaderSpecific(da,DM_CLASSID,1); 281 dd->adic_lf = ad_lf; 282 PetscFunctionReturn(0); 283 } 284 285 /*MC 286 DMDASetLocalAdicFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR 287 288 Synopsis: 289 PetscErrorCode DMDASetLocalAdicFunctioni(DM da,PetscInt (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*) 290 291 Logically Collective on DMDA 292 293 Input Parameter: 294 + da - initial distributed array 295 - ad_lfi - the local function as computed by ADIC/ADIFOR 296 297 Level: intermediate 298 299 .keywords: distributed array, refine 300 301 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(), 302 DMDASetLocalJacobian(), DMDASetLocalFunctioni() 303 M*/ 304 305 #undef __FUNCT__ 306 #define __FUNCT__ "DMDASetLocalAdicFunctioni_Private" 307 PetscErrorCode DMDASetLocalAdicFunctioni_Private(DM da,PetscErrorCode (*ad_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*)) 308 { 309 DM_DA *dd = (DM_DA*)da->data; 310 PetscFunctionBegin; 311 PetscValidHeaderSpecific(da,DM_CLASSID,1); 312 dd->adic_lfi = ad_lfi; 313 PetscFunctionReturn(0); 314 } 315 316 /*MC 317 DMDASetLocalAdicMFFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR 318 319 Synopsis: 320 PetscErrorCode DMDASetLocalAdicFunctioni(DM da,int (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*) 321 322 Logically Collective on DMDA 323 324 Input Parameter: 325 + da - initial distributed array 326 - admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR 327 328 Level: intermediate 329 330 .keywords: distributed array, refine 331 332 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(), 333 DMDASetLocalJacobian(), DMDASetLocalFunctioni() 334 M*/ 335 336 #undef __FUNCT__ 337 #define __FUNCT__ "DMDASetLocalAdicMFFunctioni_Private" 338 PetscErrorCode DMDASetLocalAdicMFFunctioni_Private(DM da,PetscErrorCode (*admf_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*)) 339 { 340 DM_DA *dd = (DM_DA*)da->data; 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(da,DM_CLASSID,1); 343 dd->adicmf_lfi = admf_lfi; 344 PetscFunctionReturn(0); 345 } 346 347 /*MC 348 DMDASetLocalAdicFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR 349 350 Synopsis: 351 PetscErrorCode DMDASetLocalAdicFunctionib(DM da,PetscInt (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*) 352 353 Logically Collective on DMDA 354 355 Input Parameter: 356 + da - initial distributed array 357 - ad_lfi - the local function as computed by ADIC/ADIFOR 358 359 Level: intermediate 360 361 .keywords: distributed array, refine 362 363 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(), 364 DMDASetLocalJacobian(), DMDASetLocalFunctionib() 365 M*/ 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "DMDASetLocalAdicFunctionib_Private" 369 PetscErrorCode DMDASetLocalAdicFunctionib_Private(DM da,PetscErrorCode (*ad_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*)) 370 { 371 DM_DA *dd = (DM_DA*)da->data; 372 PetscFunctionBegin; 373 PetscValidHeaderSpecific(da,DM_CLASSID,1); 374 dd->adic_lfib = ad_lfi; 375 PetscFunctionReturn(0); 376 } 377 378 /*MC 379 DMDASetLocalAdicMFFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR 380 381 Synopsis: 382 PetscErrorCode DMDASetLocalAdicFunctionib(DM da,int (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*) 383 384 Logically Collective on DMDA 385 386 Input Parameter: 387 + da - initial distributed array 388 - admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR 389 390 Level: intermediate 391 392 .keywords: distributed array, refine 393 394 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(), 395 DMDASetLocalJacobian(), DMDASetLocalFunctionib() 396 M*/ 397 398 #undef __FUNCT__ 399 #define __FUNCT__ "DMDASetLocalAdicMFFunctionib_Private" 400 PetscErrorCode DMDASetLocalAdicMFFunctionib_Private(DM da,PetscErrorCode (*admf_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*)) 401 { 402 DM_DA *dd = (DM_DA*)da->data; 403 PetscFunctionBegin; 404 PetscValidHeaderSpecific(da,DM_CLASSID,1); 405 dd->adicmf_lfib = admf_lfi; 406 PetscFunctionReturn(0); 407 } 408 409 /*MC 410 DMDASetLocalAdicMFFunction - Caches in a DM a local function computed by ADIC/ADIFOR 411 412 Synopsis: 413 PetscErrorCode DMDASetLocalAdicMFFunction(DM da,DMDALocalFunction1 ad_lf) 414 415 Logically Collective on DMDA 416 417 Input Parameter: 418 + da - initial distributed array 419 - ad_lf - the local function as computed by ADIC/ADIFOR 420 421 Level: intermediate 422 423 .keywords: distributed array, refine 424 425 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(), 426 DMDASetLocalJacobian() 427 M*/ 428 429 #undef __FUNCT__ 430 #define __FUNCT__ "DMDASetLocalAdicMFFunction_Private" 431 PetscErrorCode DMDASetLocalAdicMFFunction_Private(DM da,DMDALocalFunction1 ad_lf) 432 { 433 DM_DA *dd = (DM_DA*)da->data; 434 PetscFunctionBegin; 435 PetscValidHeaderSpecific(da,DM_CLASSID,1); 436 dd->adicmf_lf = ad_lf; 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "DMDAJacobianDefaultLocal" 442 PetscErrorCode DMDAJacobianLocal(DM dm,Vec x,Mat A,Mat B, MatStructure *str) 443 { 444 PetscErrorCode ierr; 445 Vec localX; 446 447 PetscFunctionBegin; 448 ierr = DMGetLocalVector(dm,&localX);CHKERRQ(ierr); 449 ierr = DMGlobalToLocalBegin(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr); 450 ierr = DMGlobalToLocalEnd(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr); 451 ierr = MatFDColoringApply(B,dm->fd,localX,str,dm);CHKERRQ(ierr); 452 ierr = DMRestoreLocalVector(dm,&localX);CHKERRQ(ierr); 453 /* Assemble true Jacobian; if it is different */ 454 if (A != B) { 455 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 456 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 457 } 458 ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 459 *str = SAME_NONZERO_PATTERN; 460 PetscFunctionReturn(0); 461 } 462 463 464 #undef __FUNCT__ 465 #define __FUNCT__ "DMDAJacobian" 466 static PetscErrorCode DMDAJacobian(DM dm,Vec x,Mat A,Mat B, MatStructure *str) 467 { 468 PetscErrorCode ierr; 469 Vec localX; 470 471 PetscFunctionBegin; 472 ierr = DMGetLocalVector(dm,&localX);CHKERRQ(ierr); 473 ierr = DMGlobalToLocalBegin(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr); 474 ierr = DMGlobalToLocalEnd(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr); 475 ierr = DMDAComputeJacobian1(dm,localX,B,dm->ctx);CHKERRQ(ierr); 476 ierr = DMRestoreLocalVector(dm,&localX);CHKERRQ(ierr); 477 /* Assemble true Jacobian; if it is different */ 478 if (A != B) { 479 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 480 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 481 } 482 ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 483 *str = SAME_NONZERO_PATTERN; 484 PetscFunctionReturn(0); 485 } 486 487 /*@C 488 DMDASetLocalJacobian - Caches in a DM a local Jacobian computation function 489 490 Logically Collective on DMDA 491 492 493 Input Parameter: 494 + da - initial distributed array 495 - lj - the local Jacobian 496 497 Level: intermediate 498 499 Notes: The routine SNESDMDAComputeFunction() uses this the cached function to evaluate the user provided function. 500 501 .keywords: distributed array, refine 502 503 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction() 504 @*/ 505 #undef __FUNCT__ 506 #define __FUNCT__ "DMDASetLocalJacobian" 507 PetscErrorCode DMDASetLocalJacobian(DM da,DMDALocalFunction1 lj) 508 { 509 PetscErrorCode ierr; 510 DM_DA *dd = (DM_DA*)da->data; 511 512 PetscFunctionBegin; 513 PetscValidHeaderSpecific(da,DM_CLASSID,1); 514 ierr = DMSetJacobian(da,DMDAJacobian);CHKERRQ(ierr); 515 dd->lj = lj; 516 PetscFunctionReturn(0); 517 } 518 519 #undef __FUNCT__ 520 #define __FUNCT__ "DMDAGetLocalFunction" 521 /*@C 522 DMDAGetLocalFunction - Gets from a DM a local function and its ADIC/ADIFOR Jacobian 523 524 Note Collective 525 526 Input Parameter: 527 . da - initial distributed array 528 529 Output Parameter: 530 . lf - the local function 531 532 Level: intermediate 533 534 .keywords: distributed array, refine 535 536 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalJacobian(), DMDASetLocalFunction() 537 @*/ 538 PetscErrorCode DMDAGetLocalFunction(DM da,DMDALocalFunction1 *lf) 539 { 540 DM_DA *dd = (DM_DA*)da->data; 541 PetscFunctionBegin; 542 PetscValidHeaderSpecific(da,DM_CLASSID,1); 543 if (lf) *lf = dd->lf; 544 PetscFunctionReturn(0); 545 } 546 547 #undef __FUNCT__ 548 #define __FUNCT__ "DMDAGetLocalJacobian" 549 /*@C 550 DMDAGetLocalJacobian - Gets from a DM a local jacobian 551 552 Not Collective 553 554 Input Parameter: 555 . da - initial distributed array 556 557 Output Parameter: 558 . lj - the local jacobian 559 560 Level: intermediate 561 562 .keywords: distributed array, refine 563 564 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalJacobian() 565 @*/ 566 PetscErrorCode DMDAGetLocalJacobian(DM da,DMDALocalFunction1 *lj) 567 { 568 DM_DA *dd = (DM_DA*)da->data; 569 PetscFunctionBegin; 570 PetscValidHeaderSpecific(da,DM_CLASSID,1); 571 if (lj) *lj = dd->lj; 572 PetscFunctionReturn(0); 573 } 574 575 #undef __FUNCT__ 576 #define __FUNCT__ "DMDAComputeFunction" 577 /*@ 578 DMDAComputeFunction - Evaluates a user provided function on each processor that 579 share a DMDA 580 581 Input Parameters: 582 + da - the DM that defines the grid 583 . vu - input vector 584 . vfu - output vector 585 - w - any user data 586 587 Notes: Does NOT do ghost updates on vu upon entry 588 589 This should eventually replace DMDAComputeFunction1 590 591 Level: advanced 592 593 .seealso: DMDAComputeJacobian1WithAdic() 594 595 @*/ 596 PetscErrorCode DMDAComputeFunction(DM da,PetscErrorCode (*lf)(void),Vec vu,Vec vfu,void *w) 597 { 598 PetscErrorCode ierr; 599 void *u,*fu; 600 DMDALocalInfo info; 601 PetscErrorCode (*f)(DMDALocalInfo*,void*,void*,void*) = (PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))lf; 602 603 PetscFunctionBegin; 604 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 605 ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr); 606 ierr = DMDAVecGetArray(da,vfu,&fu);CHKERRQ(ierr); 607 608 ierr = (*f)(&info,u,fu,w);CHKERRQ(ierr); 609 610 ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr); 611 ierr = DMDAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr); 612 PetscFunctionReturn(0); 613 } 614 615 #undef __FUNCT__ 616 #define __FUNCT__ "DMDAComputeFunctionLocal" 617 /*@C 618 DMDAComputeFunctionLocal - This is a universal function evaluation routine for 619 a local DM function. 620 621 Collective on DMDA 622 623 Input Parameters: 624 + da - the DM context 625 . func - The local function 626 . X - input vector 627 . F - function vector 628 - ctx - A user context 629 630 Level: intermediate 631 632 .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(), 633 SNESSetFunction(), SNESSetJacobian() 634 635 @*/ 636 PetscErrorCode DMDAComputeFunctionLocal(DM da, DMDALocalFunction1 func, Vec X, Vec F, void *ctx) 637 { 638 Vec localX; 639 DMDALocalInfo info; 640 void *u; 641 void *fu; 642 PetscErrorCode ierr; 643 644 PetscFunctionBegin; 645 ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); 646 /* 647 Scatter ghost points to local vector, using the 2-step process 648 DMGlobalToLocalBegin(), DMGlobalToLocalEnd(). 649 */ 650 ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); 651 ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); 652 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 653 ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr); 654 ierr = DMDAVecGetArray(da,F,&fu);CHKERRQ(ierr); 655 ierr = (*func)(&info,u,fu,ctx);CHKERRQ(ierr); 656 ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr); 657 ierr = DMDAVecRestoreArray(da,F,&fu);CHKERRQ(ierr); 658 ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); 659 PetscFunctionReturn(0); 660 } 661 662 #undef __FUNCT__ 663 #define __FUNCT__ "DMDAComputeFunctionLocalGhost" 664 /*@C 665 DMDAComputeFunctionLocalGhost - This is a universal function evaluation routine for 666 a local DM function, but the ghost values of the output are communicated and added. 667 668 Collective on DMDA 669 670 Input Parameters: 671 + da - the DM context 672 . func - The local function 673 . X - input vector 674 . F - function vector 675 - ctx - A user context 676 677 Level: intermediate 678 679 .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(), 680 SNESSetFunction(), SNESSetJacobian() 681 682 @*/ 683 PetscErrorCode DMDAComputeFunctionLocalGhost(DM da, DMDALocalFunction1 func, Vec X, Vec F, void *ctx) 684 { 685 Vec localX, localF; 686 DMDALocalInfo info; 687 void *u; 688 void *fu; 689 PetscErrorCode ierr; 690 691 PetscFunctionBegin; 692 ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); 693 ierr = DMGetLocalVector(da,&localF);CHKERRQ(ierr); 694 /* 695 Scatter ghost points to local vector, using the 2-step process 696 DMGlobalToLocalBegin(), DMGlobalToLocalEnd(). 697 */ 698 ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); 699 ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); 700 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 701 ierr = VecSet(localF, 0.0);CHKERRQ(ierr); 702 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 703 ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr); 704 ierr = DMDAVecGetArray(da,localF,&fu);CHKERRQ(ierr); 705 ierr = (*func)(&info,u,fu,ctx);CHKERRQ(ierr); 706 ierr = DMLocalToGlobalBegin(da,localF,ADD_VALUES,F);CHKERRQ(ierr); 707 ierr = DMLocalToGlobalEnd(da,localF,ADD_VALUES,F);CHKERRQ(ierr); 708 ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr); 709 ierr = DMDAVecRestoreArray(da,localF,&fu);CHKERRQ(ierr); 710 ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); 711 ierr = DMRestoreLocalVector(da,&localF);CHKERRQ(ierr); 712 PetscFunctionReturn(0); 713 } 714 715 #undef __FUNCT__ 716 #define __FUNCT__ "DMDAComputeFunction1" 717 /*@ 718 DMDAComputeFunction1 - Evaluates a user provided function on each processor that 719 share a DMDA 720 721 Input Parameters: 722 + da - the DM that defines the grid 723 . vu - input vector 724 . vfu - output vector 725 - w - any user data 726 727 Notes: Does NOT do ghost updates on vu upon entry 728 729 Level: advanced 730 731 .seealso: DMDAComputeJacobian1WithAdic() 732 733 @*/ 734 PetscErrorCode DMDAComputeFunction1(DM da,Vec vu,Vec vfu,void *w) 735 { 736 PetscErrorCode ierr; 737 void *u,*fu; 738 DMDALocalInfo info; 739 DM_DA *dd = (DM_DA*)da->data; 740 741 PetscFunctionBegin; 742 if (!dd->lf) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_NULL,"DMDASetLocalFunction() never called"); 743 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 744 ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr); 745 ierr = DMDAVecGetArray(da,vfu,&fu);CHKERRQ(ierr); 746 747 CHKMEMQ; 748 ierr = (*dd->lf)(&info,u,fu,w);CHKERRQ(ierr); 749 CHKMEMQ; 750 751 ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr); 752 ierr = DMDAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr); 753 PetscFunctionReturn(0); 754 } 755 756 #undef __FUNCT__ 757 #define __FUNCT__ "DMDAComputeFunctioniTest1" 758 PetscErrorCode DMDAComputeFunctioniTest1(DM da,void *w) 759 { 760 Vec vu,fu,fui; 761 PetscErrorCode ierr; 762 PetscInt i,n; 763 PetscScalar *ui; 764 PetscRandom rnd; 765 PetscReal norm; 766 767 PetscFunctionBegin; 768 ierr = DMGetLocalVector(da,&vu);CHKERRQ(ierr); 769 ierr = PetscRandomCreate(PETSC_COMM_SELF,&rnd);CHKERRQ(ierr); 770 ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr); 771 ierr = VecSetRandom(vu,rnd);CHKERRQ(ierr); 772 ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr); 773 774 ierr = DMGetGlobalVector(da,&fu);CHKERRQ(ierr); 775 ierr = DMGetGlobalVector(da,&fui);CHKERRQ(ierr); 776 777 ierr = DMDAComputeFunction1(da,vu,fu,w);CHKERRQ(ierr); 778 779 ierr = VecGetArray(fui,&ui);CHKERRQ(ierr); 780 ierr = VecGetLocalSize(fui,&n);CHKERRQ(ierr); 781 for (i=0; i<n; i++) { 782 ierr = DMDAComputeFunctioni1(da,i,vu,ui+i,w);CHKERRQ(ierr); 783 } 784 ierr = VecRestoreArray(fui,&ui);CHKERRQ(ierr); 785 786 ierr = VecAXPY(fui,-1.0,fu);CHKERRQ(ierr); 787 ierr = VecNorm(fui,NORM_2,&norm);CHKERRQ(ierr); 788 ierr = PetscPrintf(((PetscObject)da)->comm,"Norm of difference in vectors %G\n",norm);CHKERRQ(ierr); 789 ierr = VecView(fu,0);CHKERRQ(ierr); 790 ierr = VecView(fui,0);CHKERRQ(ierr); 791 792 ierr = DMRestoreLocalVector(da,&vu);CHKERRQ(ierr); 793 ierr = DMRestoreGlobalVector(da,&fu);CHKERRQ(ierr); 794 ierr = DMRestoreGlobalVector(da,&fui);CHKERRQ(ierr); 795 PetscFunctionReturn(0); 796 } 797 798 #undef __FUNCT__ 799 #define __FUNCT__ "DMDAComputeFunctioni1" 800 /*@ 801 DMDAComputeFunctioni1 - Evaluates a user provided point-wise function 802 803 Input Parameters: 804 + da - the DM that defines the grid 805 . i - the component of the function we wish to compute (must be local) 806 . vu - input vector 807 . vfu - output value 808 - w - any user data 809 810 Notes: Does NOT do ghost updates on vu upon entry 811 812 Level: advanced 813 814 .seealso: DMDAComputeJacobian1WithAdic() 815 816 @*/ 817 PetscErrorCode DMDAComputeFunctioni1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w) 818 { 819 PetscErrorCode ierr; 820 void *u; 821 DMDALocalInfo info; 822 MatStencil stencil; 823 DM_DA *dd = (DM_DA*)da->data; 824 825 PetscFunctionBegin; 826 827 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 828 ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr); 829 830 /* figure out stencil value from i */ 831 stencil.c = i % info.dof; 832 stencil.i = (i % (info.xm*info.dof))/info.dof; 833 stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof); 834 stencil.k = i/(info.xm*info.ym*info.dof); 835 836 ierr = (*dd->lfi)(&info,&stencil,u,vfu,w);CHKERRQ(ierr); 837 838 ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr); 839 PetscFunctionReturn(0); 840 } 841 842 #undef __FUNCT__ 843 #define __FUNCT__ "DMDAComputeFunctionib1" 844 /*@ 845 DMDAComputeFunctionib1 - Evaluates a user provided point-block function 846 847 Input Parameters: 848 + da - the DM that defines the grid 849 . i - the component of the function we wish to compute (must be local) 850 . vu - input vector 851 . vfu - output value 852 - w - any user data 853 854 Notes: Does NOT do ghost updates on vu upon entry 855 856 Level: advanced 857 858 .seealso: DMDAComputeJacobian1WithAdic() 859 860 @*/ 861 PetscErrorCode DMDAComputeFunctionib1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w) 862 { 863 PetscErrorCode ierr; 864 void *u; 865 DMDALocalInfo info; 866 MatStencil stencil; 867 DM_DA *dd = (DM_DA*)da->data; 868 869 PetscFunctionBegin; 870 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 871 ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr); 872 873 /* figure out stencil value from i */ 874 stencil.c = i % info.dof; 875 if (stencil.c) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONG,"Point-block functions can only be called for the entire block"); 876 stencil.i = (i % (info.xm*info.dof))/info.dof; 877 stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof); 878 stencil.k = i/(info.xm*info.ym*info.dof); 879 880 ierr = (*dd->lfib)(&info,&stencil,u,vfu,w);CHKERRQ(ierr); 881 882 ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr); 883 PetscFunctionReturn(0); 884 } 885 886 #if defined(new) 887 #undef __FUNCT__ 888 #define __FUNCT__ "DMDAGetDiagonal_MFFD" 889 /* 890 DMDAGetDiagonal_MFFD - Gets the diagonal for a matrix free matrix where local 891 function lives on a DMDA 892 893 y ~= (F(u + ha) - F(u))/h, 894 where F = nonlinear function, as set by SNESSetFunction() 895 u = current iterate 896 h = difference interval 897 */ 898 PetscErrorCode DMDAGetDiagonal_MFFD(DM da,Vec U,Vec a) 899 { 900 PetscScalar h,*aa,*ww,v; 901 PetscReal epsilon = PETSC_SQRT_MACHINE_EPSILON,umin = 100.0*PETSC_SQRT_MACHINE_EPSILON; 902 PetscErrorCode ierr; 903 PetscInt gI,nI; 904 MatStencil stencil; 905 DMDALocalInfo info; 906 907 PetscFunctionBegin; 908 ierr = (*ctx->func)(0,U,a,ctx->funcctx);CHKERRQ(ierr); 909 ierr = (*ctx->funcisetbase)(U,ctx->funcctx);CHKERRQ(ierr); 910 911 ierr = VecGetArray(U,&ww);CHKERRQ(ierr); 912 ierr = VecGetArray(a,&aa);CHKERRQ(ierr); 913 914 nI = 0; 915 h = ww[gI]; 916 if (h == 0.0) h = 1.0; 917 #if !defined(PETSC_USE_COMPLEX) 918 if (h < umin && h >= 0.0) h = umin; 919 else if (h < 0.0 && h > -umin) h = -umin; 920 #else 921 if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0) h = umin; 922 else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin; 923 #endif 924 h *= epsilon; 925 926 ww[gI] += h; 927 ierr = (*ctx->funci)(i,w,&v,ctx->funcctx);CHKERRQ(ierr); 928 aa[nI] = (v - aa[nI])/h; 929 ww[gI] -= h; 930 nI++; 931 } 932 ierr = VecRestoreArray(U,&ww);CHKERRQ(ierr); 933 ierr = VecRestoreArray(a,&aa);CHKERRQ(ierr); 934 PetscFunctionReturn(0); 935 } 936 #endif 937 938 #if defined(PETSC_HAVE_ADIC) 939 EXTERN_C_BEGIN 940 #include <adic/ad_utils.h> 941 EXTERN_C_END 942 943 #undef __FUNCT__ 944 #define __FUNCT__ "DMDAComputeJacobian1WithAdic" 945 /*@C 946 DMDAComputeJacobian1WithAdic - Evaluates a adiC provided Jacobian function on each processor that 947 share a DMDA 948 949 Input Parameters: 950 + da - the DM that defines the grid 951 . vu - input vector (ghosted) 952 . J - output matrix 953 - w - any user data 954 955 Level: advanced 956 957 Notes: Does NOT do ghost updates on vu upon entry 958 959 .seealso: DMDAComputeFunction1() 960 961 @*/ 962 PetscErrorCode DMDAComputeJacobian1WithAdic(DM da,Vec vu,Mat J,void *w) 963 { 964 PetscErrorCode ierr; 965 PetscInt gtdof,tdof; 966 PetscScalar *ustart; 967 DMDALocalInfo info; 968 void *ad_u,*ad_f,*ad_ustart,*ad_fstart; 969 ISColoring iscoloring; 970 971 PetscFunctionBegin; 972 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 973 974 PetscADResetIndep(); 975 976 /* get space for derivative objects. */ 977 ierr = DMDAGetAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,>dof);CHKERRQ(ierr); 978 ierr = DMDAGetAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr); 979 ierr = VecGetArray(vu,&ustart);CHKERRQ(ierr); 980 ierr = DMCreateColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr); 981 982 PetscADSetValueAndColor(ad_ustart,gtdof,iscoloring->colors,ustart); 983 984 ierr = VecRestoreArray(vu,&ustart);CHKERRQ(ierr); 985 ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); 986 ierr = PetscADIncrementTotalGradSize(iscoloring->n);CHKERRQ(ierr); 987 PetscADSetIndepDone(); 988 989 ierr = PetscLogEventBegin(DMDA_LocalADFunction,0,0,0,0);CHKERRQ(ierr); 990 ierr = (*dd->adic_lf)(&info,ad_u,ad_f,w);CHKERRQ(ierr); 991 ierr = PetscLogEventEnd(DMDA_LocalADFunction,0,0,0,0);CHKERRQ(ierr); 992 993 /* stick the values into the matrix */ 994 ierr = MatSetValuesAdic(J,(PetscScalar**)ad_fstart);CHKERRQ(ierr); 995 996 /* return space for derivative objects. */ 997 ierr = DMDARestoreAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,>dof);CHKERRQ(ierr); 998 ierr = DMDARestoreAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr); 999 PetscFunctionReturn(0); 1000 } 1001 1002 #undef __FUNCT__ 1003 #define __FUNCT__ "DMDAMultiplyByJacobian1WithAdic" 1004 /*@C 1005 DMDAMultiplyByJacobian1WithAdic - Applies an ADIC-provided Jacobian function to a vector on 1006 each processor that shares a DMDA. 1007 1008 Input Parameters: 1009 + da - the DM that defines the grid 1010 . vu - Jacobian is computed at this point (ghosted) 1011 . v - product is done on this vector (ghosted) 1012 . fu - output vector = J(vu)*v (not ghosted) 1013 - w - any user data 1014 1015 Notes: 1016 This routine does NOT do ghost updates on vu upon entry. 1017 1018 Level: advanced 1019 1020 .seealso: DMDAComputeFunction1() 1021 1022 @*/ 1023 PetscErrorCode DMDAMultiplyByJacobian1WithAdic(DM da,Vec vu,Vec v,Vec f,void *w) 1024 { 1025 PetscErrorCode ierr; 1026 PetscInt i,gtdof,tdof; 1027 PetscScalar *avu,*av,*af,*ad_vustart,*ad_fstart; 1028 DMDALocalInfo info; 1029 void *ad_vu,*ad_f; 1030 1031 PetscFunctionBegin; 1032 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 1033 1034 /* get space for derivative objects. */ 1035 ierr = DMDAGetAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,>dof);CHKERRQ(ierr); 1036 ierr = DMDAGetAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr); 1037 1038 /* copy input vector into derivative object */ 1039 ierr = VecGetArray(vu,&avu);CHKERRQ(ierr); 1040 ierr = VecGetArray(v,&av);CHKERRQ(ierr); 1041 for (i=0; i<gtdof; i++) { 1042 ad_vustart[2*i] = avu[i]; 1043 ad_vustart[2*i+1] = av[i]; 1044 } 1045 ierr = VecRestoreArray(vu,&avu);CHKERRQ(ierr); 1046 ierr = VecRestoreArray(v,&av);CHKERRQ(ierr); 1047 1048 PetscADResetIndep(); 1049 ierr = PetscADIncrementTotalGradSize(1);CHKERRQ(ierr); 1050 PetscADSetIndepDone(); 1051 1052 ierr = (*dd->adicmf_lf)(&info,ad_vu,ad_f,w);CHKERRQ(ierr); 1053 1054 /* stick the values into the vector */ 1055 ierr = VecGetArray(f,&af);CHKERRQ(ierr); 1056 for (i=0; i<tdof; i++) { 1057 af[i] = ad_fstart[2*i+1]; 1058 } 1059 ierr = VecRestoreArray(f,&af);CHKERRQ(ierr); 1060 1061 /* return space for derivative objects. */ 1062 ierr = DMDARestoreAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,>dof);CHKERRQ(ierr); 1063 ierr = DMDARestoreAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr); 1064 PetscFunctionReturn(0); 1065 } 1066 #endif 1067 1068 #undef __FUNCT__ 1069 #define __FUNCT__ "DMDAComputeJacobian1" 1070 /*@ 1071 DMDAComputeJacobian1 - Evaluates a local Jacobian function on each processor that 1072 share a DMDA 1073 1074 Input Parameters: 1075 + da - the DM that defines the grid 1076 . vu - input vector (ghosted) 1077 . J - output matrix 1078 - w - any user data 1079 1080 Notes: Does NOT do ghost updates on vu upon entry 1081 1082 Level: advanced 1083 1084 .seealso: DMDAComputeFunction1() 1085 1086 @*/ 1087 PetscErrorCode DMDAComputeJacobian1(DM da,Vec vu,Mat J,void *w) 1088 { 1089 PetscErrorCode ierr; 1090 void *u; 1091 DMDALocalInfo info; 1092 DM_DA *dd = (DM_DA*)da->data; 1093 1094 PetscFunctionBegin; 1095 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 1096 ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr); 1097 ierr = (*dd->lj)(&info,u,J,w);CHKERRQ(ierr); 1098 ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr); 1099 PetscFunctionReturn(0); 1100 } 1101 1102 1103 #undef __FUNCT__ 1104 #define __FUNCT__ "DMDAComputeJacobian1WithAdifor" 1105 /* 1106 DMDAComputeJacobian1WithAdifor - Evaluates a ADIFOR provided Jacobian local function on each processor that 1107 share a DMDA 1108 1109 Input Parameters: 1110 + da - the DM that defines the grid 1111 . vu - input vector (ghosted) 1112 . J - output matrix 1113 - w - any user data 1114 1115 Notes: Does NOT do ghost updates on vu upon entry 1116 1117 .seealso: DMDAComputeFunction1() 1118 1119 */ 1120 PetscErrorCode DMDAComputeJacobian1WithAdifor(DM da,Vec vu,Mat J,void *w) 1121 { 1122 PetscErrorCode ierr; 1123 PetscInt i,Nc,N; 1124 ISColoringValue *color; 1125 DMDALocalInfo info; 1126 PetscScalar *u,*g_u,*g_f,*f = 0,*p_u; 1127 ISColoring iscoloring; 1128 DM_DA *dd = (DM_DA*)da->data; 1129 void (*lf)(PetscInt*,DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*) = 1130 (void (*)(PetscInt*,DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*))*dd->adifor_lf; 1131 1132 PetscFunctionBegin; 1133 ierr = DMCreateColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr); 1134 Nc = iscoloring->n; 1135 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 1136 N = info.gxm*info.gym*info.gzm*info.dof; 1137 1138 /* get space for derivative objects. */ 1139 ierr = PetscMalloc(Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar),&g_u);CHKERRQ(ierr); 1140 ierr = PetscMemzero(g_u,Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar));CHKERRQ(ierr); 1141 p_u = g_u; 1142 color = iscoloring->colors; 1143 for (i=0; i<N; i++) { 1144 p_u[*color++] = 1.0; 1145 p_u += Nc; 1146 } 1147 ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); 1148 ierr = PetscMalloc2(Nc*info.xm*info.ym*info.zm*info.dof,PetscScalar,&g_f,info.xm*info.ym*info.zm*info.dof,PetscScalar,&f);CHKERRQ(ierr); 1149 1150 /* Seed the input array g_u with coloring information */ 1151 1152 ierr = VecGetArray(vu,&u);CHKERRQ(ierr); 1153 (lf)(&Nc,&info,u,g_u,&Nc,f,g_f,&Nc,w,&ierr);CHKERRQ(ierr); 1154 ierr = VecRestoreArray(vu,&u);CHKERRQ(ierr); 1155 1156 /* stick the values into the matrix */ 1157 /* PetscScalarView(Nc*info.xm*info.ym,g_f,0); */ 1158 ierr = MatSetValuesAdifor(J,Nc,g_f);CHKERRQ(ierr); 1159 1160 /* return space for derivative objects. */ 1161 ierr = PetscFree(g_u);CHKERRQ(ierr); 1162 ierr = PetscFree2(g_f,f);CHKERRQ(ierr); 1163 PetscFunctionReturn(0); 1164 } 1165 1166 #undef __FUNCT__ 1167 #define __FUNCT__ "DMDAFormJacobianLocal" 1168 /*@C 1169 DMDAFormjacobianLocal - This is a universal Jacobian evaluation routine for 1170 a local DM function. 1171 1172 Collective on DMDA 1173 1174 Input Parameters: 1175 + da - the DM context 1176 . func - The local function 1177 . X - input vector 1178 . J - Jacobian matrix 1179 - ctx - A user context 1180 1181 Level: intermediate 1182 1183 .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(), 1184 SNESSetFunction(), SNESSetJacobian() 1185 1186 @*/ 1187 PetscErrorCode DMDAFormJacobianLocal(DM da, DMDALocalFunction1 func, Vec X, Mat J, void *ctx) 1188 { 1189 Vec localX; 1190 DMDALocalInfo info; 1191 void *u; 1192 PetscErrorCode ierr; 1193 1194 PetscFunctionBegin; 1195 ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); 1196 /* 1197 Scatter ghost points to local vector, using the 2-step process 1198 DMGlobalToLocalBegin(), DMGlobalToLocalEnd(). 1199 */ 1200 ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); 1201 ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); 1202 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 1203 ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr); 1204 ierr = (*func)(&info,u,J,ctx);CHKERRQ(ierr); 1205 ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr); 1206 ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); 1207 PetscFunctionReturn(0); 1208 } 1209 1210 #undef __FUNCT__ 1211 #define __FUNCT__ "DMDAMultiplyByJacobian1WithAD" 1212 /*@C 1213 DMDAMultiplyByJacobian1WithAD - Applies a Jacobian function supplied by ADIFOR or ADIC 1214 to a vector on each processor that shares a DMDA. 1215 1216 Input Parameters: 1217 + da - the DM that defines the grid 1218 . vu - Jacobian is computed at this point (ghosted) 1219 . v - product is done on this vector (ghosted) 1220 . fu - output vector = J(vu)*v (not ghosted) 1221 - w - any user data 1222 1223 Notes: 1224 This routine does NOT do ghost updates on vu and v upon entry. 1225 1226 Automatically calls DMDAMultiplyByJacobian1WithAdifor() or DMDAMultiplyByJacobian1WithAdic() 1227 depending on whether DMDASetLocalAdicMFFunction() or DMDASetLocalAdiforMFFunction() was called. 1228 1229 Level: advanced 1230 1231 .seealso: DMDAComputeFunction1(), DMDAMultiplyByJacobian1WithAdifor(), DMDAMultiplyByJacobian1WithAdic() 1232 1233 @*/ 1234 PetscErrorCode DMDAMultiplyByJacobian1WithAD(DM da,Vec u,Vec v,Vec f,void *w) 1235 { 1236 PetscErrorCode ierr; 1237 DM_DA *dd = (DM_DA*)da->data; 1238 1239 PetscFunctionBegin; 1240 if (dd->adicmf_lf) { 1241 #if defined(PETSC_HAVE_ADIC) 1242 ierr = DMDAMultiplyByJacobian1WithAdic(da,u,v,f,w);CHKERRQ(ierr); 1243 #else 1244 SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP_SYS,"Requires ADIC to be installed and cannot use complex numbers"); 1245 #endif 1246 } else if (dd->adiformf_lf) { 1247 ierr = DMDAMultiplyByJacobian1WithAdifor(da,u,v,f,w);CHKERRQ(ierr); 1248 } else { 1249 SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ORDER,"Must call DMDASetLocalAdiforMFFunction() or DMDASetLocalAdicMFFunction() before using"); 1250 } 1251 PetscFunctionReturn(0); 1252 } 1253 1254 1255 #undef __FUNCT__ 1256 #define __FUNCT__ "DMDAMultiplyByJacobian1WithAdifor" 1257 /*@C 1258 DMDAMultiplyByJacobian1WithAdifor - Applies a ADIFOR provided Jacobian function on each processor that 1259 share a DM to a vector 1260 1261 Input Parameters: 1262 + da - the DM that defines the grid 1263 . vu - Jacobian is computed at this point (ghosted) 1264 . v - product is done on this vector (ghosted) 1265 . fu - output vector = J(vu)*v (not ghosted) 1266 - w - any user data 1267 1268 Notes: Does NOT do ghost updates on vu and v upon entry 1269 1270 Level: advanced 1271 1272 .seealso: DMDAComputeFunction1() 1273 1274 @*/ 1275 PetscErrorCode DMDAMultiplyByJacobian1WithAdifor(DM da,Vec u,Vec v,Vec f,void *w) 1276 { 1277 PetscErrorCode ierr; 1278 PetscScalar *au,*av,*af,*awork; 1279 Vec work; 1280 DMDALocalInfo info; 1281 DM_DA *dd = (DM_DA*)da->data; 1282 void (*lf)(DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*) = 1283 (void (*)(DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*))*dd->adiformf_lf; 1284 1285 PetscFunctionBegin; 1286 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 1287 1288 ierr = DMGetGlobalVector(da,&work);CHKERRQ(ierr); 1289 ierr = VecGetArray(u,&au);CHKERRQ(ierr); 1290 ierr = VecGetArray(v,&av);CHKERRQ(ierr); 1291 ierr = VecGetArray(f,&af);CHKERRQ(ierr); 1292 ierr = VecGetArray(work,&awork);CHKERRQ(ierr); 1293 (lf)(&info,au,av,awork,af,w,&ierr);CHKERRQ(ierr); 1294 ierr = VecRestoreArray(u,&au);CHKERRQ(ierr); 1295 ierr = VecRestoreArray(v,&av);CHKERRQ(ierr); 1296 ierr = VecRestoreArray(f,&af);CHKERRQ(ierr); 1297 ierr = VecRestoreArray(work,&awork);CHKERRQ(ierr); 1298 ierr = DMRestoreGlobalVector(da,&work);CHKERRQ(ierr); 1299 1300 PetscFunctionReturn(0); 1301 } 1302 1303 #undef __FUNCT__ 1304 #define __FUNCT__ "DMSetUp_DA_2D" 1305 PetscErrorCode DMSetUp_DA_2D(DM da) 1306 { 1307 DM_DA *dd = (DM_DA*)da->data; 1308 const PetscInt M = dd->M; 1309 const PetscInt N = dd->N; 1310 PetscInt m = dd->m; 1311 PetscInt n = dd->n; 1312 const PetscInt dof = dd->w; 1313 const PetscInt s = dd->s; 1314 const DMDABoundaryType bx = dd->bx; 1315 const DMDABoundaryType by = dd->by; 1316 const DMDAStencilType stencil_type = dd->stencil_type; 1317 PetscInt *lx = dd->lx; 1318 PetscInt *ly = dd->ly; 1319 MPI_Comm comm; 1320 PetscMPIInt rank,size; 1321 PetscInt xs,xe,ys,ye,x,y,Xs,Xe,Ys,Ye,start,end,IXs,IXe,IYs,IYe; 1322 PetscInt up,down,left,right,i,n0,n1,n2,n3,n5,n6,n7,n8,*idx,nn,*idx_cpy; 1323 const PetscInt *idx_full; 1324 PetscInt xbase,*bases,*ldims,j,x_t,y_t,s_t,base,count; 1325 PetscInt s_x,s_y; /* s proportionalized to w */ 1326 PetscInt sn0 = 0,sn2 = 0,sn6 = 0,sn8 = 0; 1327 Vec local,global; 1328 VecScatter ltog,gtol; 1329 IS to,from,ltogis; 1330 PetscErrorCode ierr; 1331 1332 PetscFunctionBegin; 1333 if (dof < 1) SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof); 1334 if (s < 0) SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s); 1335 ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 1336 #if !defined(PETSC_USE_64BIT_INDICES) 1337 if (((Petsc64bitInt) M)*((Petsc64bitInt) N)*((Petsc64bitInt) dof) > (Petsc64bitInt) PETSC_MPI_INT_MAX) SETERRQ3(comm,PETSC_ERR_INT_OVERFLOW,"Mesh of %D by %D by %D (dof) is too large for 32 bit indices",M,N,dof); 1338 #endif 1339 1340 if (dof < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof); 1341 if (s < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s); 1342 1343 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1344 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1345 1346 dd->dim = 2; 1347 ierr = PetscMalloc(dof*sizeof(char*),&dd->fieldname);CHKERRQ(ierr); 1348 ierr = PetscMemzero(dd->fieldname,dof*sizeof(char*));CHKERRQ(ierr); 1349 1350 if (m != PETSC_DECIDE) { 1351 if (m < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in X direction: %D",m); 1352 else if (m > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in X direction: %D %d",m,size); 1353 } 1354 if (n != PETSC_DECIDE) { 1355 if (n < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Y direction: %D",n); 1356 else if (n > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Y direction: %D %d",n,size); 1357 } 1358 1359 if (m == PETSC_DECIDE || n == PETSC_DECIDE) { 1360 if (n != PETSC_DECIDE) { 1361 m = size/n; 1362 } else if (m != PETSC_DECIDE) { 1363 n = size/m; 1364 } else { 1365 /* try for squarish distribution */ 1366 m = (PetscInt)(0.5 + sqrt(((double)M)*((double)size)/((double)N))); 1367 if (!m) m = 1; 1368 while (m > 0) { 1369 n = size/m; 1370 if (m*n == size) break; 1371 m--; 1372 } 1373 if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;} 1374 } 1375 if (m*n != size) SETERRQ(comm,PETSC_ERR_PLIB,"Unable to create partition, check the size of the communicator and input m and n "); 1376 } else if (m*n != size) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Given Bad partition"); 1377 1378 if (M < m) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in x direction is too fine! %D %D",M,m); 1379 if (N < n) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in y direction is too fine! %D %D",N,n); 1380 1381 /* 1382 Determine locally owned region 1383 xs is the first local node number, x is the number of local nodes 1384 */ 1385 if (!lx) { 1386 ierr = PetscMalloc(m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr); 1387 lx = dd->lx; 1388 for (i=0; i<m; i++) { 1389 lx[i] = M/m + ((M % m) > i); 1390 } 1391 } 1392 x = lx[rank % m]; 1393 xs = 0; 1394 for (i=0; i<(rank % m); i++) { 1395 xs += lx[i]; 1396 } 1397 #if defined(PETSC_USE_DEBUG) 1398 left = xs; 1399 for (i=(rank % m); i<m; i++) { 1400 left += lx[i]; 1401 } 1402 if (left != M) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Sum of lx across processors not equal to M: %D %D",left,M); 1403 #endif 1404 1405 /* 1406 Determine locally owned region 1407 ys is the first local node number, y is the number of local nodes 1408 */ 1409 if (!ly) { 1410 ierr = PetscMalloc(n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr); 1411 ly = dd->ly; 1412 for (i=0; i<n; i++) { 1413 ly[i] = N/n + ((N % n) > i); 1414 } 1415 } 1416 y = ly[rank/m]; 1417 ys = 0; 1418 for (i=0; i<(rank/m); i++) { 1419 ys += ly[i]; 1420 } 1421 #if defined(PETSC_USE_DEBUG) 1422 left = ys; 1423 for (i=(rank/m); i<n; i++) { 1424 left += ly[i]; 1425 } 1426 if (left != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Sum of ly across processors not equal to N: %D %D",left,N); 1427 #endif 1428 1429 /* 1430 check if the scatter requires more than one process neighbor or wraps around 1431 the domain more than once 1432 */ 1433 if ((x < s) && ((m > 1) || (bx == DMDA_BOUNDARY_PERIODIC))) { 1434 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local x-width of domain x %D is smaller than stencil width s %D",x,s); 1435 } 1436 if ((y < s) && ((n > 1) || (by == DMDA_BOUNDARY_PERIODIC))) { 1437 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local y-width of domain y %D is smaller than stencil width s %D",y,s); 1438 } 1439 xe = xs + x; 1440 ye = ys + y; 1441 1442 /* determine ghost region (Xs) and region scattered into (IXs) */ 1443 /* Assume No Periodicity */ 1444 if (xs-s > 0) { Xs = xs - s; IXs = xs - s; } else { Xs = 0; IXs = 0; } 1445 if (xe+s <= M) { Xe = xe + s; IXe = xe + s; } else { Xe = M; IXe = M; } 1446 if (ys-s > 0) { Ys = ys - s; IYs = ys - s; } else { Ys = 0; IYs = 0; } 1447 if (ye+s <= N) { Ye = ye + s; IYe = ye + s; } else { Ye = N; IYe = N; } 1448 1449 /* fix for periodicity/ghosted */ 1450 if (bx) { Xs = xs - s; Xe = xe + s; } 1451 if (bx == DMDA_BOUNDARY_PERIODIC) { IXs = xs - s; IXe = xe + s; } 1452 if (by) { Ys = ys - s; Ye = ye + s; } 1453 if (by == DMDA_BOUNDARY_PERIODIC) { IYs = ys - s; IYe = ye + s; } 1454 1455 /* Resize all X parameters to reflect w */ 1456 s_x = s; 1457 s_y = s; 1458 1459 /* determine starting point of each processor */ 1460 nn = x*y; 1461 ierr = PetscMalloc2(size+1,PetscInt,&bases,size,PetscInt,&ldims);CHKERRQ(ierr); 1462 ierr = MPI_Allgather(&nn,1,MPIU_INT,ldims,1,MPIU_INT,comm);CHKERRQ(ierr); 1463 bases[0] = 0; 1464 for (i=1; i<=size; i++) { 1465 bases[i] = ldims[i-1]; 1466 } 1467 for (i=1; i<=size; i++) { 1468 bases[i] += bases[i-1]; 1469 } 1470 base = bases[rank]*dof; 1471 1472 /* allocate the base parallel and sequential vectors */ 1473 dd->Nlocal = x*y*dof; 1474 ierr = VecCreateMPIWithArray(comm,dd->Nlocal,PETSC_DECIDE,0,&global);CHKERRQ(ierr); 1475 ierr = VecSetBlockSize(global,dof);CHKERRQ(ierr); 1476 dd->nlocal = (Xe-Xs)*(Ye-Ys)*dof; 1477 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dd->nlocal,0,&local);CHKERRQ(ierr); 1478 ierr = VecSetBlockSize(local,dof);CHKERRQ(ierr); 1479 1480 /* generate appropriate vector scatters */ 1481 /* local to global inserts non-ghost point region into global */ 1482 ierr = VecGetOwnershipRange(global,&start,&end);CHKERRQ(ierr); 1483 ierr = ISCreateStride(comm,x*y*dof,start,1,&to);CHKERRQ(ierr); 1484 1485 count = x*y; 1486 ierr = PetscMalloc(x*y*sizeof(PetscInt),&idx);CHKERRQ(ierr); 1487 left = xs - Xs; right = left + x; 1488 down = ys - Ys; up = down + y; 1489 count = 0; 1490 for (i=down; i<up; i++) { 1491 for (j=left; j<right; j++) { 1492 idx[count++] = i*(Xe-Xs) + j; 1493 } 1494 } 1495 1496 ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr); 1497 ierr = VecScatterCreate(local,from,global,to,<og);CHKERRQ(ierr); 1498 ierr = PetscLogObjectParent(dd,ltog);CHKERRQ(ierr); 1499 ierr = ISDestroy(&from);CHKERRQ(ierr); 1500 ierr = ISDestroy(&to);CHKERRQ(ierr); 1501 1502 /* global to local must include ghost points within the domain, 1503 but not ghost points outside the domain that aren't periodic */ 1504 if (stencil_type == DMDA_STENCIL_BOX) { 1505 count = (IXe-IXs)*(IYe-IYs); 1506 ierr = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr); 1507 1508 left = IXs - Xs; right = left + (IXe-IXs); 1509 down = IYs - Ys; up = down + (IYe-IYs); 1510 count = 0; 1511 for (i=down; i<up; i++) { 1512 for (j=left; j<right; j++) { 1513 idx[count++] = j + i*(Xe-Xs); 1514 } 1515 } 1516 ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr); 1517 1518 } else { 1519 /* must drop into cross shape region */ 1520 /* ---------| 1521 | top | 1522 |--- ---| up 1523 | middle | 1524 | | 1525 ---- ---- down 1526 | bottom | 1527 ----------- 1528 Xs xs xe Xe */ 1529 count = (ys-IYs)*x + y*(IXe-IXs) + (IYe-ye)*x; 1530 ierr = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr); 1531 1532 left = xs - Xs; right = left + x; 1533 down = ys - Ys; up = down + y; 1534 count = 0; 1535 /* bottom */ 1536 for (i=(IYs-Ys); i<down; i++) { 1537 for (j=left; j<right; j++) { 1538 idx[count++] = j + i*(Xe-Xs); 1539 } 1540 } 1541 /* middle */ 1542 for (i=down; i<up; i++) { 1543 for (j=(IXs-Xs); j<(IXe-Xs); j++) { 1544 idx[count++] = j + i*(Xe-Xs); 1545 } 1546 } 1547 /* top */ 1548 for (i=up; i<up+IYe-ye; i++) { 1549 for (j=left; j<right; j++) { 1550 idx[count++] = j + i*(Xe-Xs); 1551 } 1552 } 1553 ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr); 1554 } 1555 1556 1557 /* determine who lies on each side of us stored in n6 n7 n8 1558 n3 n5 1559 n0 n1 n2 1560 */ 1561 1562 /* Assume the Non-Periodic Case */ 1563 n1 = rank - m; 1564 if (rank % m) { 1565 n0 = n1 - 1; 1566 } else { 1567 n0 = -1; 1568 } 1569 if ((rank+1) % m) { 1570 n2 = n1 + 1; 1571 n5 = rank + 1; 1572 n8 = rank + m + 1; if (n8 >= m*n) n8 = -1; 1573 } else { 1574 n2 = -1; n5 = -1; n8 = -1; 1575 } 1576 if (rank % m) { 1577 n3 = rank - 1; 1578 n6 = n3 + m; if (n6 >= m*n) n6 = -1; 1579 } else { 1580 n3 = -1; n6 = -1; 1581 } 1582 n7 = rank + m; if (n7 >= m*n) n7 = -1; 1583 1584 if (bx == DMDA_BOUNDARY_PERIODIC && by == DMDA_BOUNDARY_PERIODIC) { 1585 /* Modify for Periodic Cases */ 1586 /* Handle all four corners */ 1587 if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m-1; 1588 if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0; 1589 if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size-m; 1590 if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size-1; 1591 1592 /* Handle Top and Bottom Sides */ 1593 if (n1 < 0) n1 = rank + m * (n-1); 1594 if (n7 < 0) n7 = rank - m * (n-1); 1595 if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1; 1596 if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1; 1597 if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1; 1598 if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1; 1599 1600 /* Handle Left and Right Sides */ 1601 if (n3 < 0) n3 = rank + (m-1); 1602 if (n5 < 0) n5 = rank - (m-1); 1603 if ((n1 >= 0) && (n0 < 0)) n0 = rank-1; 1604 if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1; 1605 if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1; 1606 if ((n7 >= 0) && (n8 < 0)) n8 = rank+1; 1607 } else if (by == DMDA_BOUNDARY_PERIODIC) { /* Handle Top and Bottom Sides */ 1608 if (n1 < 0) n1 = rank + m * (n-1); 1609 if (n7 < 0) n7 = rank - m * (n-1); 1610 if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1; 1611 if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1; 1612 if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1; 1613 if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1; 1614 } else if (bx == DMDA_BOUNDARY_PERIODIC) { /* Handle Left and Right Sides */ 1615 if (n3 < 0) n3 = rank + (m-1); 1616 if (n5 < 0) n5 = rank - (m-1); 1617 if ((n1 >= 0) && (n0 < 0)) n0 = rank-1; 1618 if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1; 1619 if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1; 1620 if ((n7 >= 0) && (n8 < 0)) n8 = rank+1; 1621 } 1622 1623 ierr = PetscMalloc(9*sizeof(PetscInt),&dd->neighbors);CHKERRQ(ierr); 1624 dd->neighbors[0] = n0; 1625 dd->neighbors[1] = n1; 1626 dd->neighbors[2] = n2; 1627 dd->neighbors[3] = n3; 1628 dd->neighbors[4] = rank; 1629 dd->neighbors[5] = n5; 1630 dd->neighbors[6] = n6; 1631 dd->neighbors[7] = n7; 1632 dd->neighbors[8] = n8; 1633 1634 if (stencil_type == DMDA_STENCIL_STAR) { 1635 /* save corner processor numbers */ 1636 sn0 = n0; sn2 = n2; sn6 = n6; sn8 = n8; 1637 n0 = n2 = n6 = n8 = -1; 1638 } 1639 1640 ierr = PetscMalloc((Xe-Xs)*(Ye-Ys)*sizeof(PetscInt),&idx);CHKERRQ(ierr); 1641 ierr = PetscLogObjectMemory(da,(Xe-Xs)*(Ye-Ys)*sizeof(PetscInt));CHKERRQ(ierr); 1642 1643 nn = 0; 1644 xbase = bases[rank]; 1645 for (i=1; i<=s_y; i++) { 1646 if (n0 >= 0) { /* left below */ 1647 x_t = lx[n0 % m]; 1648 y_t = ly[(n0/m)]; 1649 s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x; 1650 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1651 } 1652 if (n1 >= 0) { /* directly below */ 1653 x_t = x; 1654 y_t = ly[(n1/m)]; 1655 s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t; 1656 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 1657 } 1658 if (n2 >= 0) { /* right below */ 1659 x_t = lx[n2 % m]; 1660 y_t = ly[(n2/m)]; 1661 s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t; 1662 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1663 } 1664 } 1665 1666 for (i=0; i<y; i++) { 1667 if (n3 >= 0) { /* directly left */ 1668 x_t = lx[n3 % m]; 1669 /* y_t = y; */ 1670 s_t = bases[n3] + (i+1)*x_t - s_x; 1671 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1672 } 1673 1674 for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */ 1675 1676 if (n5 >= 0) { /* directly right */ 1677 x_t = lx[n5 % m]; 1678 /* y_t = y; */ 1679 s_t = bases[n5] + (i)*x_t; 1680 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1681 } 1682 } 1683 1684 for (i=1; i<=s_y; i++) { 1685 if (n6 >= 0) { /* left above */ 1686 x_t = lx[n6 % m]; 1687 /* y_t = ly[(n6/m)]; */ 1688 s_t = bases[n6] + (i)*x_t - s_x; 1689 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1690 } 1691 if (n7 >= 0) { /* directly above */ 1692 x_t = x; 1693 /* y_t = ly[(n7/m)]; */ 1694 s_t = bases[n7] + (i-1)*x_t; 1695 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 1696 } 1697 if (n8 >= 0) { /* right above */ 1698 x_t = lx[n8 % m]; 1699 /* y_t = ly[(n8/m)]; */ 1700 s_t = bases[n8] + (i-1)*x_t; 1701 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1702 } 1703 } 1704 1705 ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_COPY_VALUES,&from);CHKERRQ(ierr); 1706 ierr = VecScatterCreate(global,from,local,to,>ol);CHKERRQ(ierr); 1707 ierr = PetscLogObjectParent(da,gtol);CHKERRQ(ierr); 1708 ierr = ISDestroy(&to);CHKERRQ(ierr); 1709 ierr = ISDestroy(&from);CHKERRQ(ierr); 1710 1711 if (stencil_type == DMDA_STENCIL_STAR) { 1712 n0 = sn0; n2 = sn2; n6 = sn6; n8 = sn8; 1713 } 1714 1715 if ((stencil_type == DMDA_STENCIL_STAR) || 1716 (bx && bx != DMDA_BOUNDARY_PERIODIC) || 1717 (by && by != DMDA_BOUNDARY_PERIODIC)) { 1718 /* 1719 Recompute the local to global mappings, this time keeping the 1720 information about the cross corner processor numbers and any ghosted 1721 but not periodic indices. 1722 */ 1723 nn = 0; 1724 xbase = bases[rank]; 1725 for (i=1; i<=s_y; i++) { 1726 if (n0 >= 0) { /* left below */ 1727 x_t = lx[n0 % m]; 1728 y_t = ly[(n0/m)]; 1729 s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x; 1730 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1731 } else if (xs-Xs > 0 && ys-Ys > 0) { 1732 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 1733 } 1734 if (n1 >= 0) { /* directly below */ 1735 x_t = x; 1736 y_t = ly[(n1/m)]; 1737 s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t; 1738 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 1739 } else if (ys-Ys > 0) { 1740 for (j=0; j<x; j++) { idx[nn++] = -1;} 1741 } 1742 if (n2 >= 0) { /* right below */ 1743 x_t = lx[n2 % m]; 1744 y_t = ly[(n2/m)]; 1745 s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t; 1746 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1747 } else if (Xe-xe> 0 && ys-Ys > 0) { 1748 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 1749 } 1750 } 1751 1752 for (i=0; i<y; i++) { 1753 if (n3 >= 0) { /* directly left */ 1754 x_t = lx[n3 % m]; 1755 /* y_t = y; */ 1756 s_t = bases[n3] + (i+1)*x_t - s_x; 1757 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1758 } else if (xs-Xs > 0) { 1759 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 1760 } 1761 1762 for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */ 1763 1764 if (n5 >= 0) { /* directly right */ 1765 x_t = lx[n5 % m]; 1766 /* y_t = y; */ 1767 s_t = bases[n5] + (i)*x_t; 1768 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1769 } else if (Xe-xe > 0) { 1770 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 1771 } 1772 } 1773 1774 for (i=1; i<=s_y; i++) { 1775 if (n6 >= 0) { /* left above */ 1776 x_t = lx[n6 % m]; 1777 /* y_t = ly[(n6/m)]; */ 1778 s_t = bases[n6] + (i)*x_t - s_x; 1779 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1780 } else if (xs-Xs > 0 && Ye-ye > 0) { 1781 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 1782 } 1783 if (n7 >= 0) { /* directly above */ 1784 x_t = x; 1785 /* y_t = ly[(n7/m)]; */ 1786 s_t = bases[n7] + (i-1)*x_t; 1787 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 1788 } else if (Ye-ye > 0) { 1789 for (j=0; j<x; j++) { idx[nn++] = -1;} 1790 } 1791 if (n8 >= 0) { /* right above */ 1792 x_t = lx[n8 % m]; 1793 /* y_t = ly[(n8/m)]; */ 1794 s_t = bases[n8] + (i-1)*x_t; 1795 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 1796 } else if (Xe-xe > 0 && Ye-ye > 0) { 1797 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 1798 } 1799 } 1800 } 1801 /* 1802 Set the local to global ordering in the global vector, this allows use 1803 of VecSetValuesLocal(). 1804 */ 1805 ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_OWN_POINTER,<ogis);CHKERRQ(ierr); 1806 ierr = PetscMalloc(nn*dof*sizeof(PetscInt),&idx_cpy);CHKERRQ(ierr); 1807 ierr = PetscLogObjectMemory(da,nn*dof*sizeof(PetscInt));CHKERRQ(ierr); 1808 ierr = ISGetIndices(ltogis, &idx_full); 1809 ierr = PetscMemcpy(idx_cpy,idx_full,nn*dof*sizeof(PetscInt));CHKERRQ(ierr); 1810 ierr = ISRestoreIndices(ltogis, &idx_full); 1811 ierr = ISLocalToGlobalMappingCreateIS(ltogis,&da->ltogmap);CHKERRQ(ierr); 1812 ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr); 1813 ierr = ISDestroy(<ogis);CHKERRQ(ierr); 1814 ierr = ISLocalToGlobalMappingBlock(da->ltogmap,dd->w,&da->ltogmapb);CHKERRQ(ierr); 1815 ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr); 1816 1817 ierr = PetscFree2(bases,ldims);CHKERRQ(ierr); 1818 dd->m = m; dd->n = n; 1819 /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */ 1820 dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1; 1821 dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1; 1822 1823 ierr = VecDestroy(&local);CHKERRQ(ierr); 1824 ierr = VecDestroy(&global);CHKERRQ(ierr); 1825 1826 dd->gtol = gtol; 1827 dd->ltog = ltog; 1828 dd->idx = idx_cpy; 1829 dd->Nl = nn*dof; 1830 dd->base = base; 1831 da->ops->view = DMView_DA_2d; 1832 dd->ltol = PETSC_NULL; 1833 dd->ao = PETSC_NULL; 1834 1835 PetscFunctionReturn(0); 1836 } 1837 1838 #undef __FUNCT__ 1839 #define __FUNCT__ "DMDACreate2d" 1840 /*@C 1841 DMDACreate2d - Creates an object that will manage the communication of two-dimensional 1842 regular array data that is distributed across some processors. 1843 1844 Collective on MPI_Comm 1845 1846 Input Parameters: 1847 + comm - MPI communicator 1848 . bx,by - type of ghost nodes the array have. 1849 Use one of DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_GHOSTED, DMDA_BOUNDARY_PERIODIC. 1850 . stencil_type - stencil type. Use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR. 1851 . M,N - global dimension in each direction of the array (use -M and or -N to indicate that it may be set to a different value 1852 from the command line with -da_grid_x <M> -da_grid_y <N>) 1853 . m,n - corresponding number of processors in each dimension 1854 (or PETSC_DECIDE to have calculated) 1855 . dof - number of degrees of freedom per node 1856 . s - stencil width 1857 - lx, ly - arrays containing the number of nodes in each cell along 1858 the x and y coordinates, or PETSC_NULL. If non-null, these 1859 must be of length as m and n, and the corresponding 1860 m and n cannot be PETSC_DECIDE. The sum of the lx[] entries 1861 must be M, and the sum of the ly[] entries must be N. 1862 1863 Output Parameter: 1864 . da - the resulting distributed array object 1865 1866 Options Database Key: 1867 + -da_view - Calls DMView() at the conclusion of DMDACreate2d() 1868 . -da_grid_x <nx> - number of grid points in x direction, if M < 0 1869 . -da_grid_y <ny> - number of grid points in y direction, if N < 0 1870 . -da_processors_x <nx> - number of processors in x direction 1871 . -da_processors_y <ny> - number of processors in y direction 1872 . -da_refine_x <rx> - refinement ratio in x direction 1873 . -da_refine_y <ry> - refinement ratio in y direction 1874 - -da_refine <n> - refine the DMDA n times before creating, if M or N < 0 1875 1876 1877 Level: beginner 1878 1879 Notes: 1880 The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the 1881 standard 5-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes 1882 the standard 9-pt stencil. 1883 1884 The array data itself is NOT stored in the DMDA, it is stored in Vec objects; 1885 The appropriate vector objects can be obtained with calls to DMCreateGlobalVector() 1886 and DMCreateLocalVector() and calls to VecDuplicate() if more are needed. 1887 1888 .keywords: distributed array, create, two-dimensional 1889 1890 .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate3d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(), 1891 DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMDALocalToLocalBegin(), DMDALocalToLocalEnd(), DMDASetRefinementFactor(), 1892 DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMLoad(), DMDAGetOwnershipRanges() 1893 1894 @*/ 1895 1896 PetscErrorCode DMDACreate2d(MPI_Comm comm,DMDABoundaryType bx,DMDABoundaryType by,DMDAStencilType stencil_type, 1897 PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da) 1898 { 1899 PetscErrorCode ierr; 1900 1901 PetscFunctionBegin; 1902 ierr = DMDACreate(comm, da);CHKERRQ(ierr); 1903 ierr = DMDASetDim(*da, 2);CHKERRQ(ierr); 1904 ierr = DMDASetSizes(*da, M, N, 1);CHKERRQ(ierr); 1905 ierr = DMDASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr); 1906 ierr = DMDASetBoundaryType(*da, bx, by, DMDA_BOUNDARY_NONE);CHKERRQ(ierr); 1907 ierr = DMDASetDof(*da, dof);CHKERRQ(ierr); 1908 ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr); 1909 ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr); 1910 ierr = DMDASetOwnershipRanges(*da, lx, ly, PETSC_NULL);CHKERRQ(ierr); 1911 /* This violates the behavior for other classes, but right now users expect negative dimensions to be handled this way */ 1912 ierr = DMSetFromOptions(*da);CHKERRQ(ierr); 1913 ierr = DMSetUp(*da);CHKERRQ(ierr); 1914 ierr = DMView_DA_Private(*da);CHKERRQ(ierr); 1915 PetscFunctionReturn(0); 1916 } 1917