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) {
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: }