xref: /petsc/src/mat/matfd/fdmatrix.c (revision a591b6b46e402c1add0ff48140b824bb2ba2b2fc)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: fdmatrix.c,v 1.16 1997/09/25 22:39:43 curfman Exp curfman $";
3 #endif
4 
5 /*
6    This is where the abstract matrix operations are defined that are
7   used for finite difference computations of Jacobians using coloring.
8 */
9 
10 #include "petsc.h"
11 #include "src/mat/matimpl.h"        /*I "mat.h" I*/
12 #include "src/vec/vecimpl.h"
13 #include "pinclude/pviewer.h"
14 
15 #undef __FUNC__
16 #define __FUNC__ "MatFDColoringView_Draw"
17 static int MatFDColoringView_Draw(MatFDColoring fd,Viewer viewer)
18 {
19   int         ierr,i,j,pause;
20   PetscTruth  isnull;
21   Draw        draw;
22   double      xr,yr,xl,yl,h,w,x,y,xc,yc,scale = 0.0;
23   DrawButton  button;
24 
25   ierr = ViewerDrawGetDraw(viewer,&draw); CHKERRQ(ierr);
26   ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) return 0;
27   ierr = DrawSyncClear(draw); CHKERRQ(ierr);
28 
29   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
30   xr += w;    yr += h;  xl = -w;     yl = -h;
31   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
32 
33   /* loop over colors  */
34   for (i=0; i<fd->ncolors; i++ ) {
35     for ( j=0; j<fd->nrows[i]; j++ ) {
36       y = fd->M - fd->rows[i][j] - fd->rstart;
37       x = fd->columnsforrow[i][j];
38       DrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);
39     }
40   }
41   ierr = DrawSyncFlush(draw); CHKERRQ(ierr);
42   ierr = DrawGetPause(draw,&pause); CHKERRQ(ierr);
43   if (pause >= 0) { PetscSleep(pause); return 0;}
44   ierr = DrawCheckResizedWindow(draw);
45   ierr = DrawSyncGetMouseButton(draw,&button,&xc,&yc,0,0);
46   while (button != BUTTON_RIGHT) {
47     ierr = DrawSyncClear(draw); CHKERRQ(ierr);
48     if (button == BUTTON_LEFT) scale = .5;
49     else if (button == BUTTON_CENTER) scale = 2.;
50     xl = scale*(xl + w - xc) + xc - w*scale;
51     xr = scale*(xr - w - xc) + xc + w*scale;
52     yl = scale*(yl + h - yc) + yc - h*scale;
53     yr = scale*(yr - h - yc) + yc + h*scale;
54     w *= scale; h *= scale;
55     ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
56     /* loop over colors  */
57     for (i=0; i<fd->ncolors; i++ ) {
58       for ( j=0; j<fd->nrows[i]; j++ ) {
59         y = fd->M - fd->rows[i][j] - fd->rstart;
60         x = fd->columnsforrow[i][j];
61         DrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);
62       }
63     }
64     ierr = DrawCheckResizedWindow(draw);
65     ierr = DrawSyncGetMouseButton(draw,&button,&xc,&yc,0,0);
66   }
67 
68   return 0;
69 }
70 
71 #undef __FUNC__
72 #define __FUNC__ "MatFDColoringView"
73 /*@C
74    MatFDColoringView - Views a finite difference coloring context.
75 
76    Input  Parameters:
77 .  c - the coloring context
78 .  viewer - visualization context
79 
80    Notes:
81    The available visualization contexts include
82 $     VIEWER_STDOUT_SELF - standard output (default)
83 $     VIEWER_STDOUT_WORLD - synchronized standard
84 $       output where only the first processor opens
85 $       the file.  All other processors send their
86 $       data to the first processor to print.
87 $     VIEWER_DRAWX_WORLD - graphical display of nonzero structure
88 
89 .seealso: MatFDColoringCreate()
90 
91 .keywords: Mat, finite differences, coloring, view
92 @*/
93 int MatFDColoringView(MatFDColoring c,Viewer viewer)
94 {
95   ViewerType vtype;
96   int        i,j,format,ierr;
97   FILE       *fd;
98 
99   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE);
100   if (viewer) {PetscValidHeader(viewer);}
101   else {viewer = VIEWER_STDOUT_SELF;}
102 
103   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
104   if (vtype == DRAW_VIEWER) {
105     ierr = MatFDColoringView_Draw(c,viewer); CHKERRQ(ierr);
106     return 0;
107   }
108   else if (vtype  == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
109     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
110     PetscFPrintf(c->comm,fd,"MatFDColoring Object:\n");
111     PetscFPrintf(c->comm,fd,"  Error tolerance=%g\n",c->error_rel);
112     PetscFPrintf(c->comm,fd,"  Umin=%g\n",c->umin);
113     PetscFPrintf(c->comm,fd,"  Number of colors=%d\n",c->ncolors);
114 
115     ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr);
116     if (format != VIEWER_FORMAT_ASCII_INFO) {
117       for ( i=0; i<c->ncolors; i++ ) {
118         PetscFPrintf(c->comm,fd,"  Information for color %d\n",i);
119         PetscFPrintf(c->comm,fd,"    Number of columns %d\n",c->ncolumns[i]);
120         for ( j=0; j<c->ncolumns[i]; j++ ) {
121           PetscFPrintf(c->comm,fd,"      %d\n",c->columns[i][j]);
122         }
123         PetscFPrintf(c->comm,fd,"    Number of rows %d\n",c->nrows[i]);
124         for ( j=0; j<c->nrows[i]; j++ ) {
125           PetscFPrintf(c->comm,fd,"      %d %d \n",c->rows[i][j],c->columnsforrow[i][j]);
126         }
127       }
128     }
129   }
130   return 0;
131 }
132 
133 #undef __FUNC__
134 #define __FUNC__ "MatFDColoringSetParameters"
135 /*@
136    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
137    a Jacobian matrix using finite differences.
138 
139 $       J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where
140 $        h = error_rel*u[i]                    if  u[i] > umin
141 $          = error_rel*umin                    else
142 $
143 $   dx_{i} = (0, ... 1, .... 0)
144 
145    Input Parameters:
146 .  coloring - the coloring context
147 .  error_rel - relative error
148 .  umin - minimum allowable u-value
149 
150 .keywords: Mat, finite differences, coloring, set, parameters
151 
152 .seealso: MatFDColoringCreate()
153 @*/
154 int MatFDColoringSetParameters(MatFDColoring matfd,double error,double umin)
155 {
156   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
157 
158   if (error != PETSC_DEFAULT) matfd->error_rel = error;
159   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
160   return 0;
161 }
162 
163 #undef __FUNC__
164 #define __FUNC__ "MatFDColoringSetFrequency"
165 /*@
166    MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian
167    matrices.
168 
169    Input Parameters:
170 .  coloring - the coloring context
171 .  freq - frequency (default is 1)
172 
173    Notes:
174    Using a modified Newton strategy, where the Jacobian remains fixed for several
175    iterations, can be cost effective in terms of overall nonlinear solution
176    efficiency.  This parameter indicates that a new Jacobian will be computed every
177    <freq> nonlinear iterations.
178 
179    Options Database Keys:
180 $  -mat_fd_coloring_freq <freq>
181 
182 .keywords: Mat, finite differences, coloring, set, frequency
183 @*/
184 int MatFDColoringSetFrequency(MatFDColoring matfd,int freq)
185 {
186   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
187 
188   matfd->freq = freq;
189   return 0;
190 }
191 
192 #undef __FUNC__
193 #define __FUNC__ "MatFDColoringSetFunction"
194 /*@
195    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
196 
197    Input Parameters:
198 .  coloring - the coloring context
199 .  f - the function
200 .  fctx - the function context
201 
202 .keywords: Mat, Jacobian, finite differences, set, function
203 @*/
204 int MatFDColoringSetFunction(MatFDColoring matfd,int (*f)(void *,Vec,Vec,void *),void *fctx)
205 {
206   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
207 
208   matfd->f    = f;
209   matfd->fctx = fctx;
210 
211   return 0;
212 }
213 
214 #undef __FUNC__
215 #define __FUNC__ "MatFDColoringSetFromOptions"
216 /*@
217    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
218    the options database.
219 
220    The Jacobian is estimated with the differencing approximation
221 $       J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where
222 $        h = error_rel*u[i]                    if  u[i] > umin
223 $          = error_rel*umin                      else
224 $
225 $   dx_{i} = (0, ... 1, .... 0)
226 
227    Input Parameters:
228 .  coloring - the coloring context
229 
230    Options Database Keys:
231 $  -mat_fd_coloring_error <err>, where <err> is the square root
232 $           of relative error in the function
233 $  -mat_fd_coloring_umin  <umin>, where umin is described above
234 $  -mat_fd_coloring_freq <freq> where <freq> is the frequency of
235 $           computing a new Jacobian
236 
237 .keywords: Mat, finite differences, parameters
238 @*/
239 int MatFDColoringSetFromOptions(MatFDColoring matfd)
240 {
241   int    ierr,flag,freq = 1;
242   double error = PETSC_DEFAULT,umin = PETSC_DEFAULT;
243   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
244 
245   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_err",&error,&flag);CHKERRQ(ierr);
246   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_umin",&umin,&flag);CHKERRQ(ierr);
247   ierr = MatFDColoringSetParameters(matfd,error,umin); CHKERRQ(ierr);
248   ierr = OptionsGetInt(matfd->prefix,"-mat_fd_coloring_freq",&freq,&flag);CHKERRQ(ierr);
249   ierr = MatFDColoringSetFrequency(matfd,freq);CHKERRQ(ierr);
250   ierr = OptionsHasName(PETSC_NULL,"-help",&flag); CHKERRQ(ierr);
251   if (flag) {
252     ierr = MatFDColoringPrintHelp(matfd); CHKERRQ(ierr);
253   }
254   return 0;
255 }
256 
257 #undef __FUNC__
258 #define __FUNC__ "MatFDColoringPrintHelp"
259 /*@
260     MatFDColoringPrintHelp - Prints help message for matrix finite difference calculations
261     using coloring.
262 
263     Input Parameter:
264 .   fdcoloring - the MatFDColoring context
265 
266 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringSetFromOptions()
267 @*/
268 int MatFDColoringPrintHelp(MatFDColoring fd)
269 {
270   PetscValidHeaderSpecific(fd,MAT_FDCOLORING_COOKIE);
271 
272   PetscPrintf(fd->comm,"-mat_fd_coloring_err <err>: set sqrt rel tol in function, defaults to %g\n",fd->error_rel);
273   PetscPrintf(fd->comm,"-mat_fd_coloring_umin <umin>: see users manual, defaults to %d\n",fd->umin);
274   PetscPrintf(fd->comm,"-mat_fd_coloring_freq <freq>: frequency that Jacobian is recomputed, defaults to %d\n",fd->freq);
275   PetscPrintf(fd->comm,"-mat_fd_coloring_view\n");
276   PetscPrintf(fd->comm,"-mat_fd_coloring_view_draw\n");
277   PetscPrintf(fd->comm,"-mat_fd_coloring_view_info\n");
278   return 0;
279 }
280 
281 int MatFDColoringView_Private(MatFDColoring fd)
282 {
283   int ierr,flg;
284 
285   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg); CHKERRQ(ierr);
286   if (flg) {
287     Viewer viewer;
288     ierr = ViewerFileOpenASCII(fd->comm,"stdout",&viewer);CHKERRQ(ierr);
289     ierr = MatFDColoringView(fd,viewer); CHKERRQ(ierr);
290     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
291   }
292   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg); CHKERRQ(ierr);
293   if (flg) {
294     Viewer viewer;
295     ierr = ViewerFileOpenASCII(fd->comm,"stdout",&viewer);CHKERRQ(ierr);
296     ierr = ViewerPushFormat(viewer,VIEWER_FORMAT_ASCII_INFO,PETSC_NULL);CHKERRQ(ierr);
297     ierr = MatFDColoringView(fd,viewer); CHKERRQ(ierr);
298     ierr = ViewerPopFormat(viewer);CHKERRQ(ierr);
299     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
300   }
301   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg); CHKERRQ(ierr);
302   if (flg) {
303     ierr = MatFDColoringView(fd,VIEWER_DRAWX_(fd->comm)); CHKERRQ(ierr);
304     ierr = ViewerFlush(VIEWER_DRAWX_(fd->comm)); CHKERRQ(ierr);
305   }
306   return 0;
307 }
308 
309 #undef __FUNC__
310 #define __FUNC__ "MatFDColoringCreate"
311 /*@C
312    MatFDColoringCreate - Creates a matrix coloring context for finite difference
313    computation of Jacobians.
314 
315    Input Parameters:
316 .  mat - the matrix containing the nonzero structure of the Jacobian
317 .  iscoloring - the coloring of the matrix
318 
319     Output Parameter:
320 .   color - the new coloring context
321 
322     Options Database Keys:
323 $    -mat_fd_coloring_view
324 $    -mat_fd_coloring_view_draw
325 $    -mat_fd_coloring_view_info
326 
327 .seealso: MatFDColoringDestroy()
328 @*/
329 int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
330 {
331   MatFDColoring c;
332   MPI_Comm      comm;
333   int           ierr,M,N;
334 
335   ierr = MatGetSize(mat,&M,&N); CHKERRQ(ierr);
336   if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Only for square matrices");
337 
338   PetscObjectGetComm((PetscObject)mat,&comm);
339   PetscHeaderCreate(c,_p_MatFDColoring,MAT_FDCOLORING_COOKIE,0,comm,MatFDColoringDestroy,MatFDColoringView);
340   PLogObjectCreate(c);
341 
342   if (mat->ops.fdcoloringcreate) {
343     ierr = (*mat->ops.fdcoloringcreate)(mat,iscoloring,c); CHKERRQ(ierr);
344   } else {
345     SETERRQ(PETSC_ERR_SUP,0,"Code not yet written for this matrix type");
346   }
347 
348   c->error_rel = 1.e-8;
349   c->umin      = 1.e-6;
350   c->freq      = 1;
351 
352   ierr = MatFDColoringView_Private(c); CHKERRQ(ierr);
353 
354   *color = c;
355 
356   return 0;
357 }
358 
359 #undef __FUNC__
360 #define __FUNC__ "MatFDColoringDestroy"
361 /*@C
362     MatFDColoringDestroy - Destroys a matrix coloring context that was created
363     via MatFDColoringCreate().
364 
365     Input Parameter:
366 .   c - coloring context
367 
368 .seealso: MatFDColoringCreate()
369 @*/
370 int MatFDColoringDestroy(MatFDColoring c)
371 {
372   int i,ierr,flag;
373 
374   if (--c->refct > 0) return 0;
375 
376   ierr = OptionsHasName(PETSC_NULL,"-matfdcoloring_view",&flag);
377   if (flag) {
378     Viewer viewer;
379     ierr = ViewerFileOpenASCII(c->comm,"stdout",&viewer);CHKERRQ(ierr);
380     ierr = MatFDColoringView(c,viewer);CHKERRQ(ierr);
381     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
382   }
383   ierr = OptionsHasName(PETSC_NULL,"-matfdcoloring_view_info",&flag);
384   if (flag) {
385     Viewer viewer;
386     ierr = ViewerFileOpenASCII(c->comm,"stdout",&viewer);CHKERRQ(ierr);
387     ierr = ViewerPushFormat(viewer,VIEWER_FORMAT_ASCII_INFO, PETSC_NULL); CHKERRQ(ierr);
388     ierr = MatFDColoringView(c,viewer);CHKERRQ(ierr);
389     ierr = ViewerPopFormat(viewer);
390     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
391   }
392 
393   for ( i=0; i<c->ncolors; i++ ) {
394     if (c->columns[i])       PetscFree(c->columns[i]);
395     if (c->rows[i])          PetscFree(c->rows[i]);
396     if (c->columnsforrow[i]) PetscFree(c->columnsforrow[i]);
397   }
398   PetscFree(c->ncolumns);
399   PetscFree(c->columns);
400   PetscFree(c->nrows);
401   PetscFree(c->rows);
402   PetscFree(c->columnsforrow);
403   PetscFree(c->scale);
404   if (c->w1) {
405     ierr = VecDestroy(c->w1); CHKERRQ(ierr);
406     ierr = VecDestroy(c->w2); CHKERRQ(ierr);
407     ierr = VecDestroy(c->w3); CHKERRQ(ierr);
408   }
409   PLogObjectDestroy(c);
410   PetscHeaderDestroy(c);
411   return 0;
412 }
413 
414 #include "snes.h"
415 
416 #undef __FUNC__
417 #define __FUNC__ "MatFDColoringApply"
418 /*@
419     MatFDColoringApply - Given a matrix for which a MatFDColoring context
420     has been created, computes the Jacobian for a function via finite differences.
421 
422     Input Parameters:
423 .   mat - location to store Jacobian
424 .   coloring - coloring context created with MatFDColoringCreate()
425 .   x1 - location at which Jacobian is to be computed
426 .   sctx - optional context required by function (actually a SNES context)
427 
428 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
429 
430 .keywords: coloring, Jacobian, finite differences
431 @*/
432 int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
433 {
434   int           k,fg,ierr,N,start,end,l,row,col,srow;
435   Scalar        dx, mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale;
436   double        epsilon = coloring->error_rel, umin = coloring->umin;
437   MPI_Comm      comm = coloring->comm;
438   Vec           w1,w2,w3;
439   int           (*f)(void *,Vec,Vec,void *) = coloring->f;
440   void          *fctx = coloring->fctx;
441 
442   PetscValidHeaderSpecific(J,MAT_COOKIE);
443   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
444   PetscValidHeaderSpecific(x1,VEC_COOKIE);
445 
446   /*
447   ierr = SNESGetIterationNumber((SNES)sctx,&it); CHKERRQ(ierr);
448   if ((freq > 1) && ((it % freq) != 1)) {
449     PLogInfo(coloring,"MatFDColoringApply:Skipping Jacobian, iteration %d, freq %d\n",it,freq);
450     *flag = SAME_PRECONDITIONER;
451     return 0;
452   } else {
453     PLogInfo(coloring,"MatFDColoringApply:Computing Jacobian, iteration %d, freq %d\n",it,freq);
454     *flag = SAME_NONZERO_PATTERN;
455   }*/
456 
457   if (!coloring->w1) {
458     ierr = VecDuplicate(x1,&coloring->w1); CHKERRQ(ierr);
459     PLogObjectParent(coloring,coloring->w1);
460     ierr = VecDuplicate(x1,&coloring->w2); CHKERRQ(ierr);
461     PLogObjectParent(coloring,coloring->w2);
462     ierr = VecDuplicate(x1,&coloring->w3); CHKERRQ(ierr);
463     PLogObjectParent(coloring,coloring->w3);
464   }
465   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
466 
467   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&fg); CHKERRQ(ierr);
468   if (fg) {
469     PLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
470   } else {
471     ierr = MatZeroEntries(J); CHKERRQ(ierr);
472   }
473 
474   ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr);
475   ierr = VecGetSize(x1,&N); CHKERRQ(ierr);
476   ierr = VecGetArray(x1,&xx); CHKERRQ(ierr);
477   ierr = (*f)(sctx,x1,w1,fctx); CHKERRQ(ierr);
478 
479   PetscMemzero(wscale,N*sizeof(Scalar));
480   /*
481       Loop over each color
482   */
483 
484   for (k=0; k<coloring->ncolors; k++) {
485     ierr = VecCopy(x1,w3); CHKERRQ(ierr);
486     /*
487        Loop over each column associated with color adding the
488        perturbation to the vector w3.
489     */
490     for (l=0; l<coloring->ncolumns[k]; l++) {
491       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
492       dx  = xx[col-start];
493       if (dx == 0.0) dx = 1.0;
494 #if !defined(PETSC_COMPLEX)
495       if (dx < umin && dx >= 0.0)      dx = umin;
496       else if (dx < 0.0 && dx > -umin) dx = -umin;
497 #else
498       if (abs(dx) < umin && real(dx) >= 0.0)     dx = umin;
499       else if (real(dx) < 0.0 && abs(dx) < umin) dx = -umin;
500 #endif
501       dx          *= epsilon;
502       wscale[col] = 1.0/dx;
503       VecSetValues(w3,1,&col,&dx,ADD_VALUES);
504     }
505     VecRestoreArray(x1,&xx);
506     /*
507        Evaluate function at x1 + dx (here dx is a vector of perturbations)
508     */
509     ierr = (*f)(sctx,w3,w2,fctx); CHKERRQ(ierr);
510     ierr = VecAXPY(&mone,w1,w2); CHKERRQ(ierr);
511     /* Communicate scale to all processors */
512 #if !defined(PETSC_COMPLEX)
513     MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm);
514 #else
515     MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm);
516 #endif
517     /*
518        Loop over rows of vector, putting results into Jacobian matrix
519     */
520     VecGetArray(w2,&y);
521     for (l=0; l<coloring->nrows[k]; l++) {
522       row    = coloring->rows[k][l];
523       col    = coloring->columnsforrow[k][l];
524       y[row] *= scale[col];
525       srow   = row + start;
526       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
527     }
528     VecRestoreArray(w2,&y);
529   }
530   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
531   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
532   return 0;
533 }
534