1 2 #ifdef PETSC_RCS_HEADER 3 static char vcid[] = "$Id: fdmatrix.c,v 1.37 1998/10/06 03:23:20 bsmith Exp bsmith $"; 4 #endif 5 6 /* 7 This is where the abstract matrix operations are defined that are 8 used for finite difference computations of Jacobians using coloring. 9 */ 10 11 #include "petsc.h" 12 #include "src/mat/matimpl.h" /*I "mat.h" I*/ 13 #include "src/vec/vecimpl.h" 14 15 #undef __FUNC__ 16 #define __FUNC__ "MatFDColoringView_Draw" 17 static int MatFDColoringView_Draw(MatFDColoring fd,Viewer viewer) 18 { 19 int ierr,i,j,pause; 20 PetscTruth isnull; 21 Draw draw; 22 double xr,yr,xl,yl,h,w,x,y,xc,yc,scale = 0.0; 23 DrawButton button; 24 25 PetscFunctionBegin; 26 ierr = ViewerDrawGetDraw(viewer,0,&draw); CHKERRQ(ierr); 27 ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 28 ierr = DrawSynchronizedClear(draw); CHKERRQ(ierr); 29 30 xr = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0; 31 xr += w; yr += h; xl = -w; yl = -h; 32 ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr); 33 34 /* loop over colors */ 35 for (i=0; i<fd->ncolors; i++ ) { 36 for ( j=0; j<fd->nrows[i]; j++ ) { 37 y = fd->M - fd->rows[i][j] - fd->rstart; 38 x = fd->columnsforrow[i][j]; 39 ierr = DrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1); CHKERRQ(ierr); 40 } 41 } 42 ierr = DrawSynchronizedFlush(draw); CHKERRQ(ierr); 43 ierr = DrawGetPause(draw,&pause); CHKERRQ(ierr); 44 if (pause >= 0) { PetscSleep(pause); PetscFunctionReturn(0);} 45 ierr = DrawCheckResizedWindow(draw); CHKERRQ(ierr); 46 ierr = DrawSynchronizedGetMouseButton(draw,&button,&xc,&yc,0,0); CHKERRQ(ierr); 47 while (button != BUTTON_RIGHT) { 48 ierr = DrawSynchronizedClear(draw); CHKERRQ(ierr); 49 if (button == BUTTON_LEFT) scale = .5; 50 else if (button == BUTTON_CENTER) scale = 2.; 51 xl = scale*(xl + w - xc) + xc - w*scale; 52 xr = scale*(xr - w - xc) + xc + w*scale; 53 yl = scale*(yl + h - yc) + yc - h*scale; 54 yr = scale*(yr - h - yc) + yc + h*scale; 55 w *= scale; h *= scale; 56 ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr); 57 /* loop over colors */ 58 for (i=0; i<fd->ncolors; i++ ) { 59 for ( j=0; j<fd->nrows[i]; j++ ) { 60 y = fd->M - fd->rows[i][j] - fd->rstart; 61 x = fd->columnsforrow[i][j]; 62 ierr = DrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1); CHKERRQ(ierr); 63 } 64 } 65 ierr = DrawCheckResizedWindow(draw); CHKERRQ(ierr); 66 ierr = DrawSynchronizedGetMouseButton(draw,&button,&xc,&yc,0,0); CHKERRQ(ierr); 67 } 68 69 PetscFunctionReturn(0); 70 } 71 72 #undef __FUNC__ 73 #define __FUNC__ "MatFDColoringView" 74 /*@C 75 MatFDColoringView - Views a finite difference coloring context. 76 77 Collective on MatFDColoring unless Viewer is VIEWER_STDOUT_SELF 78 79 Input Parameters: 80 + c - the coloring context 81 - viewer - visualization context 82 83 Notes: 84 The available visualization contexts include 85 + VIEWER_STDOUT_SELF - standard output (default) 86 . VIEWER_STDOUT_WORLD - synchronized standard 87 output where only the first processor opens 88 the file. All other processors send their 89 data to the first processor to print. 90 - VIEWER_DRAWX_WORLD - graphical display of nonzero structure 91 92 .seealso: MatFDColoringCreate() 93 94 .keywords: Mat, finite differences, coloring, view 95 @*/ 96 int MatFDColoringView(MatFDColoring c,Viewer viewer) 97 { 98 ViewerType vtype; 99 int i,j,format,ierr; 100 FILE *fd; 101 102 PetscFunctionBegin; 103 PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE); 104 if (viewer) {PetscValidHeader(viewer);} 105 else {viewer = VIEWER_STDOUT_SELF;} 106 107 ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 108 if (!PetscStrcmp(vtype,DRAW_VIEWER)) { 109 ierr = MatFDColoringView_Draw(c,viewer); CHKERRQ(ierr); 110 PetscFunctionReturn(0); 111 } else if (!PetscStrcmp(vtype,ASCII_VIEWER)) { 112 ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 113 PetscFPrintf(c->comm,fd,"MatFDColoring Object:\n"); 114 PetscFPrintf(c->comm,fd," Error tolerance=%g\n",c->error_rel); 115 PetscFPrintf(c->comm,fd," Umin=%g\n",c->umin); 116 PetscFPrintf(c->comm,fd," Number of colors=%d\n",c->ncolors); 117 118 ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr); 119 if (format != VIEWER_FORMAT_ASCII_INFO) { 120 for ( i=0; i<c->ncolors; i++ ) { 121 PetscFPrintf(c->comm,fd," Information for color %d\n",i); 122 PetscFPrintf(c->comm,fd," Number of columns %d\n",c->ncolumns[i]); 123 for ( j=0; j<c->ncolumns[i]; j++ ) { 124 PetscFPrintf(c->comm,fd," %d\n",c->columns[i][j]); 125 } 126 PetscFPrintf(c->comm,fd," Number of rows %d\n",c->nrows[i]); 127 for ( j=0; j<c->nrows[i]; j++ ) { 128 PetscFPrintf(c->comm,fd," %d %d \n",c->rows[i][j],c->columnsforrow[i][j]); 129 } 130 } 131 } 132 } else { 133 SETERRQ(1,1,"Viewer type not supported for this object"); 134 } 135 PetscFunctionReturn(0); 136 } 137 138 #undef __FUNC__ 139 #define __FUNC__ "MatFDColoringSetParameters" 140 /*@ 141 MatFDColoringSetParameters - Sets the parameters for the sparse approximation of 142 a Jacobian matrix using finite differences. 143 144 Collective on MatFDColoring 145 146 The Jacobian is estimated with the differencing approximation 147 .vb 148 J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where 149 h = error_rel*u[i] if abs(u[i]) > umin 150 = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i] 151 dx_{i} = (0, ... 1, .... 0) 152 .ve 153 154 Input Parameters: 155 + coloring - the coloring context 156 . error_rel - relative error 157 - umin - minimum allowable u-value magnitude 158 159 .keywords: Mat, finite differences, coloring, set, parameters 160 161 .seealso: MatFDColoringCreate() 162 @*/ 163 int MatFDColoringSetParameters(MatFDColoring matfd,double error,double umin) 164 { 165 PetscFunctionBegin; 166 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 167 168 if (error != PETSC_DEFAULT) matfd->error_rel = error; 169 if (umin != PETSC_DEFAULT) matfd->umin = umin; 170 PetscFunctionReturn(0); 171 } 172 173 #undef __FUNC__ 174 #define __FUNC__ "MatFDColoringSetFrequency" 175 /*@ 176 MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian 177 matrices. 178 179 Collective on MatFDColoring 180 181 Input Parameters: 182 + coloring - the coloring context 183 - freq - frequency (default is 1) 184 185 Notes: 186 Using a modified Newton strategy, where the Jacobian remains fixed for several 187 iterations, can be cost effective in terms of overall nonlinear solution 188 efficiency. This parameter indicates that a new Jacobian will be computed every 189 <freq> nonlinear iterations. 190 191 Options Database Keys: 192 . -mat_fd_coloring_freq <freq> - Sets coloring frequency 193 194 .keywords: Mat, finite differences, coloring, set, frequency 195 196 .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency() 197 @*/ 198 int MatFDColoringSetFrequency(MatFDColoring matfd,int freq) 199 { 200 PetscFunctionBegin; 201 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 202 203 matfd->freq = freq; 204 PetscFunctionReturn(0); 205 } 206 207 #undef __FUNC__ 208 #define __FUNC__ "MatFDColoringGetFrequency" 209 /*@ 210 MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian 211 matrices. 212 213 Not Collective 214 215 Input Parameters: 216 . coloring - the coloring context 217 218 Output Parameters: 219 . freq - frequency (default is 1) 220 221 Notes: 222 Using a modified Newton strategy, where the Jacobian remains fixed for several 223 iterations, can be cost effective in terms of overall nonlinear solution 224 efficiency. This parameter indicates that a new Jacobian will be computed every 225 <freq> nonlinear iterations. 226 227 Options Database Keys: 228 . -mat_fd_coloring_freq <freq> - Sets coloring frequency 229 230 .keywords: Mat, finite differences, coloring, get, frequency 231 232 .seealso: MatFDColoringSetFrequency() 233 @*/ 234 int MatFDColoringGetFrequency(MatFDColoring matfd,int *freq) 235 { 236 PetscFunctionBegin; 237 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 238 239 *freq = matfd->freq; 240 PetscFunctionReturn(0); 241 } 242 243 #undef __FUNC__ 244 #define __FUNC__ "MatFDColoringSetFunction" 245 /*@C 246 MatFDColoringSetFunction - Sets the function to use for computing the Jacobian. 247 248 Collective on MatFDColoring 249 250 Input Parameters: 251 + coloring - the coloring context 252 . f - the function 253 - fctx - the optional user-defined function context 254 255 .keywords: Mat, Jacobian, finite differences, set, function 256 @*/ 257 int MatFDColoringSetFunction(MatFDColoring matfd,int (*f)(void),void *fctx) 258 { 259 PetscFunctionBegin; 260 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 261 262 matfd->f = f; 263 matfd->fctx = fctx; 264 265 PetscFunctionReturn(0); 266 } 267 268 #undef __FUNC__ 269 #define __FUNC__ "MatFDColoringSetFromOptions" 270 /*@ 271 MatFDColoringSetFromOptions - Sets coloring finite difference parameters from 272 the options database. 273 274 Collective on MatFDColoring 275 276 The Jacobian is estimated with the differencing approximation 277 .vb 278 J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where 279 h = error_rel*u[i] if abs(u[i]) > umin 280 = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i] 281 dx_{i} = (0, ... 1, .... 0) 282 .ve 283 284 Input Parameter: 285 . coloring - the coloring context 286 287 Options Database Keys: 288 + -mat_fd_coloring_error <err> - Sets <err> (square root 289 of relative error in the function) 290 . -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude 291 . -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian 292 . -mat_fd_coloring_view - Activates basic viewing 293 . -mat_fd_coloring_view_info - Activates viewing info 294 - -mat_fd_coloring_view_draw - Activates drawing 295 296 .keywords: Mat, finite differences, parameters 297 @*/ 298 int MatFDColoringSetFromOptions(MatFDColoring matfd) 299 { 300 int ierr,flag,freq = 1; 301 double error = PETSC_DEFAULT,umin = PETSC_DEFAULT; 302 303 PetscFunctionBegin; 304 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 305 306 ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_err",&error,&flag);CHKERRQ(ierr); 307 ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_umin",&umin,&flag);CHKERRQ(ierr); 308 ierr = MatFDColoringSetParameters(matfd,error,umin); CHKERRQ(ierr); 309 ierr = OptionsGetInt(matfd->prefix,"-mat_fd_coloring_freq",&freq,&flag);CHKERRQ(ierr); 310 ierr = MatFDColoringSetFrequency(matfd,freq);CHKERRQ(ierr); 311 ierr = OptionsHasName(PETSC_NULL,"-help",&flag); CHKERRQ(ierr); 312 if (flag) { 313 ierr = MatFDColoringPrintHelp(matfd); CHKERRQ(ierr); 314 } 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNC__ 319 #define __FUNC__ "MatFDColoringPrintHelp" 320 /*@ 321 MatFDColoringPrintHelp - Prints help message for matrix finite difference calculations 322 using coloring. 323 324 Collective on MatFDColoring 325 326 Input Parameter: 327 . fdcoloring - the MatFDColoring context 328 329 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringSetFromOptions() 330 @*/ 331 int MatFDColoringPrintHelp(MatFDColoring fd) 332 { 333 PetscFunctionBegin; 334 PetscValidHeaderSpecific(fd,MAT_FDCOLORING_COOKIE); 335 336 (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_err <err>: set sqrt rel tol in function, defaults to %g\n",fd->error_rel); 337 (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_umin <umin>: see users manual, defaults to %d\n",fd->umin); 338 (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_freq <freq>: frequency that Jacobian is recomputed, defaults to %d\n",fd->freq); 339 (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view\n"); 340 (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_draw\n"); 341 (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_info\n"); 342 PetscFunctionReturn(0); 343 } 344 345 int MatFDColoringView_Private(MatFDColoring fd) 346 { 347 int ierr,flg; 348 349 PetscFunctionBegin; 350 ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg); CHKERRQ(ierr); 351 if (flg) { 352 ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm)); CHKERRQ(ierr); 353 } 354 ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg); CHKERRQ(ierr); 355 if (flg) { 356 ierr = ViewerPushFormat(VIEWER_STDOUT_(fd->comm),VIEWER_FORMAT_ASCII_INFO,PETSC_NULL);CHKERRQ(ierr); 357 ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm)); CHKERRQ(ierr); 358 ierr = ViewerPopFormat(VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr); 359 } 360 ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg); CHKERRQ(ierr); 361 if (flg) { 362 ierr = MatFDColoringView(fd,VIEWER_DRAWX_(fd->comm)); CHKERRQ(ierr); 363 ierr = ViewerFlush(VIEWER_DRAWX_(fd->comm)); CHKERRQ(ierr); 364 } 365 PetscFunctionReturn(0); 366 } 367 368 #undef __FUNC__ 369 #define __FUNC__ "MatFDColoringCreate" 370 /*@C 371 MatFDColoringCreate - Creates a matrix coloring context for finite difference 372 computation of Jacobians. 373 374 Collective on Mat 375 376 Input Parameters: 377 + mat - the matrix containing the nonzero structure of the Jacobian 378 - iscoloring - the coloring of the matrix 379 380 Output Parameter: 381 . color - the new coloring context 382 383 Options Database Keys: 384 + -mat_fd_coloring_view - Activates basic viewing or coloring 385 . -mat_fd_coloring_view_draw - Activates drawing of coloring 386 - -mat_fd_coloring_view_info - Activates viewing of coloring info 387 388 .seealso: MatFDColoringDestroy() 389 @*/ 390 int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color) 391 { 392 MatFDColoring c; 393 MPI_Comm comm; 394 int ierr,M,N; 395 396 PetscFunctionBegin; 397 ierr = MatGetSize(mat,&M,&N); CHKERRQ(ierr); 398 if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Only for square matrices"); 399 400 PetscObjectGetComm((PetscObject)mat,&comm); 401 PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,comm,MatFDColoringDestroy,MatFDColoringView); 402 PLogObjectCreate(c); 403 404 if (mat->ops->fdcoloringcreate) { 405 ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c); CHKERRQ(ierr); 406 } else { 407 SETERRQ(PETSC_ERR_SUP,0,"Code not yet written for this matrix type"); 408 } 409 410 c->error_rel = 1.e-8; 411 c->umin = 1.e-6; 412 c->freq = 1; 413 414 ierr = MatFDColoringView_Private(c); CHKERRQ(ierr); 415 416 *color = c; 417 418 PetscFunctionReturn(0); 419 } 420 421 #undef __FUNC__ 422 #define __FUNC__ "MatFDColoringDestroy" 423 /*@C 424 MatFDColoringDestroy - Destroys a matrix coloring context that was created 425 via MatFDColoringCreate(). 426 427 Collective on MatFDColoring 428 429 Input Parameter: 430 . c - coloring context 431 432 .seealso: MatFDColoringCreate() 433 @*/ 434 int MatFDColoringDestroy(MatFDColoring c) 435 { 436 int i,ierr; 437 438 PetscFunctionBegin; 439 if (--c->refct > 0) PetscFunctionReturn(0); 440 441 442 for ( i=0; i<c->ncolors; i++ ) { 443 if (c->columns[i]) PetscFree(c->columns[i]); 444 if (c->rows[i]) PetscFree(c->rows[i]); 445 if (c->columnsforrow[i]) PetscFree(c->columnsforrow[i]); 446 } 447 PetscFree(c->ncolumns); 448 PetscFree(c->columns); 449 PetscFree(c->nrows); 450 PetscFree(c->rows); 451 PetscFree(c->columnsforrow); 452 PetscFree(c->scale); 453 if (c->w1) { 454 ierr = VecDestroy(c->w1); CHKERRQ(ierr); 455 ierr = VecDestroy(c->w2); CHKERRQ(ierr); 456 ierr = VecDestroy(c->w3); CHKERRQ(ierr); 457 } 458 PLogObjectDestroy(c); 459 PetscHeaderDestroy(c); 460 PetscFunctionReturn(0); 461 } 462 463 #include "snes.h" 464 465 #undef __FUNC__ 466 #define __FUNC__ "MatFDColoringApply" 467 /*@ 468 MatFDColoringApply - Given a matrix for which a MatFDColoring context 469 has been created, computes the Jacobian for a function via finite differences. 470 471 Collective on MatFDColoring 472 473 Input Parameters: 474 + mat - location to store Jacobian 475 . coloring - coloring context created with MatFDColoringCreate() 476 . x1 - location at which Jacobian is to be computed 477 - sctx - optional context required by function (actually a SNES context) 478 479 Options Database Keys: 480 . -mat_fd_coloring_freq <freq> - Sets coloring frequency 481 482 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView() 483 484 .keywords: coloring, Jacobian, finite differences 485 @*/ 486 int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx) 487 { 488 int k,fg,ierr,N,start,end,l,row,col,srow; 489 Scalar dx, mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale; 490 double epsilon = coloring->error_rel, umin = coloring->umin; 491 MPI_Comm comm = coloring->comm; 492 Vec w1,w2,w3; 493 int (*f)(void *,Vec,Vec,void *) = ( int (*)(void *,Vec,Vec,void *))coloring->f; 494 void *fctx = coloring->fctx; 495 496 PetscFunctionBegin; 497 PetscValidHeaderSpecific(J,MAT_COOKIE); 498 PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE); 499 PetscValidHeaderSpecific(x1,VEC_COOKIE); 500 501 502 if (!coloring->w1) { 503 ierr = VecDuplicate(x1,&coloring->w1); CHKERRQ(ierr); 504 PLogObjectParent(coloring,coloring->w1); 505 ierr = VecDuplicate(x1,&coloring->w2); CHKERRQ(ierr); 506 PLogObjectParent(coloring,coloring->w2); 507 ierr = VecDuplicate(x1,&coloring->w3); CHKERRQ(ierr); 508 PLogObjectParent(coloring,coloring->w3); 509 } 510 w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3; 511 512 ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&fg); CHKERRQ(ierr); 513 if (fg) { 514 PLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n"); 515 } else { 516 ierr = MatZeroEntries(J); CHKERRQ(ierr); 517 } 518 519 ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr); 520 ierr = VecGetSize(x1,&N); CHKERRQ(ierr); 521 ierr = (*f)(sctx,x1,w1,fctx); CHKERRQ(ierr); 522 523 PetscMemzero(wscale,N*sizeof(Scalar)); 524 /* 525 Loop over each color 526 */ 527 528 ierr = VecGetArray(x1,&xx); CHKERRQ(ierr); 529 for (k=0; k<coloring->ncolors; k++) { 530 ierr = VecCopy(x1,w3); CHKERRQ(ierr); 531 /* 532 Loop over each column associated with color adding the 533 perturbation to the vector w3. 534 */ 535 for (l=0; l<coloring->ncolumns[k]; l++) { 536 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 537 dx = xx[col-start]; 538 if (dx == 0.0) dx = 1.0; 539 #if !defined(USE_PETSC_COMPLEX) 540 if (dx < umin && dx >= 0.0) dx = umin; 541 else if (dx < 0.0 && dx > -umin) dx = -umin; 542 #else 543 if (PetscAbsScalar(dx) < umin && PetscReal(dx) >= 0.0) dx = umin; 544 else if (PetscReal(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 545 #endif 546 dx *= epsilon; 547 wscale[col] = 1.0/dx; 548 ierr = VecSetValues(w3,1,&col,&dx,ADD_VALUES);CHKERRQ(ierr); 549 } 550 551 /* 552 Evaluate function at x1 + dx (here dx is a vector of perturbations) 553 */ 554 ierr = (*f)(sctx,w3,w2,fctx); CHKERRQ(ierr); 555 ierr = VecAXPY(&mone,w1,w2); CHKERRQ(ierr); 556 /* Communicate scale to all processors */ 557 #if !defined(USE_PETSC_COMPLEX) 558 ierr = MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr); 559 #else 560 ierr = MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr); 561 #endif 562 /* 563 Loop over rows of vector, putting results into Jacobian matrix 564 */ 565 ierr = VecGetArray(w2,&y);CHKERRQ(ierr); 566 for (l=0; l<coloring->nrows[k]; l++) { 567 row = coloring->rows[k][l]; 568 col = coloring->columnsforrow[k][l]; 569 y[row] *= scale[col]; 570 srow = row + start; 571 ierr = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 572 } 573 ierr = VecRestoreArray(w2,&y); CHKERRQ(ierr); 574 } 575 ierr = VecRestoreArray(x1,&xx);CHKERRQ(ierr); 576 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 577 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 578 PetscFunctionReturn(0); 579 } 580 581 #include "ts.h" 582 583 #undef __FUNC__ 584 #define __FUNC__ "MatFDColoringApplyTS" 585 /*@ 586 MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context 587 has been created, computes the Jacobian for a function via finite differences. 588 589 Collective on Mat, MatFDColoring, and Vec 590 591 Input Parameters: 592 + mat - location to store Jacobian 593 . coloring - coloring context created with MatFDColoringCreate() 594 . x1 - location at which Jacobian is to be computed 595 - sctx - optional context required by function (actually a SNES context) 596 597 Options Database Keys: 598 . -mat_fd_coloring_freq <freq> - Sets coloring frequency 599 600 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView() 601 602 .keywords: coloring, Jacobian, finite differences 603 @*/ 604 int MatFDColoringApplyTS(Mat J,MatFDColoring coloring,double t,Vec x1,MatStructure *flag,void *sctx) 605 { 606 int k,fg,ierr,N,start,end,l,row,col,srow; 607 Scalar dx, mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale; 608 double epsilon = coloring->error_rel, umin = coloring->umin; 609 MPI_Comm comm = coloring->comm; 610 Vec w1,w2,w3; 611 int (*f)(void *,double,Vec,Vec,void *) = ( int (*)(void *,double,Vec,Vec,void *))coloring->f; 612 void *fctx = coloring->fctx; 613 614 PetscFunctionBegin; 615 PetscValidHeaderSpecific(J,MAT_COOKIE); 616 PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE); 617 PetscValidHeaderSpecific(x1,VEC_COOKIE); 618 619 if (!coloring->w1) { 620 ierr = VecDuplicate(x1,&coloring->w1); CHKERRQ(ierr); 621 PLogObjectParent(coloring,coloring->w1); 622 ierr = VecDuplicate(x1,&coloring->w2); CHKERRQ(ierr); 623 PLogObjectParent(coloring,coloring->w2); 624 ierr = VecDuplicate(x1,&coloring->w3); CHKERRQ(ierr); 625 PLogObjectParent(coloring,coloring->w3); 626 } 627 w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3; 628 629 ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&fg); CHKERRQ(ierr); 630 if (fg) { 631 PLogInfo(coloring,"MatFDColoringApplyTS: Not calling MatZeroEntries()\n"); 632 } else { 633 ierr = MatZeroEntries(J); CHKERRQ(ierr); 634 } 635 636 ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr); 637 ierr = VecGetSize(x1,&N); CHKERRQ(ierr); 638 ierr = (*f)(sctx,t,x1,w1,fctx); CHKERRQ(ierr); 639 640 PetscMemzero(wscale,N*sizeof(Scalar)); 641 /* 642 Loop over each color 643 */ 644 645 ierr = VecGetArray(x1,&xx); CHKERRQ(ierr); 646 for (k=0; k<coloring->ncolors; k++) { 647 ierr = VecCopy(x1,w3); CHKERRQ(ierr); 648 /* 649 Loop over each column associated with color adding the 650 perturbation to the vector w3. 651 */ 652 for (l=0; l<coloring->ncolumns[k]; l++) { 653 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 654 dx = xx[col-start]; 655 if (dx == 0.0) dx = 1.0; 656 #if !defined(USE_PETSC_COMPLEX) 657 if (dx < umin && dx >= 0.0) dx = umin; 658 else if (dx < 0.0 && dx > -umin) dx = -umin; 659 #else 660 if (PetscAbsScalar(dx) < umin && PetscReal(dx) >= 0.0) dx = umin; 661 else if (PetscReal(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 662 #endif 663 dx *= epsilon; 664 wscale[col] = 1.0/dx; 665 ierr = VecSetValues(w3,1,&col,&dx,ADD_VALUES); CHKERRQ(ierr); 666 } 667 /* 668 Evaluate function at x1 + dx (here dx is a vector of perturbations) 669 */ 670 ierr = (*f)(sctx,t,w3,w2,fctx); CHKERRQ(ierr); 671 ierr = VecAXPY(&mone,w1,w2); CHKERRQ(ierr); 672 /* Communicate scale to all processors */ 673 #if !defined(USE_PETSC_COMPLEX) 674 ierr = MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr); 675 #else 676 ierr = MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr); 677 #endif 678 /* 679 Loop over rows of vector, putting results into Jacobian matrix 680 */ 681 ierr = VecGetArray(w2,&y); CHKERRQ(ierr); 682 for (l=0; l<coloring->nrows[k]; l++) { 683 row = coloring->rows[k][l]; 684 col = coloring->columnsforrow[k][l]; 685 y[row] *= scale[col]; 686 srow = row + start; 687 ierr = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 688 } 689 ierr = VecRestoreArray(w2,&y); CHKERRQ(ierr); 690 } 691 ierr = VecRestoreArray(x1,&xx); CHKERRQ(ierr); 692 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 693 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); 694 PetscFunctionReturn(0); 695 } 696 697 698 699