Actual source code: util2.c
petsc-3.3-p7 2013-05-11
2: /*
3: This file contains utility routines for finite difference
4: approximation of Jacobian matrices. This functionality for
5: the TS component will eventually be incorporated as part of
6: the base PETSc libraries.
7: */
8: #include <petsc-private/tsimpl.h>
9: #include <petsc-private/snesimpl.h>
10: #include <petsc-private/fortranimpl.h>
12: PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*);
13: PetscErrorCode RHSJacobianFD(TS,PetscReal,Vec,Mat*,Mat*,MatStructure *,void*);
15: /* -------------------------------------------------------------------*/
17: /* Temporary interface routine; this will be eliminated soon! */
18: #ifdef PETSC_HAVE_FORTRAN_CAPS
19: #define setcroutinefromfortran_ SETCROUTINEFROMFORTRAN
20: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
21: #define setcroutinefromfortran_ setcroutinefromfortran
22: #endif
24: EXTERN_C_BEGIN
26: void PETSC_STDCALL setcroutinefromfortran_(TS *ts,Mat *A,Mat *B,PetscErrorCode *__ierr)
27: {
28: *__TSSetRHSJacobian(*ts,*A,*B,RHSJacobianFD,PETSC_NULL);
29: }
31: EXTERN_C_END
34: /* -------------------------------------------------------------------*/
35: /*
36: RHSJacobianFD - Computes the Jacobian using finite differences.
38: Input Parameters:
39: . ts - TS context
40: . xx1 - compute Jacobian at this point
41: . ctx - application's function context, as set with SNESSetFunction()
43: Output Parameters:
44: . J - Jacobian
45: . B - preconditioner, same as Jacobian
46: . flag - matrix flag
48: Notes:
49: This routine is slow and expensive, and is not currently optimized
50: to take advantage of sparsity in the problem.
52: Sparse approximations using colorings are also available and
53: would be a much better alternative!
54: */
55: PetscErrorCode RHSJacobianFD(TS ts,PetscReal t,Vec xx1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
56: {
57: Vec jj1,jj2,xx2;
58: PetscInt i,N,start,end,j;
60: PetscScalar dx,*y,scale,*xx,wscale;
61: PetscReal amax,epsilon = 1.e-8; /* assumes PetscReal precision */
62: PetscReal dx_min = 1.e-16,dx_par = 1.e-1;
63: MPI_Comm comm;
64: PetscBool assembled;
66: VecDuplicate(xx1,&jj1);
67: VecDuplicate(xx1,&jj2);
68: VecDuplicate(xx1,&xx2);
70: PetscObjectGetComm((PetscObject)xx1,&comm);
71: MatAssembled(*J,&assembled);
72: if (assembled) {
73: MatZeroEntries(*J);
74: }
76: VecGetSize(xx1,&N);
77: VecGetOwnershipRange(xx1,&start,&end);
78: TSComputeRHSFunction(ts,t,xx1,jj1);
80: /* Compute Jacobian approximation, 1 column at a time.
81: xx1 = current iterate, jj1 = F(xx1)
82: xx2 = perturbed iterate, jj2 = F(xx2)
83: */
84: VecGetArray(xx1,&xx);
85: for (i=0; i<N; i++) {
86: VecCopy(xx1,xx2);
87: if (i>= start && i<end) {
88: dx = xx[i-start];
89: #if !defined(PETSC_USE_COMPLEX)
90: if (dx < dx_min && dx >= 0.0) dx = dx_par;
91: else if (dx < 0.0 && dx > -dx_min) dx = -dx_par;
92: #else
93: if (PetscAbsScalar(dx) < dx_min && PetscRealPart(dx) >= 0.0) dx = dx_par;
94: else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < dx_min) dx = -dx_par;
95: #endif
96: dx *= epsilon;
97: wscale = 1.0/dx;
98: VecSetValues(xx2,1,&i,&dx,ADD_VALUES);
99: } else {
100: wscale = 0.0;
101: }
102: TSComputeRHSFunction(ts,t,xx2,jj2);
103: VecAXPY(jj2,-1.0,jj1);
104: /* Communicate scale to all processors */
105: MPI_Allreduce(&wscale,&scale,1,MPIU_SCALAR,MPIU_SUM,comm);
106: VecScale(jj2,scale);
107: VecGetArray(jj2,&y);
108: VecNorm(jj2,NORM_INFINITY,&amax);
109: amax *= 1.e-14;
110: for (j=start; j<end; j++) {
111: if (PetscAbsScalar(y[j-start]) > amax) {
112: MatSetValues(*J,1,&j,1,&i,y+j-start,INSERT_VALUES);
113: }
114: }
115: VecRestoreArray(jj2,&y);
116: }
118: VecRestoreArray(xx1,&xx);
119: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
120: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
121: *flag = DIFFERENT_NONZERO_PATTERN;
123: VecDestroy(&jj1);
124: VecDestroy(&jj2);
125: VecDestroy(&xx2);
127: return 0;
128: }