1 /*$Id: fdmatrix.c,v 1.92 2001/08/21 21:03:06 bsmith Exp $*/ 2 3 /* 4 This is where the abstract matrix operations are defined that are 5 used for finite difference computations of Jacobians using coloring. 6 */ 7 8 #include "src/mat/matimpl.h" /*I "petscmat.h" I*/ 9 10 /* Logging support */ 11 int MAT_FDCOLORING_COOKIE; 12 13 #undef __FUNCT__ 14 #define __FUNCT__ "MatFDColoringSetF" 15 int MatFDColoringSetF(MatFDColoring fd,Vec F) 16 { 17 PetscFunctionBegin; 18 fd->F = F; 19 PetscFunctionReturn(0); 20 } 21 22 #undef __FUNCT__ 23 #define __FUNCT__ "MatFDColoringView_Draw_Zoom" 24 static int MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa) 25 { 26 MatFDColoring fd = (MatFDColoring)Aa; 27 int ierr,i,j; 28 PetscReal x,y; 29 30 PetscFunctionBegin; 31 32 /* loop over colors */ 33 for (i=0; i<fd->ncolors; i++) { 34 for (j=0; j<fd->nrows[i]; j++) { 35 y = fd->M - fd->rows[i][j] - fd->rstart; 36 x = fd->columnsforrow[i][j]; 37 ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr); 38 } 39 } 40 PetscFunctionReturn(0); 41 } 42 43 #undef __FUNCT__ 44 #define __FUNCT__ "MatFDColoringView_Draw" 45 static int MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer) 46 { 47 int ierr; 48 PetscTruth isnull; 49 PetscDraw draw; 50 PetscReal xr,yr,xl,yl,h,w; 51 52 PetscFunctionBegin; 53 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 54 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 55 56 ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 57 58 xr = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0; 59 xr += w; yr += h; xl = -w; yl = -h; 60 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 61 ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr); 62 ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 63 PetscFunctionReturn(0); 64 } 65 66 #undef __FUNCT__ 67 #define __FUNCT__ "MatFDColoringView" 68 /*@C 69 MatFDColoringView - Views a finite difference coloring context. 70 71 Collective on MatFDColoring 72 73 Input Parameters: 74 + c - the coloring context 75 - viewer - visualization context 76 77 Level: intermediate 78 79 Notes: 80 The available visualization contexts include 81 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 82 . PETSC_VIEWER_STDOUT_WORLD - synchronized standard 83 output where only the first processor opens 84 the file. All other processors send their 85 data to the first processor to print. 86 - PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure 87 88 Notes: 89 Since PETSc uses only a small number of basic colors (currently 33), if the coloring 90 involves more than 33 then some seemingly identical colors are displayed making it look 91 like an illegal coloring. This is just a graphical artifact. 92 93 .seealso: MatFDColoringCreate() 94 95 .keywords: Mat, finite differences, coloring, view 96 @*/ 97 int MatFDColoringView(MatFDColoring c,PetscViewer viewer) 98 { 99 int i,j,ierr; 100 PetscTruth isdraw,isascii; 101 PetscViewerFormat format; 102 103 PetscFunctionBegin; 104 PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE); 105 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(c->comm); 106 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE); 107 PetscCheckSameComm(c,viewer); 108 109 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr); 110 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr); 111 if (isdraw) { 112 ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr); 113 } else if (isascii) { 114 ierr = PetscViewerASCIIPrintf(viewer,"MatFDColoring Object:\n");CHKERRQ(ierr); 115 ierr = PetscViewerASCIIPrintf(viewer," Error tolerance=%g\n",c->error_rel);CHKERRQ(ierr); 116 ierr = PetscViewerASCIIPrintf(viewer," Umin=%g\n",c->umin);CHKERRQ(ierr); 117 ierr = PetscViewerASCIIPrintf(viewer," Number of colors=%d\n",c->ncolors);CHKERRQ(ierr); 118 119 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 120 if (format != PETSC_VIEWER_ASCII_INFO) { 121 for (i=0; i<c->ncolors; i++) { 122 ierr = PetscViewerASCIIPrintf(viewer," Information for color %d\n",i);CHKERRQ(ierr); 123 ierr = PetscViewerASCIIPrintf(viewer," Number of columns %d\n",c->ncolumns[i]);CHKERRQ(ierr); 124 for (j=0; j<c->ncolumns[i]; j++) { 125 ierr = PetscViewerASCIIPrintf(viewer," %d\n",c->columns[i][j]);CHKERRQ(ierr); 126 } 127 ierr = PetscViewerASCIIPrintf(viewer," Number of rows %d\n",c->nrows[i]);CHKERRQ(ierr); 128 for (j=0; j<c->nrows[i]; j++) { 129 ierr = PetscViewerASCIIPrintf(viewer," %d %d \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr); 130 } 131 } 132 } 133 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 134 } else { 135 SETERRQ1(1,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name); 136 } 137 PetscFunctionReturn(0); 138 } 139 140 #undef __FUNCT__ 141 #define __FUNCT__ "MatFDColoringSetParameters" 142 /*@ 143 MatFDColoringSetParameters - Sets the parameters for the sparse approximation of 144 a Jacobian matrix using finite differences. 145 146 Collective on MatFDColoring 147 148 The Jacobian is estimated with the differencing approximation 149 .vb 150 F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where 151 h = error_rel*u[i] if abs(u[i]) > umin 152 = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i] 153 dx_{i} = (0, ... 1, .... 0) 154 .ve 155 156 Input Parameters: 157 + coloring - the coloring context 158 . error_rel - relative error 159 - umin - minimum allowable u-value magnitude 160 161 Level: advanced 162 163 .keywords: Mat, finite differences, coloring, set, parameters 164 165 .seealso: MatFDColoringCreate() 166 @*/ 167 int MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin) 168 { 169 PetscFunctionBegin; 170 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 171 172 if (error != PETSC_DEFAULT) matfd->error_rel = error; 173 if (umin != PETSC_DEFAULT) matfd->umin = umin; 174 PetscFunctionReturn(0); 175 } 176 177 #undef __FUNCT__ 178 #define __FUNCT__ "MatFDColoringSetFrequency" 179 /*@ 180 MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian 181 matrices. 182 183 Collective on MatFDColoring 184 185 Input Parameters: 186 + coloring - the coloring context 187 - freq - frequency (default is 1) 188 189 Options Database Keys: 190 . -mat_fd_coloring_freq <freq> - Sets coloring frequency 191 192 Level: advanced 193 194 Notes: 195 Using a modified Newton strategy, where the Jacobian remains fixed for several 196 iterations, can be cost effective in terms of overall nonlinear solution 197 efficiency. This parameter indicates that a new Jacobian will be computed every 198 <freq> nonlinear iterations. 199 200 .keywords: Mat, finite differences, coloring, set, frequency 201 202 .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency(), MatFDColoringSetRecompute() 203 @*/ 204 int MatFDColoringSetFrequency(MatFDColoring matfd,int freq) 205 { 206 PetscFunctionBegin; 207 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 208 209 matfd->freq = freq; 210 PetscFunctionReturn(0); 211 } 212 213 #undef __FUNCT__ 214 #define __FUNCT__ "MatFDColoringGetFrequency" 215 /*@ 216 MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian 217 matrices. 218 219 Not Collective 220 221 Input Parameters: 222 . coloring - the coloring context 223 224 Output Parameters: 225 . freq - frequency (default is 1) 226 227 Options Database Keys: 228 . -mat_fd_coloring_freq <freq> - Sets coloring frequency 229 230 Level: advanced 231 232 Notes: 233 Using a modified Newton strategy, where the Jacobian remains fixed for several 234 iterations, can be cost effective in terms of overall nonlinear solution 235 efficiency. This parameter indicates that a new Jacobian will be computed every 236 <freq> nonlinear iterations. 237 238 .keywords: Mat, finite differences, coloring, get, frequency 239 240 .seealso: MatFDColoringSetFrequency() 241 @*/ 242 int MatFDColoringGetFrequency(MatFDColoring matfd,int *freq) 243 { 244 PetscFunctionBegin; 245 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 246 247 *freq = matfd->freq; 248 PetscFunctionReturn(0); 249 } 250 251 #undef __FUNCT__ 252 #define __FUNCT__ "MatFDColoringSetFunction" 253 /*@C 254 MatFDColoringSetFunction - Sets the function to use for computing the Jacobian. 255 256 Collective on MatFDColoring 257 258 Input Parameters: 259 + coloring - the coloring context 260 . f - the function 261 - fctx - the optional user-defined function context 262 263 Level: intermediate 264 265 Notes: 266 In Fortran you must call MatFDColoringSetFunctionSNES() for a coloring object to 267 be used with the SNES solvers and MatFDColoringSetFunctionTS() if it is to be used 268 with the TS solvers. 269 270 .keywords: Mat, Jacobian, finite differences, set, function 271 @*/ 272 int MatFDColoringSetFunction(MatFDColoring matfd,int (*f)(void),void *fctx) 273 { 274 PetscFunctionBegin; 275 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 276 277 matfd->f = f; 278 matfd->fctx = fctx; 279 280 PetscFunctionReturn(0); 281 } 282 283 #undef __FUNCT__ 284 #define __FUNCT__ "MatFDColoringSetFromOptions" 285 /*@ 286 MatFDColoringSetFromOptions - Sets coloring finite difference parameters from 287 the options database. 288 289 Collective on MatFDColoring 290 291 The Jacobian, F'(u), is estimated with the differencing approximation 292 .vb 293 F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where 294 h = error_rel*u[i] if abs(u[i]) > umin 295 = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i] 296 dx_{i} = (0, ... 1, .... 0) 297 .ve 298 299 Input Parameter: 300 . coloring - the coloring context 301 302 Options Database Keys: 303 + -mat_fd_coloring_err <err> - Sets <err> (square root 304 of relative error in the function) 305 . -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude 306 . -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian 307 . -mat_fd_coloring_view - Activates basic viewing 308 . -mat_fd_coloring_view_info - Activates viewing info 309 - -mat_fd_coloring_view_draw - Activates drawing 310 311 Level: intermediate 312 313 .keywords: Mat, finite differences, parameters 314 315 .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters() 316 317 @*/ 318 int MatFDColoringSetFromOptions(MatFDColoring matfd) 319 { 320 int ierr; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE); 324 325 ierr = PetscOptionsBegin(matfd->comm,matfd->prefix,"Jacobian computation via finite differences option","MatFD");CHKERRQ(ierr); 326 ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr); 327 ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr); 328 ierr = PetscOptionsInt("-mat_fd_coloring_freq","How often Jacobian is recomputed","MatFDColoringSetFrequency",matfd->freq,&matfd->freq,0);CHKERRQ(ierr); 329 /* not used here; but so they are presented in the GUI */ 330 ierr = PetscOptionsName("-mat_fd_coloring_view","Print entire datastructure used for Jacobian","None",0);CHKERRQ(ierr); 331 ierr = PetscOptionsName("-mat_fd_coloring_view_info","Print number of colors etc for Jacobian","None",0);CHKERRQ(ierr); 332 ierr = PetscOptionsName("-mat_fd_coloring_view_draw","Plot nonzero structure ofJacobian","None",0);CHKERRQ(ierr); 333 PetscOptionsEnd();CHKERRQ(ierr); 334 PetscFunctionReturn(0); 335 } 336 337 #undef __FUNCT__ 338 #define __FUNCT__ "MatFDColoringView_Private" 339 int MatFDColoringView_Private(MatFDColoring fd) 340 { 341 int ierr; 342 PetscTruth flg; 343 344 PetscFunctionBegin; 345 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg);CHKERRQ(ierr); 346 if (flg) { 347 ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr); 348 } 349 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg);CHKERRQ(ierr); 350 if (flg) { 351 ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(fd->comm),PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); 352 ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr); 353 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr); 354 } 355 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg);CHKERRQ(ierr); 356 if (flg) { 357 ierr = MatFDColoringView(fd,PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr); 358 ierr = PetscViewerFlush(PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr); 359 } 360 PetscFunctionReturn(0); 361 } 362 363 #undef __FUNCT__ 364 #define __FUNCT__ "MatFDColoringCreate" 365 /*@C 366 MatFDColoringCreate - Creates a matrix coloring context for finite difference 367 computation of Jacobians. 368 369 Collective on Mat 370 371 Input Parameters: 372 + mat - the matrix containing the nonzero structure of the Jacobian 373 - iscoloring - the coloring of the matrix 374 375 Output Parameter: 376 . color - the new coloring context 377 378 Level: intermediate 379 380 .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(), 381 MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(), 382 MatFDColoringSetFrequency(), MatFDColoringSetRecompute(), MatFDColoringView(), 383 MatFDColoringSetParameters() 384 @*/ 385 int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color) 386 { 387 MatFDColoring c; 388 MPI_Comm comm; 389 int ierr,M,N; 390 391 PetscFunctionBegin; 392 ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr); 393 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 394 if (M != N) SETERRQ(PETSC_ERR_SUP,"Only for square matrices"); 395 396 ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 397 PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,"MatFDColoring",comm,MatFDColoringDestroy,MatFDColoringView); 398 PetscLogObjectCreate(c); 399 400 if (mat->ops->fdcoloringcreate) { 401 ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr); 402 } else { 403 SETERRQ(PETSC_ERR_SUP,"Code not yet written for this matrix type"); 404 } 405 406 c->error_rel = PETSC_SQRT_MACHINE_EPSILON; 407 c->umin = 100.0*PETSC_SQRT_MACHINE_EPSILON; 408 c->freq = 1; 409 c->usersetsrecompute = PETSC_FALSE; 410 c->recompute = PETSC_FALSE; 411 c->currentcolor = -1; 412 413 *color = c; 414 ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr); 415 PetscFunctionReturn(0); 416 } 417 418 #undef __FUNCT__ 419 #define __FUNCT__ "MatFDColoringDestroy" 420 /*@C 421 MatFDColoringDestroy - Destroys a matrix coloring context that was created 422 via MatFDColoringCreate(). 423 424 Collective on MatFDColoring 425 426 Input Parameter: 427 . c - coloring context 428 429 Level: intermediate 430 431 .seealso: MatFDColoringCreate() 432 @*/ 433 int MatFDColoringDestroy(MatFDColoring c) 434 { 435 int i,ierr; 436 437 PetscFunctionBegin; 438 if (--c->refct > 0) PetscFunctionReturn(0); 439 440 for (i=0; i<c->ncolors; i++) { 441 if (c->columns[i]) {ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);} 442 if (c->rows[i]) {ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);} 443 if (c->columnsforrow[i]) {ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);} 444 if (c->vscaleforrow && c->vscaleforrow[i]) {ierr = PetscFree(c->vscaleforrow[i]);CHKERRQ(ierr);} 445 } 446 ierr = PetscFree(c->ncolumns);CHKERRQ(ierr); 447 ierr = PetscFree(c->columns);CHKERRQ(ierr); 448 ierr = PetscFree(c->nrows);CHKERRQ(ierr); 449 ierr = PetscFree(c->rows);CHKERRQ(ierr); 450 ierr = PetscFree(c->columnsforrow);CHKERRQ(ierr); 451 if (c->vscaleforrow) {ierr = PetscFree(c->vscaleforrow);CHKERRQ(ierr);} 452 if (c->vscale) {ierr = VecDestroy(c->vscale);CHKERRQ(ierr);} 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 PetscLogObjectDestroy(c); 459 PetscHeaderDestroy(c); 460 PetscFunctionReturn(0); 461 } 462 463 #undef __FUNCT__ 464 #define __FUNCT__ "MatFDColoringGetPerturbedColumns" 465 /*@C 466 MatFDColoringGetPerturbedColumns - Returns the indices of the columns that 467 that are currently being perturbed. 468 469 Not Collective 470 471 Input Parameters: 472 . coloring - coloring context created with MatFDColoringCreate() 473 474 Output Parameters: 475 + n - the number of local columns being perturbed 476 - cols - the column indices, in global numbering 477 478 Level: intermediate 479 480 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply() 481 482 .keywords: coloring, Jacobian, finite differences 483 @*/ 484 EXTERN int MatFDColoringGetPerturbedColumns(MatFDColoring coloring,int *n,int **cols) 485 { 486 PetscFunctionBegin; 487 if (coloring->currentcolor >= 0) { 488 *n = coloring->ncolumns[coloring->currentcolor]; 489 *cols = coloring->columns[coloring->currentcolor]; 490 } else { 491 *n = 0; 492 } 493 PetscFunctionReturn(0); 494 } 495 496 #undef __FUNCT__ 497 #define __FUNCT__ "MatFDColoringApply" 498 /*@ 499 MatFDColoringApply - Given a matrix for which a MatFDColoring context 500 has been created, computes the Jacobian for a function via finite differences. 501 502 Collective on MatFDColoring 503 504 Input Parameters: 505 + mat - location to store Jacobian 506 . coloring - coloring context created with MatFDColoringCreate() 507 . x1 - location at which Jacobian is to be computed 508 - sctx - optional context required by function (actually a SNES context) 509 510 Options Database Keys: 511 + -mat_fd_coloring_freq <freq> - Sets coloring frequency 512 . -mat_fd_coloring_view - Activates basic viewing or coloring 513 . -mat_fd_coloring_view_draw - Activates drawing of coloring 514 - -mat_fd_coloring_view_info - Activates viewing of coloring info 515 516 Level: intermediate 517 518 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView() 519 520 .keywords: coloring, Jacobian, finite differences 521 @*/ 522 int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx) 523 { 524 int (*f)(void *,Vec,Vec,void*) = (int (*)(void *,Vec,Vec,void *))coloring->f; 525 int k,ierr,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2; 526 PetscScalar dx,mone = -1.0,*y,*xx,*w3_array; 527 PetscScalar *vscale_array; 528 PetscReal epsilon = coloring->error_rel,umin = coloring->umin; 529 Vec w1,w2,w3; 530 void *fctx = coloring->fctx; 531 PetscTruth flg; 532 533 534 PetscFunctionBegin; 535 PetscValidHeaderSpecific(J,MAT_COOKIE); 536 PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE); 537 PetscValidHeaderSpecific(x1,VEC_COOKIE); 538 539 if (coloring->usersetsrecompute) { 540 if (!coloring->recompute) { 541 *flag = SAME_PRECONDITIONER; 542 PetscLogInfo(J,"MatFDColoringApply:Skipping Jacobian, since user called MatFDColorSetRecompute()\n"); 543 PetscFunctionReturn(0); 544 } else { 545 coloring->recompute = PETSC_FALSE; 546 } 547 } 548 549 ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr); 550 if (J->ops->fdcoloringapply) { 551 ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,flag,sctx);CHKERRQ(ierr); 552 } else { 553 554 if (!coloring->w1) { 555 ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr); 556 PetscLogObjectParent(coloring,coloring->w1); 557 ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr); 558 PetscLogObjectParent(coloring,coloring->w2); 559 ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr); 560 PetscLogObjectParent(coloring,coloring->w3); 561 } 562 w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3; 563 564 ierr = MatSetUnfactored(J);CHKERRQ(ierr); 565 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr); 566 if (flg) { 567 PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n"); 568 } else { 569 ierr = MatZeroEntries(J);CHKERRQ(ierr); 570 } 571 572 ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr); 573 ierr = VecGetSize(x1,&N);CHKERRQ(ierr); 574 575 /* 576 This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets 577 coloring->F for the coarser grids from the finest 578 */ 579 if (coloring->F) { 580 ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr); 581 ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr); 582 if (m1 != m2) { 583 coloring->F = 0; 584 } 585 } 586 587 if (coloring->F) { 588 w1 = coloring->F; /* use already computed value of function */ 589 coloring->F = 0; 590 } else { 591 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 592 ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr); 593 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 594 } 595 596 /* 597 Compute all the scale factors and share with other processors 598 */ 599 ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start; 600 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start; 601 for (k=0; k<coloring->ncolors; k++) { 602 /* 603 Loop over each column associated with color adding the 604 perturbation to the vector w3. 605 */ 606 for (l=0; l<coloring->ncolumns[k]; l++) { 607 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 608 dx = xx[col]; 609 if (dx == 0.0) dx = 1.0; 610 #if !defined(PETSC_USE_COMPLEX) 611 if (dx < umin && dx >= 0.0) dx = umin; 612 else if (dx < 0.0 && dx > -umin) dx = -umin; 613 #else 614 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 615 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 616 #endif 617 dx *= epsilon; 618 vscale_array[col] = 1.0/dx; 619 } 620 } 621 vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 622 ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 623 ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 624 625 /* ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD); 626 ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/ 627 628 if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow; 629 else vscaleforrow = coloring->columnsforrow; 630 631 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 632 /* 633 Loop over each color 634 */ 635 for (k=0; k<coloring->ncolors; k++) { 636 coloring->currentcolor = k; 637 ierr = VecCopy(x1,w3);CHKERRQ(ierr); 638 ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start; 639 /* 640 Loop over each column associated with color adding the 641 perturbation to the vector w3. 642 */ 643 for (l=0; l<coloring->ncolumns[k]; l++) { 644 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 645 dx = xx[col]; 646 if (dx == 0.0) dx = 1.0; 647 #if !defined(PETSC_USE_COMPLEX) 648 if (dx < umin && dx >= 0.0) dx = umin; 649 else if (dx < 0.0 && dx > -umin) dx = -umin; 650 #else 651 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 652 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 653 #endif 654 dx *= epsilon; 655 if (!PetscAbsScalar(dx)) SETERRQ(1,"Computed 0 differencing parameter"); 656 w3_array[col] += dx; 657 } 658 w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr); 659 660 /* 661 Evaluate function at x1 + dx (here dx is a vector of perturbations) 662 */ 663 664 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 665 ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr); 666 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 667 ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr); 668 669 /* 670 Loop over rows of vector, putting results into Jacobian matrix 671 */ 672 ierr = VecGetArray(w2,&y);CHKERRQ(ierr); 673 for (l=0; l<coloring->nrows[k]; l++) { 674 row = coloring->rows[k][l]; 675 col = coloring->columnsforrow[k][l]; 676 y[row] *= vscale_array[vscaleforrow[k][l]]; 677 srow = row + start; 678 ierr = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 679 } 680 ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr); 681 } 682 coloring->currentcolor = -1; 683 ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 684 xx = xx + start; ierr = VecRestoreArray(x1,&xx);CHKERRQ(ierr); 685 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 686 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 687 } 688 ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr); 689 690 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test",&flg);CHKERRQ(ierr); 691 if (flg) { 692 ierr = MatNullSpaceTest(J->nullsp,J);CHKERRQ(ierr); 693 } 694 ierr = MatFDColoringView_Private(coloring);CHKERRQ(ierr); 695 696 PetscFunctionReturn(0); 697 } 698 699 #undef __FUNCT__ 700 #define __FUNCT__ "MatFDColoringApplyTS" 701 /*@ 702 MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context 703 has been created, computes the Jacobian for a function via finite differences. 704 705 Collective on Mat, MatFDColoring, and Vec 706 707 Input Parameters: 708 + mat - location to store Jacobian 709 . coloring - coloring context created with MatFDColoringCreate() 710 . x1 - location at which Jacobian is to be computed 711 - sctx - optional context required by function (actually a SNES context) 712 713 Options Database Keys: 714 . -mat_fd_coloring_freq <freq> - Sets coloring frequency 715 716 Level: intermediate 717 718 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView() 719 720 .keywords: coloring, Jacobian, finite differences 721 @*/ 722 int MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx) 723 { 724 int (*f)(void *,PetscReal,Vec,Vec,void*)=(int (*)(void *,PetscReal,Vec,Vec,void *))coloring->f; 725 int k,ierr,N,start,end,l,row,col,srow,**vscaleforrow; 726 PetscScalar dx,mone = -1.0,*y,*xx,*w3_array; 727 PetscScalar *vscale_array; 728 PetscReal epsilon = coloring->error_rel,umin = coloring->umin; 729 Vec w1,w2,w3; 730 void *fctx = coloring->fctx; 731 PetscTruth flg; 732 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(J,MAT_COOKIE); 735 PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE); 736 PetscValidHeaderSpecific(x1,VEC_COOKIE); 737 738 ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr); 739 if (!coloring->w1) { 740 ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr); 741 PetscLogObjectParent(coloring,coloring->w1); 742 ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr); 743 PetscLogObjectParent(coloring,coloring->w2); 744 ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr); 745 PetscLogObjectParent(coloring,coloring->w3); 746 } 747 w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3; 748 749 ierr = MatSetUnfactored(J);CHKERRQ(ierr); 750 ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr); 751 if (flg) { 752 PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n"); 753 } else { 754 ierr = MatZeroEntries(J);CHKERRQ(ierr); 755 } 756 757 ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr); 758 ierr = VecGetSize(x1,&N);CHKERRQ(ierr); 759 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 760 ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr); 761 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 762 763 /* 764 Compute all the scale factors and share with other processors 765 */ 766 ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start; 767 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start; 768 for (k=0; k<coloring->ncolors; k++) { 769 /* 770 Loop over each column associated with color adding the 771 perturbation to the vector w3. 772 */ 773 for (l=0; l<coloring->ncolumns[k]; l++) { 774 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 775 dx = xx[col]; 776 if (dx == 0.0) dx = 1.0; 777 #if !defined(PETSC_USE_COMPLEX) 778 if (dx < umin && dx >= 0.0) dx = umin; 779 else if (dx < 0.0 && dx > -umin) dx = -umin; 780 #else 781 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 782 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 783 #endif 784 dx *= epsilon; 785 vscale_array[col] = 1.0/dx; 786 } 787 } 788 vscale_array = vscale_array - start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 789 ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 790 ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 791 792 if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow; 793 else vscaleforrow = coloring->columnsforrow; 794 795 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 796 /* 797 Loop over each color 798 */ 799 for (k=0; k<coloring->ncolors; k++) { 800 ierr = VecCopy(x1,w3);CHKERRQ(ierr); 801 ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start; 802 /* 803 Loop over each column associated with color adding the 804 perturbation to the vector w3. 805 */ 806 for (l=0; l<coloring->ncolumns[k]; l++) { 807 col = coloring->columns[k][l]; /* column of the matrix we are probing for */ 808 dx = xx[col]; 809 if (dx == 0.0) dx = 1.0; 810 #if !defined(PETSC_USE_COMPLEX) 811 if (dx < umin && dx >= 0.0) dx = umin; 812 else if (dx < 0.0 && dx > -umin) dx = -umin; 813 #else 814 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 815 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 816 #endif 817 dx *= epsilon; 818 w3_array[col] += dx; 819 } 820 w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr); 821 822 /* 823 Evaluate function at x1 + dx (here dx is a vector of perturbations) 824 */ 825 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 826 ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr); 827 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 828 ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr); 829 830 /* 831 Loop over rows of vector, putting results into Jacobian matrix 832 */ 833 ierr = VecGetArray(w2,&y);CHKERRQ(ierr); 834 for (l=0; l<coloring->nrows[k]; l++) { 835 row = coloring->rows[k][l]; 836 col = coloring->columnsforrow[k][l]; 837 y[row] *= vscale_array[vscaleforrow[k][l]]; 838 srow = row + start; 839 ierr = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 840 } 841 ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr); 842 } 843 ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 844 xx = xx + start; ierr = VecRestoreArray(x1,&xx);CHKERRQ(ierr); 845 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 846 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 847 ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr); 848 PetscFunctionReturn(0); 849 } 850 851 852 #undef __FUNCT__ 853 #define __FUNCT__ "MatFDColoringSetRecompute()" 854 /*@C 855 MatFDColoringSetRecompute - Indicates that the next time a Jacobian preconditioner 856 is needed it sholuld be recomputed. Once this is called and the new Jacobian is computed 857 no additional Jacobian's will be computed (the same one will be used) until this is 858 called again. 859 860 Collective on MatFDColoring 861 862 Input Parameters: 863 . c - the coloring context 864 865 Level: intermediate 866 867 Notes: The MatFDColoringSetFrequency() is ignored once this is called 868 869 .seealso: MatFDColoringCreate(), MatFDColoringSetFrequency() 870 871 .keywords: Mat, finite differences, coloring 872 @*/ 873 int MatFDColoringSetRecompute(MatFDColoring c) 874 { 875 PetscFunctionBegin; 876 PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE); 877 c->usersetsrecompute = PETSC_TRUE; 878 c->recompute = PETSC_TRUE; 879 PetscFunctionReturn(0); 880 } 881 882 883