Actual source code: tsfd.c
1: #define PETSCTS_DLL
3: #include private/matimpl.h
4: #include private/tsimpl.h
8: /*@C
9: TSDefaultComputeJacobianColor - Computes the Jacobian using
10: finite differences and coloring to exploit matrix sparsity.
11:
12: Collective on TS, Vec and Mat
14: Input Parameters:
15: + ts - nonlinear solver object
16: . t - current time
17: . x1 - location at which to evaluate Jacobian
18: - ctx - coloring context, where ctx must have type MatFDColoring,
19: as created via MatFDColoringCreate()
21: Output Parameters:
22: + J - Jacobian matrix (not altered in this routine)
23: . B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
24: - flag - flag indicating whether the matrix sparsity structure has changed
26: Level: intermediate
28: .keywords: TS, finite differences, Jacobian, coloring, sparse
30: .seealso: TSSetJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
31: @*/
32: PetscErrorCode TSDefaultComputeJacobianColor(TS ts,PetscReal t,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
33: {
34: MatFDColoring color = (MatFDColoring) ctx;
38: MatFDColoringApplyTS(*B,color,t,x1,flag,ts);
39:
40: if (*J != *B) {
41: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
42: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
43: }
44: return(0);
45: }
49: /*@C
50: TSDefaultComputeJacobian - Computes the Jacobian using finite differences.
52: Input Parameters:
53: + ts - TS context
54: . xx1 - compute Jacobian at this point
55: - ctx - application's function context, as set with SNESSetFunction()
57: Output Parameters:
58: + J - Jacobian
59: . B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
60: - flag - matrix flag
62: Notes:
63: This routine is slow and expensive, and is not optimized.
65: Sparse approximations using colorings are also available and
66: would be a much better alternative!
68: Level: intermediate
70: .seealso: TSDefaultComputeJacobianColor()
71: @*/
72: PetscErrorCode TSDefaultComputeJacobian(TS ts,PetscReal t,Vec xx1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
73: {
74: Vec f1,f2,xx2;
76: PetscInt i,N,start,end,j;
77: PetscScalar dx,*y,*xx,wscale;
78: PetscReal amax,epsilon = PETSC_SQRT_MACHINE_EPSILON;
79: PetscReal dx_min = 1.e-16,dx_par = 1.e-1;
80: MPI_Comm comm;
81: PetscTruth assembled;
82: PetscMPIInt size;
83: const PetscInt *ranges;
84: PetscMPIInt root;
87: VecDuplicate(xx1,&f1);
88: VecDuplicate(xx1,&f2);
89: VecDuplicate(xx1,&xx2);
91: PetscObjectGetComm((PetscObject)xx1,&comm);
92: MPI_Comm_size(comm,&size);
93: MatAssembled(*B,&assembled);
94: if (assembled) {
95: MatZeroEntries(*B);
96: }
98: VecGetSize(xx1,&N);
99: VecGetOwnershipRange(xx1,&start,&end);
100: TSComputeRHSFunction(ts,ts->ptime,xx1,f1);
102: /* Compute Jacobian approximation, 1 column at a time.
103: xx1 = current iterate, f1 = F(xx1)
104: xx2 = perturbed iterate, f2 = F(xx2)
105: */
106: for (i=0; i<N; i++) {
107: VecCopy(xx1,xx2);
108: if (i>= start && i<end) {
109: VecGetArray(xx1,&xx);
110: dx = xx[i-start];
111: VecRestoreArray(xx1,&xx);
112: #if !defined(PETSC_USE_COMPLEX)
113: if (dx < dx_min && dx >= 0.0) dx = dx_par;
114: else if (dx < 0.0 && dx > -dx_min) dx = -dx_par;
115: #else
116: if (PetscAbsScalar(dx) < dx_min && PetscRealPart(dx) >= 0.0) dx = dx_par;
117: else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < dx_min) dx = -dx_par;
118: #endif
119: dx *= epsilon;
120: wscale = 1.0/dx;
121: VecSetValues(xx2,1,&i,&dx,ADD_VALUES);
122: } else {
123: wscale = 0.0;
124: }
125: TSComputeRHSFunction(ts,t,xx2,f2);
126: VecAXPY(f2,-1.0,f1);
127: /* Communicate scale=1/dx_i to all processors */
128: VecGetOwnershipRanges(xx1,&ranges);
129: root = size;
130: for (j=size-1; j>-1; j--){
131: root--;
132: if (i>=ranges[j]) break;
133: }
134: MPI_Bcast(&wscale,1,MPIU_SCALAR,root,comm);
136: VecScale(f2,wscale);
137: VecNorm(f2,NORM_INFINITY,&amax); amax *= 1.e-14;
138: VecGetArray(f2,&y);
139: for (j=start; j<end; j++) {
140: if (PetscAbsScalar(y[j-start]) > amax || j == i) {
141: MatSetValues(*B,1,&j,1,&i,y+j-start,INSERT_VALUES);
142: }
143: }
144: VecRestoreArray(f2,&y);
145: }
146: MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);
147: MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);
148: if (*B != *J) {
149: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
150: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
151: }
152: *flag = DIFFERENT_NONZERO_PATTERN;
154: VecDestroy(f1);
155: VecDestroy(f2);
156: VecDestroy(xx2);
157: return(0);
158: }