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