1 2 /* 3 This is where the abstract matrix operations are defined that are 4 used for finite difference computations of Jacobians using coloring. 5 */ 6 7 #include <petsc-private/matimpl.h> /*I "petscmat.h" I*/ 8 9 #undef __FUNCT__ 10 #define __FUNCT__ "MatFDColoringSetF" 11 PetscErrorCode MatFDColoringSetF(MatFDColoring fd,Vec F) 12 { 13 PetscErrorCode ierr; 14 PetscFunctionBegin; 15 if (F) { 16 ierr = VecCopy(F,fd->w1);CHKERRQ(ierr); 17 fd->fset = PETSC_TRUE; 18 } else { 19 fd->fset = PETSC_FALSE; 20 } 21 PetscFunctionReturn(0); 22 } 23 24 #undef __FUNCT__ 25 #define __FUNCT__ "MatFDColoringView_Draw_Zoom" 26 static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa) 27 { 28 MatFDColoring fd = (MatFDColoring)Aa; 29 PetscErrorCode ierr; 30 PetscInt i,j; 31 PetscReal x,y; 32 33 PetscFunctionBegin; 34 35 /* loop over colors */ 36 for (i=0; i<fd->ncolors; i++) { 37 for (j=0; j<fd->nrows[i]; j++) { 38 y = fd->M - fd->rows[i][j] - fd->rstart; 39 x = fd->columnsforrow[i][j]; 40 ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr); 41 } 42 } 43 PetscFunctionReturn(0); 44 } 45 46 #undef __FUNCT__ 47 #define __FUNCT__ "MatFDColoringView_Draw" 48 static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer) 49 { 50 PetscErrorCode ierr; 51 PetscBool isnull; 52 PetscDraw draw; 53 PetscReal xr,yr,xl,yl,h,w; 54 55 PetscFunctionBegin; 56 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 57 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 58 59 ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr); 60 61 xr = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0; 62 xr += w; yr += h; xl = -w; yl = -h; 63 ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr); 64 ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr); 65 ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr); 66 PetscFunctionReturn(0); 67 } 68 69 #undef __FUNCT__ 70 #define __FUNCT__ "MatFDColoringView" 71 /*@C 72 MatFDColoringView - Views a finite difference coloring context. 73 74 Collective on MatFDColoring 75 76 Input Parameters: 77 + c - the coloring context 78 - viewer - visualization context 79 80 Level: intermediate 81 82 Notes: 83 The available visualization contexts include 84 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 85 . PETSC_VIEWER_STDOUT_WORLD - synchronized standard 86 output where only the first processor opens 87 the file. All other processors send their 88 data to the first processor to print. 89 - PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure 90 91 Notes: 92 Since PETSc uses only a small number of basic colors (currently 33), if the coloring 93 involves more than 33 then some seemingly identical colors are displayed making it look 94 like an illegal coloring. This is just a graphical artifact. 95 96 .seealso: MatFDColoringCreate() 97 98 .keywords: Mat, finite differences, coloring, view 99 @*/ 100 PetscErrorCode MatFDColoringView(MatFDColoring c,PetscViewer viewer) 101 { 102 PetscErrorCode ierr; 103 PetscInt i,j; 104 PetscBool isdraw,iascii; 105 PetscViewerFormat format; 106 107 PetscFunctionBegin; 108 PetscValidHeaderSpecific(c,MAT_FDCOLORING_CLASSID,1); 109 if (!viewer) { 110 ierr = PetscViewerASCIIGetStdout(((PetscObject)c)->comm,&viewer);CHKERRQ(ierr); 111 } 112 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 113 PetscCheckSameComm(c,1,viewer,2); 114 115 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 116 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 117 if (isdraw) { 118 ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr); 119 } else if (iascii) { 120 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)c,viewer,"MatFDColoring Object");CHKERRQ(ierr); 121 ierr = PetscViewerASCIIPrintf(viewer," Error tolerance=%G\n",c->error_rel);CHKERRQ(ierr); 122 ierr = PetscViewerASCIIPrintf(viewer," Umin=%G\n",c->umin);CHKERRQ(ierr); 123 ierr = PetscViewerASCIIPrintf(viewer," Number of colors=%D\n",c->ncolors);CHKERRQ(ierr); 124 125 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 126 if (format != PETSC_VIEWER_ASCII_INFO) { 127 for (i=0; i<c->ncolors; i++) { 128 ierr = PetscViewerASCIIPrintf(viewer," Information for color %D\n",i);CHKERRQ(ierr); 129 ierr = PetscViewerASCIIPrintf(viewer," Number of columns %D\n",c->ncolumns[i]);CHKERRQ(ierr); 130 for (j=0; j<c->ncolumns[i]; j++) { 131 ierr = PetscViewerASCIIPrintf(viewer," %D\n",c->columns[i][j]);CHKERRQ(ierr); 132 } 133 ierr = PetscViewerASCIIPrintf(viewer," Number of rows %D\n",c->nrows[i]);CHKERRQ(ierr); 134 for (j=0; j<c->nrows[i]; j++) { 135 ierr = PetscViewerASCIIPrintf(viewer," %D %D \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr); 136 } 137 } 138 } 139 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 140 } else { 141 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name); 142 } 143 PetscFunctionReturn(0); 144 } 145 146 #undef __FUNCT__ 147 #define __FUNCT__ "MatFDColoringSetParameters" 148 /*@ 149 MatFDColoringSetParameters - Sets the parameters for the sparse approximation of 150 a Jacobian matrix using finite differences. 151 152 Logically Collective on MatFDColoring 153 154 The Jacobian is estimated with the differencing approximation 155 .vb 156 F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where 157 h = error_rel*u[i] if abs(u[i]) > umin 158 = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i] 159 dx_{i} = (0, ... 1, .... 0) 160 .ve 161 162 Input Parameters: 163 + coloring - the coloring context 164 . error_rel - relative error 165 - umin - minimum allowable u-value magnitude 166 167 Level: advanced 168 169 .keywords: Mat, finite differences, coloring, set, parameters 170 171 .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions() 172 173 @*/ 174 PetscErrorCode MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin) 175 { 176 PetscFunctionBegin; 177 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1); 178 PetscValidLogicalCollectiveReal(matfd,error,2); 179 PetscValidLogicalCollectiveReal(matfd,umin,3); 180 if (error != PETSC_DEFAULT) matfd->error_rel = error; 181 if (umin != PETSC_DEFAULT) matfd->umin = umin; 182 PetscFunctionReturn(0); 183 } 184 185 186 187 #undef __FUNCT__ 188 #define __FUNCT__ "MatFDColoringGetFunction" 189 /*@C 190 MatFDColoringGetFunction - Gets the function to use for computing the Jacobian. 191 192 Not Collective 193 194 Input Parameters: 195 . coloring - the coloring context 196 197 Output Parameters: 198 + f - the function 199 - fctx - the optional user-defined function context 200 201 Level: intermediate 202 203 .keywords: Mat, Jacobian, finite differences, set, function 204 205 .seealso: MatFDColoringCreate(), MatFDColoringSetFunction(), MatFDColoringSetFromOptions() 206 207 @*/ 208 PetscErrorCode MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx) 209 { 210 PetscFunctionBegin; 211 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1); 212 if (f) *f = matfd->f; 213 if (fctx) *fctx = matfd->fctx; 214 PetscFunctionReturn(0); 215 } 216 217 #undef __FUNCT__ 218 #define __FUNCT__ "MatFDColoringSetFunction" 219 /*@C 220 MatFDColoringSetFunction - Sets the function to use for computing the Jacobian. 221 222 Logically Collective on MatFDColoring 223 224 Input Parameters: 225 + coloring - the coloring context 226 . f - the function 227 - fctx - the optional user-defined function context 228 229 Calling sequence of (*f) function: 230 For SNES: PetscErrorCode (*f)(SNES,Vec,Vec,void*) 231 If not using SNES: PetscErrorCode (*f)(void *dummy,Vec,Vec,void*) and dummy is ignored 232 233 Level: advanced 234 235 Notes: This function is usually used automatically by SNES (when one uses SNESSetJacobian() with the argument 236 SNESDefaultComputeJacobianColor()) and only needs to be used by someone computing a matrix via coloring directly by 237 calling MatFDColoringApply() 238 239 Fortran Notes: 240 In Fortran you must call MatFDColoringSetFunction() for a coloring object to 241 be used without SNES or within the SNES solvers. 242 243 .keywords: Mat, Jacobian, finite differences, set, function 244 245 .seealso: MatFDColoringCreate(), MatFDColoringGetFunction(), MatFDColoringSetFromOptions() 246 247 @*/ 248 PetscErrorCode MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx) 249 { 250 PetscFunctionBegin; 251 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1); 252 matfd->f = f; 253 matfd->fctx = fctx; 254 PetscFunctionReturn(0); 255 } 256 257 #undef __FUNCT__ 258 #define __FUNCT__ "MatFDColoringSetFromOptions" 259 /*@ 260 MatFDColoringSetFromOptions - Sets coloring finite difference parameters from 261 the options database. 262 263 Collective on MatFDColoring 264 265 The Jacobian, F'(u), is estimated with the differencing approximation 266 .vb 267 F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where 268 h = error_rel*u[i] if abs(u[i]) > umin 269 = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i] 270 dx_{i} = (0, ... 1, .... 0) 271 .ve 272 273 Input Parameter: 274 . coloring - the coloring context 275 276 Options Database Keys: 277 + -mat_fd_coloring_err <err> - Sets <err> (square root 278 of relative error in the function) 279 . -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude 280 . -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS) 281 . -mat_fd_coloring_view - Activates basic viewing 282 . -mat_fd_coloring_view ::ascii_info - Activates viewing info 283 - -mat_fd_coloring_view draw - Activates drawing 284 285 Level: intermediate 286 287 .keywords: Mat, finite differences, parameters 288 289 .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters() 290 291 @*/ 292 PetscErrorCode MatFDColoringSetFromOptions(MatFDColoring matfd) 293 { 294 PetscErrorCode ierr; 295 PetscBool flg; 296 char value[3]; 297 298 PetscFunctionBegin; 299 PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1); 300 301 ierr = PetscObjectOptionsBegin((PetscObject)matfd);CHKERRQ(ierr); 302 ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr); 303 ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr); 304 ierr = PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,3,&flg);CHKERRQ(ierr); 305 if (flg) { 306 if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp"; 307 else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds"; 308 else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value); 309 } 310 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 311 ierr = PetscObjectProcessOptionsHandlers((PetscObject)matfd);CHKERRQ(ierr); 312 PetscOptionsEnd();CHKERRQ(ierr); 313 PetscFunctionReturn(0); 314 } 315 316 #undef __FUNCT__ 317 #define __FUNCT__ "MatFDColoringViewFromOptions" 318 PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd,const char optionname[]) 319 { 320 PetscErrorCode ierr; 321 PetscBool flg; 322 PetscViewer viewer; 323 324 PetscFunctionBegin; 325 ierr = PetscOptionsGetViewer(((PetscObject)fd)->comm,((PetscObject)fd)->prefix,optionname,&viewer,&flg);CHKERRQ(ierr); 326 if (flg) { 327 ierr = MatFDColoringView(fd,viewer);CHKERRQ(ierr); 328 ierr = PetscOptionsRestoreViewer(viewer);CHKERRQ(ierr); 329 } 330 PetscFunctionReturn(0); 331 } 332 333 #undef __FUNCT__ 334 #define __FUNCT__ "MatFDColoringCreate" 335 /*@ 336 MatFDColoringCreate - Creates a matrix coloring context for finite difference 337 computation of Jacobians. 338 339 Collective on Mat 340 341 Input Parameters: 342 + mat - the matrix containing the nonzero structure of the Jacobian 343 - iscoloring - the coloring of the matrix; usually obtained with MatGetColoring() or DMCreateColoring() 344 345 Output Parameter: 346 . color - the new coloring context 347 348 Level: intermediate 349 350 .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(), 351 MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(), 352 MatFDColoringView(), MatFDColoringSetParameters(), MatGetColoring(), DMCreateColoring() 353 @*/ 354 PetscErrorCode MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color) 355 { 356 MatFDColoring c; 357 MPI_Comm comm; 358 PetscErrorCode ierr; 359 PetscInt M,N; 360 361 PetscFunctionBegin; 362 ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr); 363 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 364 if (M != N) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Only for square matrices"); 365 ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 366 ierr = PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_CLASSID,0,"MatFDColoring","Jacobian computation via finite differences with coloring","Mat",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr); 367 368 c->ctype = iscoloring->ctype; 369 370 if (mat->ops->fdcoloringcreate) { 371 ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr); 372 } else SETERRQ1(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name); 373 374 ierr = MatGetVecs(mat,PETSC_NULL,&c->w1);CHKERRQ(ierr); 375 ierr = PetscLogObjectParent(c,c->w1);CHKERRQ(ierr); 376 ierr = VecDuplicate(c->w1,&c->w2);CHKERRQ(ierr); 377 ierr = PetscLogObjectParent(c,c->w2);CHKERRQ(ierr); 378 379 c->error_rel = PETSC_SQRT_MACHINE_EPSILON; 380 c->umin = 100.0*PETSC_SQRT_MACHINE_EPSILON; 381 c->currentcolor = -1; 382 c->htype = "wp"; 383 c->fset = PETSC_FALSE; 384 385 *color = c; 386 ierr = PetscObjectCompose((PetscObject)mat,"SNESMatFDColoring",(PetscObject)c);CHKERRQ(ierr); 387 ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr); 388 PetscFunctionReturn(0); 389 } 390 391 #undef __FUNCT__ 392 #define __FUNCT__ "MatFDColoringDestroy" 393 /*@ 394 MatFDColoringDestroy - Destroys a matrix coloring context that was created 395 via MatFDColoringCreate(). 396 397 Collective on MatFDColoring 398 399 Input Parameter: 400 . c - coloring context 401 402 Level: intermediate 403 404 .seealso: MatFDColoringCreate() 405 @*/ 406 PetscErrorCode MatFDColoringDestroy(MatFDColoring *c) 407 { 408 PetscErrorCode ierr; 409 PetscInt i; 410 411 PetscFunctionBegin; 412 if (!*c) PetscFunctionReturn(0); 413 if (--((PetscObject)(*c))->refct > 0) {*c = 0; PetscFunctionReturn(0);} 414 415 for (i=0; i<(*c)->ncolors; i++) { 416 ierr = PetscFree((*c)->columns[i]);CHKERRQ(ierr); 417 ierr = PetscFree((*c)->rows[i]);CHKERRQ(ierr); 418 ierr = PetscFree((*c)->columnsforrow[i]);CHKERRQ(ierr); 419 if ((*c)->vscaleforrow) {ierr = PetscFree((*c)->vscaleforrow[i]);CHKERRQ(ierr);} 420 } 421 ierr = PetscFree((*c)->ncolumns);CHKERRQ(ierr); 422 ierr = PetscFree((*c)->columns);CHKERRQ(ierr); 423 ierr = PetscFree((*c)->nrows);CHKERRQ(ierr); 424 ierr = PetscFree((*c)->rows);CHKERRQ(ierr); 425 ierr = PetscFree((*c)->columnsforrow);CHKERRQ(ierr); 426 ierr = PetscFree((*c)->vscaleforrow);CHKERRQ(ierr); 427 ierr = VecDestroy(&(*c)->vscale);CHKERRQ(ierr); 428 ierr = VecDestroy(&(*c)->w1);CHKERRQ(ierr); 429 ierr = VecDestroy(&(*c)->w2);CHKERRQ(ierr); 430 ierr = VecDestroy(&(*c)->w3);CHKERRQ(ierr); 431 ierr = PetscHeaderDestroy(c);CHKERRQ(ierr); 432 PetscFunctionReturn(0); 433 } 434 435 #undef __FUNCT__ 436 #define __FUNCT__ "MatFDColoringGetPerturbedColumns" 437 /*@C 438 MatFDColoringGetPerturbedColumns - Returns the indices of the columns that 439 that are currently being perturbed. 440 441 Not Collective 442 443 Input Parameters: 444 . coloring - coloring context created with MatFDColoringCreate() 445 446 Output Parameters: 447 + n - the number of local columns being perturbed 448 - cols - the column indices, in global numbering 449 450 Level: intermediate 451 452 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply() 453 454 .keywords: coloring, Jacobian, finite differences 455 @*/ 456 PetscErrorCode MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,PetscInt *cols[]) 457 { 458 PetscFunctionBegin; 459 if (coloring->currentcolor >= 0) { 460 *n = coloring->ncolumns[coloring->currentcolor]; 461 *cols = coloring->columns[coloring->currentcolor]; 462 } else { 463 *n = 0; 464 } 465 PetscFunctionReturn(0); 466 } 467 468 #undef __FUNCT__ 469 #define __FUNCT__ "MatFDColoringApply" 470 /*@ 471 MatFDColoringApply - Given a matrix for which a MatFDColoring context 472 has been created, computes the Jacobian for a function via finite differences. 473 474 Collective on MatFDColoring 475 476 Input Parameters: 477 + mat - location to store Jacobian 478 . coloring - coloring context created with MatFDColoringCreate() 479 . x1 - location at which Jacobian is to be computed 480 - sctx - context required by function, if this is being used with the SNES solver then it is SNES object, otherwise it is null 481 482 Options Database Keys: 483 + -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS) 484 . -mat_fd_coloring_view - Activates basic viewing or coloring 485 . -mat_fd_coloring_view draw - Activates drawing of coloring 486 - -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info 487 488 Level: intermediate 489 490 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction() 491 492 .keywords: coloring, Jacobian, finite differences 493 @*/ 494 PetscErrorCode MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx) 495 { 496 PetscErrorCode ierr; 497 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(J,MAT_CLASSID,1); 500 PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2); 501 PetscValidHeaderSpecific(x1,VEC_CLASSID,3); 502 if (!coloring->f) SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()"); 503 if (!J->ops->fdcoloringapply) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)J)->type_name); 504 ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,flag,sctx);CHKERRQ(ierr); 505 PetscFunctionReturn(0); 506 } 507 508 #undef __FUNCT__ 509 #define __FUNCT__ "MatFDColoringApply_AIJ" 510 PetscErrorCode MatFDColoringApply_AIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx) 511 { 512 PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f; 513 PetscErrorCode ierr; 514 PetscInt k,start,end,l,row,col,srow,**vscaleforrow; 515 PetscScalar dx,*y,*xx,*w3_array; 516 PetscScalar *vscale_array; 517 PetscReal epsilon = coloring->error_rel,umin = coloring->umin,unorm; 518 Vec w1=coloring->w1,w2=coloring->w2,w3; 519 void *fctx = coloring->fctx; 520 PetscBool flg = PETSC_FALSE; 521 PetscInt ctype=coloring->ctype,N,col_start=0,col_end=0; 522 Vec x1_tmp; 523 524 PetscFunctionBegin; 525 PetscValidHeaderSpecific(J,MAT_CLASSID,1); 526 PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2); 527 PetscValidHeaderSpecific(x1,VEC_CLASSID,3); 528 if (!f) SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()"); 529 530 ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr); 531 ierr = MatSetUnfactored(J);CHKERRQ(ierr); 532 ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr); 533 if (flg) { 534 ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr); 535 } else { 536 PetscBool assembled; 537 ierr = MatAssembled(J,&assembled);CHKERRQ(ierr); 538 if (assembled) { 539 ierr = MatZeroEntries(J);CHKERRQ(ierr); 540 } 541 } 542 543 x1_tmp = x1; 544 if (!coloring->vscale){ 545 ierr = VecDuplicate(x1_tmp,&coloring->vscale);CHKERRQ(ierr); 546 } 547 548 if (coloring->htype[0] == 'w') { /* tacky test; need to make systematic if we add other approaches to computing h*/ 549 ierr = VecNorm(x1_tmp,NORM_2,&unorm);CHKERRQ(ierr); 550 } 551 ierr = VecGetOwnershipRange(w1,&start,&end);CHKERRQ(ierr); /* OwnershipRange is used by ghosted x! */ 552 553 /* Set w1 = F(x1) */ 554 if (!coloring->fset) { 555 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 556 ierr = (*f)(sctx,x1_tmp,w1,fctx);CHKERRQ(ierr); 557 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 558 } else { 559 coloring->fset = PETSC_FALSE; 560 } 561 562 if (!coloring->w3) { 563 ierr = VecDuplicate(x1_tmp,&coloring->w3);CHKERRQ(ierr); 564 ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr); 565 } 566 w3 = coloring->w3; 567 568 /* Compute all the local scale factors, including ghost points */ 569 ierr = VecGetLocalSize(x1_tmp,&N);CHKERRQ(ierr); 570 ierr = VecGetArray(x1_tmp,&xx);CHKERRQ(ierr); 571 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 572 if (ctype == IS_COLORING_GHOSTED){ 573 col_start = 0; col_end = N; 574 } else if (ctype == IS_COLORING_GLOBAL){ 575 xx = xx - start; 576 vscale_array = vscale_array - start; 577 col_start = start; col_end = N + start; 578 } 579 for (col=col_start; col<col_end; col++){ 580 /* Loop over each local column, vscale[col] = 1./(epsilon*dx[col]) */ 581 if (coloring->htype[0] == 'w') { 582 dx = 1.0 + unorm; 583 } else { 584 dx = xx[col]; 585 } 586 if (dx == (PetscScalar)0.0) dx = 1.0; 587 #if !defined(PETSC_USE_COMPLEX) 588 if (dx < umin && dx >= 0.0) dx = umin; 589 else if (dx < 0.0 && dx > -umin) dx = -umin; 590 #else 591 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 592 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 593 #endif 594 dx *= epsilon; 595 vscale_array[col] = (PetscScalar)1.0/dx; 596 } 597 if (ctype == IS_COLORING_GLOBAL) vscale_array = vscale_array + start; 598 ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 599 if (ctype == IS_COLORING_GLOBAL){ 600 ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 601 ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 602 } 603 604 if (coloring->vscaleforrow) { 605 vscaleforrow = coloring->vscaleforrow; 606 } else SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_NULL,"Null Object: coloring->vscaleforrow"); 607 608 /* 609 Loop over each color 610 */ 611 ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 612 for (k=0; k<coloring->ncolors; k++) { 613 coloring->currentcolor = k; 614 ierr = VecCopy(x1_tmp,w3);CHKERRQ(ierr); 615 ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr); 616 if (ctype == IS_COLORING_GLOBAL) w3_array = w3_array - start; 617 /* 618 Loop over each column associated with color 619 adding the perturbation to the vector w3. 620 */ 621 for (l=0; l<coloring->ncolumns[k]; l++) { 622 col = coloring->columns[k][l]; /* local column of the matrix we are probing for */ 623 if (coloring->htype[0] == 'w') { 624 dx = 1.0 + unorm; 625 } else { 626 dx = xx[col]; 627 } 628 if (dx == (PetscScalar)0.0) dx = 1.0; 629 #if !defined(PETSC_USE_COMPLEX) 630 if (dx < umin && dx >= 0.0) dx = umin; 631 else if (dx < 0.0 && dx > -umin) dx = -umin; 632 #else 633 if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0) dx = umin; 634 else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin; 635 #endif 636 dx *= epsilon; 637 if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter"); 638 w3_array[col] += dx; 639 } 640 if (ctype == IS_COLORING_GLOBAL) w3_array = w3_array + start; 641 ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr); 642 643 /* 644 Evaluate function at w3 = x1 + dx (here dx is a vector of perturbations) 645 w2 = F(x1 + dx) - F(x1) 646 */ 647 ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 648 ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr); 649 ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr); 650 ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr); 651 652 /* 653 Loop over rows of vector, putting results into Jacobian matrix 654 */ 655 ierr = VecGetArray(w2,&y);CHKERRQ(ierr); 656 for (l=0; l<coloring->nrows[k]; l++) { 657 row = coloring->rows[k][l]; /* local row index */ 658 col = coloring->columnsforrow[k][l]; /* global column index */ 659 y[row] *= vscale_array[vscaleforrow[k][l]]; 660 srow = row + start; 661 ierr = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr); 662 } 663 ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr); 664 } /* endof for each color */ 665 if (ctype == IS_COLORING_GLOBAL) xx = xx + start; 666 ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr); 667 ierr = VecRestoreArray(x1_tmp,&xx);CHKERRQ(ierr); 668 669 coloring->currentcolor = -1; 670 ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 671 ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 672 ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr); 673 674 ierr = MatFDColoringViewFromOptions(coloring,"-mat_fd_coloring_view");CHKERRQ(ierr); 675 PetscFunctionReturn(0); 676 } 677